From e6c591e7a430197777a6456a3cd2db38fffd7647 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Apr 2016 17:35:29 +0200 Subject: [PATCH 001/427] gcov: disable for COMPILE_TEST commit cc622420798c4bcf093785d872525087a7798db9 upstream. Enabling gcov is counterproductive to compile testing: it significantly increases the kernel image size, compile time, and it produces lots of false positive "may be used uninitialized" warnings as the result of missed optimizations. This is in line with how UBSAN_SANITIZE_ALL and PROFILE_ALL_BRANCHES work, both of which have similar problems. With an ARM allmodconfig kernel, I see the build time drop from 283 minutes CPU time to 225 minutes, and the vmlinux size drops from 43MB to 26MB. Signed-off-by: Arnd Bergmann Acked-by: Peter Oberparleiter Signed-off-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- kernel/gcov/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig index c92e44855ddd..1276aabaab55 100644 --- a/kernel/gcov/Kconfig +++ b/kernel/gcov/Kconfig @@ -37,6 +37,7 @@ config ARCH_HAS_GCOV_PROFILE_ALL config GCOV_PROFILE_ALL bool "Profile entire Kernel" + depends on !COMPILE_TEST depends on GCOV_KERNEL depends on ARCH_HAS_GCOV_PROFILE_ALL default n From 20c28c04a6bc2ebd60fa20e5c3a6bf3bfa736d81 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Mon, 8 Jan 2018 16:09:21 -0600 Subject: [PATCH 002/427] x86/cpu/AMD: Make LFENCE a serializing instruction commit e4d0e84e490790798691aaa0f2e598637f1867ec upstream. To aid in speculation control, make LFENCE a serializing instruction since it has less overhead than MFENCE. This is done by setting bit 1 of MSR 0xc0011029 (DE_CFG). Some families that support LFENCE do not have this MSR. For these families, the LFENCE instruction is already serializing. Signed-off-by: Tom Lendacky Signed-off-by: Thomas Gleixner Reviewed-by: Reviewed-by: Borislav Petkov Cc: Peter Zijlstra Cc: Tim Chen Cc: Dave Hansen Cc: Borislav Petkov Cc: Dan Williams Cc: Linus Torvalds Cc: Greg Kroah-Hartman Cc: David Woodhouse Cc: Paul Turner Link: https://lkml.kernel.org/r/20180108220921.12580.71694.stgit@tlendack-t1.amdoffice.net Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr-index.h | 2 ++ arch/x86/kernel/cpu/amd.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 37db36fddc88..f00dfff81370 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -330,6 +330,8 @@ #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL #define FAM10H_MMIO_CONF_BASE_SHIFT 20 #define MSR_FAM10H_NODE_ID 0xc001100c +#define MSR_F10H_DECFG 0xc0011029 +#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT 1 /* K8 MSRs */ #define MSR_K8_TOP_MEM1 0xc001001a diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e2defc7593a4..7f2e9c6ff239 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -746,6 +746,16 @@ static void init_amd(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_K8); if (cpu_has_xmm2) { + /* + * A serializing LFENCE has less overhead than MFENCE, so + * use it for execution serialization. On families which + * don't have that MSR, LFENCE is already serializing. + * msr_set_bit() uses the safe accessors, too, even if the MSR + * is not present. + */ + msr_set_bit(MSR_F10H_DECFG, + MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT); + /* MFENCE stops RDTSC speculation */ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); } From 642ce1bb5ea64b1d036dff04a005d9bbe28ab5b4 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Mon, 8 Jan 2018 16:09:32 -0600 Subject: [PATCH 003/427] x86/cpu/AMD: Use LFENCE_RDTSC in preference to MFENCE_RDTSC commit 9c6a73c75864ad9fa49e5fa6513e4c4071c0e29f upstream. With LFENCE now a serializing instruction, use LFENCE_RDTSC in preference to MFENCE_RDTSC. However, since the kernel could be running under a hypervisor that does not support writing that MSR, read the MSR back and verify that the bit has been set successfully. If the MSR can be read and the bit is set, then set the LFENCE_RDTSC feature, otherwise set the MFENCE_RDTSC feature. Signed-off-by: Tom Lendacky Signed-off-by: Thomas Gleixner Reviewed-by: Reviewed-by: Borislav Petkov Cc: Peter Zijlstra Cc: Tim Chen Cc: Dave Hansen Cc: Borislav Petkov Cc: Dan Williams Cc: Linus Torvalds Cc: Greg Kroah-Hartman Cc: David Woodhouse Cc: Paul Turner Link: https://lkml.kernel.org/r/20180108220932.12580.52458.stgit@tlendack-t1.amdoffice.net Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr-index.h | 1 + arch/x86/kernel/cpu/amd.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index f00dfff81370..b8911aecf035 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -332,6 +332,7 @@ #define MSR_FAM10H_NODE_ID 0xc001100c #define MSR_F10H_DECFG 0xc0011029 #define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT 1 +#define MSR_F10H_DECFG_LFENCE_SERIALIZE BIT_ULL(MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT) /* K8 MSRs */ #define MSR_K8_TOP_MEM1 0xc001001a diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 7f2e9c6ff239..4bf9e77f3e05 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -746,6 +746,9 @@ static void init_amd(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_K8); if (cpu_has_xmm2) { + unsigned long long val; + int ret; + /* * A serializing LFENCE has less overhead than MFENCE, so * use it for execution serialization. On families which @@ -756,8 +759,19 @@ static void init_amd(struct cpuinfo_x86 *c) msr_set_bit(MSR_F10H_DECFG, MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT); - /* MFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + /* + * Verify that the MSR write was successful (could be running + * under a hypervisor) and only then assume that LFENCE is + * serializing. + */ + ret = rdmsrl_safe(MSR_F10H_DECFG, &val); + if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) { + /* A serializing LFENCE stops RDTSC speculation */ + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); + } else { + /* MFENCE stops RDTSC speculation */ + set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + } } /* From 416f66509fce36e128ea2d9e62739a21f1a1d04d Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 17 Sep 2017 09:03:50 -0700 Subject: [PATCH 004/427] x86/mm/32: Move setup_clear_cpu_cap(X86_FEATURE_PCID) earlier commit b8b7abaed7a49b350f8ba659ddc264b04931d581 upstream. Otherwise we might have the PCID feature bit set during cpu_init(). This is just for robustness. I haven't seen any actual bugs here. Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: cba4671af755 ("x86/mm: Disable PCID on 32-bit kernels") Link: http://lkml.kernel.org/r/b16dae9d6b0db5d9801ddbebbfd83384097c61f3.1505663533.git.luto@kernel.org Signed-off-by: Ingo Molnar Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/bugs.c | 8 -------- arch/x86/kernel/cpu/common.c | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index cd46f9039119..cb6b4f9d0b7a 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -22,14 +22,6 @@ void __init check_bugs(void) { -#ifdef CONFIG_X86_32 - /* - * Regardless of whether PCID is enumerated, the SDM says - * that it can't be enabled in 32-bit mode. - */ - setup_clear_cpu_cap(X86_FEATURE_PCID); -#endif - identify_boot_cpu(); if (!IS_ENABLED(CONFIG_SMP)) { diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index dc4dfad66a70..0531c1707b40 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -838,6 +838,14 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) setup_force_cpu_bug(X86_BUG_SPECTRE_V2); fpu__init_system(c); + +#ifdef CONFIG_X86_32 + /* + * Regardless of whether PCID is enumerated, the SDM says + * that it can't be enabled in 32-bit mode. + */ + setup_clear_cpu_cap(X86_FEATURE_PCID); +#endif } void __init early_cpu_init(void) From cfc8c1d61e46fd3c60a34a5b1962eeeb03222a3d Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Fri, 29 Sep 2017 17:15:36 +0300 Subject: [PATCH 005/427] x86/asm: Use register variable to get stack pointer value commit 196bd485ee4f03ce4c690bfcf38138abfcd0a4bc upstream. Currently we use current_stack_pointer() function to get the value of the stack pointer register. Since commit: f5caf621ee35 ("x86/asm: Fix inline asm call constraints for Clang") ... we have a stack register variable declared. It can be used instead of current_stack_pointer() function which allows to optimize away some excessive "mov %rsp, %" instructions: -mov %rsp,%rdx -sub %rdx,%rax -cmp $0x3fff,%rax -ja ffffffff810722fd +sub %rsp,%rax +cmp $0x3fff,%rax +ja ffffffff810722fa Remove current_stack_pointer(), rename __asm_call_sp to current_stack_pointer and use it instead of the removed function. Signed-off-by: Andrey Ryabinin Reviewed-by: Josh Poimboeuf Cc: Andy Lutomirski Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170929141537.29167-1-aryabinin@virtuozzo.com Signed-off-by: Ingo Molnar [dwmw2: We want ASM_CALL_CONSTRAINT for retpoline] Signed-off-by: David Woodhouse Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/asm.h | 11 +++++++++++ arch/x86/include/asm/thread_info.h | 11 ----------- arch/x86/kernel/irq_32.c | 6 +++--- arch/x86/kernel/traps.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index 189679aba703..b9c6c7a6f5a6 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h @@ -105,4 +105,15 @@ /* For C file, we already have NOKPROBE_SYMBOL macro */ #endif +#ifndef __ASSEMBLY__ +/* + * This output constraint should be used for any inline asm which has a "call" + * instruction. Otherwise the asm may be inserted before the frame pointer + * gets set up by the containing function. If you forget to do this, objtool + * may print a "call without frame pointer save/setup" warning. + */ +register unsigned long current_stack_pointer asm(_ASM_SP); +#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) +#endif + #endif /* _ASM_X86_ASM_H */ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index c7b551028740..9b028204685d 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -166,17 +166,6 @@ static inline struct thread_info *current_thread_info(void) return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE); } -static inline unsigned long current_stack_pointer(void) -{ - unsigned long sp; -#ifdef CONFIG_X86_64 - asm("mov %%rsp,%0" : "=g" (sp)); -#else - asm("mov %%esp,%0" : "=g" (sp)); -#endif - return sp; -} - #else /* !__ASSEMBLY__ */ #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 38da8f29a9c8..647089c64d13 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -65,7 +65,7 @@ static void call_on_stack(void *func, void *stack) static inline void *current_stack(void) { - return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1)); + return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1)); } static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc) @@ -89,7 +89,7 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc) /* Save the next esp at the bottom of the stack */ prev_esp = (u32 *)irqstk; - *prev_esp = current_stack_pointer(); + *prev_esp = current_stack_pointer; if (unlikely(overflow)) call_on_stack(print_stack_overflow, isp); @@ -142,7 +142,7 @@ void do_softirq_own_stack(void) /* Push the previous esp onto the stack */ prev_esp = (u32 *)irqstk; - *prev_esp = current_stack_pointer(); + *prev_esp = current_stack_pointer; call_on_stack(__do_softirq, isp); } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 679302c312f8..22b81f35c500 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -166,7 +166,7 @@ void ist_begin_non_atomic(struct pt_regs *regs) * from double_fault. */ BUG_ON((unsigned long)(current_top_of_stack() - - current_stack_pointer()) >= THREAD_SIZE); + current_stack_pointer) >= THREAD_SIZE); preempt_enable_no_resched(); } From b76ac90af34dc08f057da15aa34584a0a3d381b5 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 11 Dec 2016 02:09:18 +0100 Subject: [PATCH 006/427] x86/kbuild: enable modversions for symbols exported from asm commit 334bb773876403eae3457d81be0b8ea70f8e4ccc upstream. Commit 4efca4ed ("kbuild: modversions for EXPORT_SYMBOL() for asm") adds modversion support for symbols exported from asm files. Architectures must include C-style declarations for those symbols in asm/asm-prototypes.h in order for them to be versioned. Add these declarations for x86, and an architecture-independent file that can be used for common symbols. With f27c2f6 reverting 8ab2ae6 ("default exported asm symbols to zero") we produce a scary warning on x86, this commit fixes that. Signed-off-by: Adam Borowski Tested-by: Kalle Valo Acked-by: Nicholas Piggin Tested-by: Peter Wu Tested-by: Oliver Hartkopp Signed-off-by: Michal Marek Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/asm-prototypes.h | 16 ++++++++++++++++ include/asm-generic/asm-prototypes.h | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/x86/include/asm/asm-prototypes.h create mode 100644 include/asm-generic/asm-prototypes.h diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h new file mode 100644 index 000000000000..44b8762fa0c7 --- /dev/null +++ b/arch/x86/include/asm/asm-prototypes.h @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifndef CONFIG_X86_CMPXCHG64 +extern void cmpxchg8b_emu(void); +#endif diff --git a/include/asm-generic/asm-prototypes.h b/include/asm-generic/asm-prototypes.h new file mode 100644 index 000000000000..df13637e4017 --- /dev/null +++ b/include/asm-generic/asm-prototypes.h @@ -0,0 +1,7 @@ +#include +extern void *__memset(void *, int, __kernel_size_t); +extern void *__memcpy(void *, const void *, __kernel_size_t); +extern void *__memmove(void *, const void *, __kernel_size_t); +extern void *memset(void *, int, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); +extern void *memmove(void *, const void *, __kernel_size_t); From b8e7a489b51810992ba3266bfd9e043709e07267 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 26 Apr 2016 12:23:25 -0700 Subject: [PATCH 007/427] x86/asm: Make asm/alternative.h safe from assembly commit f005f5d860e0231fe212cfda8c1a3148b99609f4 upstream. asm/alternative.h isn't directly useful from assembly, but it shouldn't break the build. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/e5b693fcef99fe6e80341c9e97a002fb23871e91.1461698311.git.luto@kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/alternative.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index d1cf17173b1b..215ea9214215 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_ALTERNATIVE_H #define _ASM_X86_ALTERNATIVE_H +#ifndef __ASSEMBLY__ + #include #include #include @@ -271,4 +273,6 @@ extern void *text_poke(void *addr, const void *opcode, size_t len); extern int poke_int3_handler(struct pt_regs *regs); extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); +#endif /* __ASSEMBLY__ */ + #endif /* _ASM_X86_ALTERNATIVE_H */ From a88693d006986b8fc9ae5036852ac0156106de2a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 11 Jan 2016 10:54:54 -0500 Subject: [PATCH 008/427] EXPORT_SYMBOL() for asm commit 22823ab419d8ed884195cfa75483fd3a99bb1462 upstream. Add asm-usable variants of EXPORT_SYMBOL/EXPORT_SYMBOL_GPL. This commit just adds the default implementation; most of the architectures can simply add export.h to asm/Kbuild and start using from assembler. The rest needs to have their define everal macros and then explicitly include One area where the things might diverge from default is the alignment; normally it's 8 bytes on 64bit targets and 4 on 32bit ones, both for unsigned long and for struct kernel_symbol. Unfortunately, amd64 and m68k are unusual - m68k aligns to 2 bytes (for both) and amd64 aligns struct kernel_symbol to 16 bytes. For those we'll need asm/export.h to override the constants used by generic version - KSYM_ALIGN and KCRC_ALIGN for kernel_symbol and unsigned long resp. And no, __alignof__ would not do the trick - on amd64 __alignof__ of struct kernel_symbol is 8, not 16. More serious source of unpleasantness is treatment of function descriptors on architectures that have those. Things like ppc64, parisc, ia64, etc. need more than the address of the first insn to call an arbitrary function. As the result, their representation of pointers to functions is not the typical "address of the entry point" - it's an address of a small static structure containing all the required information (including the entry point, of course). Sadly, the asm-side conventions differ in what the function name refers to - entry point or the function descriptor. On ppc64 we do the latter; bar: .quad foo is what void (*bar)(void) = foo; turns into and the rare places where we need to explicitly work with the label of entry point are dealt with as DOTSYM(foo). For our purposes it's ideal - generic macros are usable. However, parisc would have foo and P%foo used for label of entry point and address of the function descriptor and bar: .long P%foo woudl be used instead. ia64 goes similar to parisc in that respect, except that there it's @fptr(foo) rather than P%foo. Such architectures need to define KSYM_FUNC that would turn a function name into whatever is needed to refer to function descriptor. What's more, on such architectures we need to know whether we are exporting a function or an object - in assembler we have to tell that explicitly, to decide whether we want EXPORT_SYMBOL(foo) produce e.g. __ksymtab_foo: .quad foo or __ksymtab_foo: .quad @fptr(foo) For that reason we introduce EXPORT_DATA_SYMBOL{,_GPL}(), to be used for exports of data objects. On normal architectures it's the same thing as EXPORT_SYMBOL{,_GPL}(), but on parisc-like ones they differ and the right one needs to be used. Most of the exports are functions, so we keep EXPORT_SYMBOL for those... Signed-off-by: Al Viro Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- include/asm-generic/export.h | 94 ++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 include/asm-generic/export.h diff --git a/include/asm-generic/export.h b/include/asm-generic/export.h new file mode 100644 index 000000000000..43199a049da5 --- /dev/null +++ b/include/asm-generic/export.h @@ -0,0 +1,94 @@ +#ifndef __ASM_GENERIC_EXPORT_H +#define __ASM_GENERIC_EXPORT_H + +#ifndef KSYM_FUNC +#define KSYM_FUNC(x) x +#endif +#ifdef CONFIG_64BIT +#define __put .quad +#ifndef KSYM_ALIGN +#define KSYM_ALIGN 8 +#endif +#ifndef KCRC_ALIGN +#define KCRC_ALIGN 8 +#endif +#else +#define __put .long +#ifndef KSYM_ALIGN +#define KSYM_ALIGN 4 +#endif +#ifndef KCRC_ALIGN +#define KCRC_ALIGN 4 +#endif +#endif + +#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX +#define KSYM(name) _##name +#else +#define KSYM(name) name +#endif + +/* + * note on .section use: @progbits vs %progbits nastiness doesn't matter, + * since we immediately emit into those sections anyway. + */ +.macro ___EXPORT_SYMBOL name,val,sec +#ifdef CONFIG_MODULES + .globl KSYM(__ksymtab_\name) + .section ___ksymtab\sec+\name,"a" + .balign KSYM_ALIGN +KSYM(__ksymtab_\name): + __put \val, KSYM(__kstrtab_\name) + .previous + .section __ksymtab_strings,"a" +KSYM(__kstrtab_\name): +#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX + .asciz "_\name" +#else + .asciz "\name" +#endif + .previous +#ifdef CONFIG_MODVERSIONS + .section ___kcrctab\sec+\name,"a" + .balign KCRC_ALIGN +KSYM(__kcrctab_\name): + __put KSYM(__crc_\name) + .weak KSYM(__crc_\name) + .previous +#endif +#endif +.endm +#undef __put + +#if defined(__KSYM_DEPS__) + +#define __EXPORT_SYMBOL(sym, val, sec) === __KSYM_##sym === + +#elif defined(CONFIG_TRIM_UNUSED_KSYMS) + +#include +#include + +#define __EXPORT_SYMBOL(sym, val, sec) \ + __cond_export_sym(sym, val, sec, config_enabled(__KSYM_##sym)) +#define __cond_export_sym(sym, val, sec, conf) \ + ___cond_export_sym(sym, val, sec, conf) +#define ___cond_export_sym(sym, val, sec, enabled) \ + __cond_export_sym_##enabled(sym, val, sec) +#define __cond_export_sym_1(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec +#define __cond_export_sym_0(sym, val, sec) /* nothing */ + +#else +#define __EXPORT_SYMBOL(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec +#endif + +#define EXPORT_SYMBOL(name) \ + __EXPORT_SYMBOL(name, KSYM_FUNC(KSYM(name)),) +#define EXPORT_SYMBOL_GPL(name) \ + __EXPORT_SYMBOL(name, KSYM_FUNC(KSYM(name)), _gpl) +#define EXPORT_DATA_SYMBOL(name) \ + __EXPORT_SYMBOL(name, KSYM(name),) +#define EXPORT_DATA_SYMBOL_GPL(name) \ + __EXPORT_SYMBOL(name, KSYM(name),_gpl) + +#endif From 675901851fd2a00c7a70bcf327303efba3b81e2f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 14 Jun 2016 14:58:54 +0900 Subject: [PATCH 009/427] kconfig.h: use __is_defined() to check if MODULE is defined commit 4f920843d248946545415c1bf6120942048708ed upstream. The macro MODULE is not a config option, it is a per-file build option. So, config_enabled(MODULE) is not sensible. (There is another case in include/linux/export.h, where config_enabled() is used against a non-config option.) This commit renames some macros in include/linux/kconfig.h for the use for non-config macros and replaces config_enabled(MODULE) with __is_defined(MODULE). I am keeping config_enabled() because it is still referenced from some places, but I expect it would be deprecated in the future. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- include/linux/kconfig.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h index b33c7797eb57..a94b5bf57f51 100644 --- a/include/linux/kconfig.h +++ b/include/linux/kconfig.h @@ -17,10 +17,11 @@ * the last step cherry picks the 2nd arg, we get a zero. */ #define __ARG_PLACEHOLDER_1 0, -#define config_enabled(cfg) _config_enabled(cfg) -#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value) -#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0) -#define ___config_enabled(__ignored, val, ...) val +#define config_enabled(cfg) ___is_defined(cfg) +#define __is_defined(x) ___is_defined(x) +#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val) +#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0) +#define __take_second_arg(__ignored, val, ...) val /* * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 @@ -42,7 +43,7 @@ * built-in code when CONFIG_FOO is set to 'm'. */ #define IS_REACHABLE(option) (config_enabled(option) || \ - (config_enabled(option##_MODULE) && config_enabled(MODULE))) + (config_enabled(option##_MODULE) && __is_defined(MODULE))) /* * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', From 3c5e10905263dbe9fbc621d1889b85e9c867da25 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:25 +0000 Subject: [PATCH 010/427] x86/retpoline: Add initial retpoline support commit 76b043848fd22dbf7f8bf3a1452f8c70d557b860 upstream. Enable the use of -mindirect-branch=thunk-extern in newer GCC, and provide the corresponding thunks. Provide assembler macros for invoking the thunks in the same way that GCC does, from native and inline assembler. This adds X86_FEATURE_RETPOLINE and sets it by default on all CPUs. In some circumstances, IBRS microcode features may be used instead, and the retpoline can be disabled. On AMD CPUs if lfence is serialising, the retpoline can be dramatically simplified to a simple "lfence; jmp *\reg". A future patch, after it has been verified that lfence really is serialising in all circumstances, can enable this by setting the X86_FEATURE_RETPOLINE_AMD feature bit in addition to X86_FEATURE_RETPOLINE. Do not align the retpoline in the altinstr section, because there is no guarantee that it stays aligned when it's copied over the oldinstr during alternative patching. [ Andi Kleen: Rename the macros, add CONFIG_RETPOLINE option, export thunks] [ tglx: Put actual function CALL/JMP in front of the macros, convert to symbolic labels ] [ dwmw2: Convert back to numeric labels, merge objtool fixes ] Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-4-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse [ 4.4 backport: removed objtool annotation since there is no objtool ] Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 13 ++++ arch/x86/Makefile | 10 +++ arch/x86/include/asm/asm-prototypes.h | 25 ++++++ arch/x86/include/asm/cpufeature.h | 2 + arch/x86/include/asm/nospec-branch.h | 106 ++++++++++++++++++++++++++ arch/x86/kernel/cpu/common.c | 4 + arch/x86/lib/Makefile | 1 + arch/x86/lib/retpoline.S | 48 ++++++++++++ 8 files changed, 209 insertions(+) create mode 100644 arch/x86/include/asm/nospec-branch.h create mode 100644 arch/x86/lib/retpoline.S diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0ef2cdd11616..75d0053b495a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -379,6 +379,19 @@ config GOLDFISH def_bool y depends on X86_GOLDFISH +config RETPOLINE + bool "Avoid speculative indirect branches in kernel" + default y + ---help--- + Compile kernel with the retpoline compiler options to guard against + kernel-to-user data leaks by avoiding speculative indirect + branches. Requires a compiler with -mindirect-branch=thunk-extern + support for full protection. The kernel may run slower. + + Without compiler support, at least indirect branches in assembler + code are eliminated. Since this includes the syscall entry path, + it is not entirely pointless. + if X86_32 config X86_EXTENDED_PLATFORM bool "Support for extended (non-PC) x86 platforms" diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 4086abca0b32..34fdac520edb 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -189,6 +189,16 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) +# Avoid indirect branches in kernel to deal with Spectre +ifdef CONFIG_RETPOLINE + RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) + ifneq ($(RETPOLINE_CFLAGS),) + KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE + else + $(warning CONFIG_RETPOLINE=y, but not supported by the compiler. Toolchain update recommended.) + endif +endif + archscripts: scripts_basic $(Q)$(MAKE) $(build)=arch/x86/tools relocs diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h index 44b8762fa0c7..b15aa4083dfd 100644 --- a/arch/x86/include/asm/asm-prototypes.h +++ b/arch/x86/include/asm/asm-prototypes.h @@ -10,7 +10,32 @@ #include #include #include +#include #ifndef CONFIG_X86_CMPXCHG64 extern void cmpxchg8b_emu(void); #endif + +#ifdef CONFIG_RETPOLINE +#ifdef CONFIG_X86_32 +#define INDIRECT_THUNK(reg) extern asmlinkage void __x86_indirect_thunk_e ## reg(void); +#else +#define INDIRECT_THUNK(reg) extern asmlinkage void __x86_indirect_thunk_r ## reg(void); +INDIRECT_THUNK(8) +INDIRECT_THUNK(9) +INDIRECT_THUNK(10) +INDIRECT_THUNK(11) +INDIRECT_THUNK(12) +INDIRECT_THUNK(13) +INDIRECT_THUNK(14) +INDIRECT_THUNK(15) +#endif +INDIRECT_THUNK(ax) +INDIRECT_THUNK(bx) +INDIRECT_THUNK(cx) +INDIRECT_THUNK(dx) +INDIRECT_THUNK(si) +INDIRECT_THUNK(di) +INDIRECT_THUNK(bp) +INDIRECT_THUNK(sp) +#endif /* CONFIG_RETPOLINE */ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 142028afd049..0fbc98568018 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -200,6 +200,8 @@ #define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */ #define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ +#define X86_FEATURE_RETPOLINE ( 7*32+29) /* Generic Retpoline mitigation for Spectre variant 2 */ +#define X86_FEATURE_RETPOLINE_AMD ( 7*32+30) /* AMD Retpoline mitigation for Spectre variant 2 */ /* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */ #define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */ diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h new file mode 100644 index 000000000000..5763548fb30b --- /dev/null +++ b/arch/x86/include/asm/nospec-branch.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __NOSPEC_BRANCH_H__ +#define __NOSPEC_BRANCH_H__ + +#include +#include +#include + +#ifdef __ASSEMBLY__ + +/* + * These are the bare retpoline primitives for indirect jmp and call. + * Do not use these directly; they only exist to make the ALTERNATIVE + * invocation below less ugly. + */ +.macro RETPOLINE_JMP reg:req + call .Ldo_rop_\@ +.Lspec_trap_\@: + pause + jmp .Lspec_trap_\@ +.Ldo_rop_\@: + mov \reg, (%_ASM_SP) + ret +.endm + +/* + * This is a wrapper around RETPOLINE_JMP so the called function in reg + * returns to the instruction after the macro. + */ +.macro RETPOLINE_CALL reg:req + jmp .Ldo_call_\@ +.Ldo_retpoline_jmp_\@: + RETPOLINE_JMP \reg +.Ldo_call_\@: + call .Ldo_retpoline_jmp_\@ +.endm + +/* + * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple + * indirect jmp/call which may be susceptible to the Spectre variant 2 + * attack. + */ +.macro JMP_NOSPEC reg:req +#ifdef CONFIG_RETPOLINE + ALTERNATIVE_2 __stringify(jmp *\reg), \ + __stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \ + __stringify(lfence; jmp *\reg), X86_FEATURE_RETPOLINE_AMD +#else + jmp *\reg +#endif +.endm + +.macro CALL_NOSPEC reg:req +#ifdef CONFIG_RETPOLINE + ALTERNATIVE_2 __stringify(call *\reg), \ + __stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\ + __stringify(lfence; call *\reg), X86_FEATURE_RETPOLINE_AMD +#else + call *\reg +#endif +.endm + +#else /* __ASSEMBLY__ */ + +#if defined(CONFIG_X86_64) && defined(RETPOLINE) + +/* + * Since the inline asm uses the %V modifier which is only in newer GCC, + * the 64-bit one is dependent on RETPOLINE not CONFIG_RETPOLINE. + */ +# define CALL_NOSPEC \ + ALTERNATIVE( \ + "call *%[thunk_target]\n", \ + "call __x86_indirect_thunk_%V[thunk_target]\n", \ + X86_FEATURE_RETPOLINE) +# define THUNK_TARGET(addr) [thunk_target] "r" (addr) + +#elif defined(CONFIG_X86_32) && defined(CONFIG_RETPOLINE) +/* + * For i386 we use the original ret-equivalent retpoline, because + * otherwise we'll run out of registers. We don't care about CET + * here, anyway. + */ +# define CALL_NOSPEC ALTERNATIVE("call *%[thunk_target]\n", \ + " jmp 904f;\n" \ + " .align 16\n" \ + "901: call 903f;\n" \ + "902: pause;\n" \ + " jmp 902b;\n" \ + " .align 16\n" \ + "903: addl $4, %%esp;\n" \ + " pushl %[thunk_target];\n" \ + " ret;\n" \ + " .align 16\n" \ + "904: call 901b;\n", \ + X86_FEATURE_RETPOLINE) + +# define THUNK_TARGET(addr) [thunk_target] "rm" (addr) +#else /* No retpoline */ +# define CALL_NOSPEC "call *%[thunk_target]\n" +# define THUNK_TARGET(addr) [thunk_target] "rm" (addr) +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __NOSPEC_BRANCH_H__ */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0531c1707b40..5b3a6e888bc5 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -837,6 +837,10 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) setup_force_cpu_bug(X86_BUG_SPECTRE_V1); setup_force_cpu_bug(X86_BUG_SPECTRE_V2); +#ifdef CONFIG_RETPOLINE + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); +#endif + fpu__init_system(c); #ifdef CONFIG_X86_32 diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index f2587888d987..12a34d15b648 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -21,6 +21,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o lib-y += memcpy_$(BITS).o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o +lib-$(CONFIG_RETPOLINE) += retpoline.o obj-y += msr.o msr-reg.o msr-reg-export.o diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S new file mode 100644 index 000000000000..019a03599bb0 --- /dev/null +++ b/arch/x86/lib/retpoline.S @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include +#include +#include +#include +#include +#include +#include + +.macro THUNK reg + .section .text.__x86.indirect_thunk.\reg + +ENTRY(__x86_indirect_thunk_\reg) + CFI_STARTPROC + JMP_NOSPEC %\reg + CFI_ENDPROC +ENDPROC(__x86_indirect_thunk_\reg) +.endm + +/* + * Despite being an assembler file we can't just use .irp here + * because __KSYM_DEPS__ only uses the C preprocessor and would + * only see one instance of "__x86_indirect_thunk_\reg" rather + * than one per register with the correct names. So we do it + * the simple and nasty way... + */ +#define EXPORT_THUNK(reg) EXPORT_SYMBOL(__x86_indirect_thunk_ ## reg) +#define GENERATE_THUNK(reg) THUNK reg ; EXPORT_THUNK(reg) + +GENERATE_THUNK(_ASM_AX) +GENERATE_THUNK(_ASM_BX) +GENERATE_THUNK(_ASM_CX) +GENERATE_THUNK(_ASM_DX) +GENERATE_THUNK(_ASM_SI) +GENERATE_THUNK(_ASM_DI) +GENERATE_THUNK(_ASM_BP) +GENERATE_THUNK(_ASM_SP) +#ifdef CONFIG_64BIT +GENERATE_THUNK(r8) +GENERATE_THUNK(r9) +GENERATE_THUNK(r10) +GENERATE_THUNK(r11) +GENERATE_THUNK(r12) +GENERATE_THUNK(r13) +GENERATE_THUNK(r14) +GENERATE_THUNK(r15) +#endif From 9f789bc5711bcacb5df003594b992f0c1cc19df4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:26 +0000 Subject: [PATCH 011/427] x86/spectre: Add boot time option to select Spectre v2 mitigation commit da285121560e769cc31797bba6422eea71d473e0 upstream. Add a spectre_v2= option to select the mitigation used for the indirect branch speculation vulnerability. Currently, the only option available is retpoline, in its various forms. This will be expanded to cover the new IBRS/IBPB microcode features. The RETPOLINE_AMD feature relies on a serializing LFENCE for speculation control. For AMD hardware, only set RETPOLINE_AMD if LFENCE is a serializing instruction, which is indicated by the LFENCE_RDTSC feature. [ tglx: Folded back the LFENCE/AMD fixes and reworked it so IBRS integration becomes simple ] Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-5-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 28 +++++ arch/x86/include/asm/nospec-branch.h | 10 ++ arch/x86/kernel/cpu/bugs.c | 158 ++++++++++++++++++++++++++- arch/x86/kernel/cpu/common.c | 4 - 4 files changed, 195 insertions(+), 5 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 39280b72f27a..22a4688dc0c8 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2452,6 +2452,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. nohugeiomap [KNL,x86] Disable kernel huge I/O mappings. + nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2 + (indirect branch prediction) vulnerability. System may + allow data leaks with this option, which is equivalent + to spectre_v2=off. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. @@ -3594,6 +3599,29 @@ bytes respectively. Such letter suffixes can also be entirely omitted. sonypi.*= [HW] Sony Programmable I/O Control Device driver See Documentation/laptops/sonypi.txt + spectre_v2= [X86] Control mitigation of Spectre variant 2 + (indirect branch speculation) vulnerability. + + on - unconditionally enable + off - unconditionally disable + auto - kernel detects whether your CPU model is + vulnerable + + Selecting 'on' will, and 'auto' may, choose a + mitigation method at run time according to the + CPU, the available microcode, the setting of the + CONFIG_RETPOLINE configuration option, and the + compiler with which the kernel was built. + + Specific mitigations can also be selected manually: + + retpoline - replace indirect branches + retpoline,generic - google's original retpoline + retpoline,amd - AMD-specific minimal thunk + + Not specifying this option is equivalent to + spectre_v2=auto. + spia_io_base= [HW,MTD] spia_fio_base= spia_pedr= diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 5763548fb30b..fe48aeee79d1 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -102,5 +102,15 @@ # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) #endif +/* The Spectre V2 mitigation variants */ +enum spectre_v2_mitigation { + SPECTRE_V2_NONE, + SPECTRE_V2_RETPOLINE_MINIMAL, + SPECTRE_V2_RETPOLINE_MINIMAL_AMD, + SPECTRE_V2_RETPOLINE_GENERIC, + SPECTRE_V2_RETPOLINE_AMD, + SPECTRE_V2_IBRS, +}; + #endif /* __ASSEMBLY__ */ #endif /* __NOSPEC_BRANCH_H__ */ diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index cb6b4f9d0b7a..49d25ddf0e9f 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -10,6 +10,9 @@ #include #include #include + +#include +#include #include #include #include @@ -20,6 +23,8 @@ #include #include +static void __init spectre_v2_select_mitigation(void); + void __init check_bugs(void) { identify_boot_cpu(); @@ -29,6 +34,9 @@ void __init check_bugs(void) print_cpu_info(&boot_cpu_data); } + /* Select the proper spectre mitigation before patching alternatives */ + spectre_v2_select_mitigation(); + #ifdef CONFIG_X86_32 /* * Check whether we are able to run this kernel safely on SMP. @@ -61,6 +69,153 @@ void __init check_bugs(void) #endif } +/* The kernel command line selection */ +enum spectre_v2_mitigation_cmd { + SPECTRE_V2_CMD_NONE, + SPECTRE_V2_CMD_AUTO, + SPECTRE_V2_CMD_FORCE, + SPECTRE_V2_CMD_RETPOLINE, + SPECTRE_V2_CMD_RETPOLINE_GENERIC, + SPECTRE_V2_CMD_RETPOLINE_AMD, +}; + +static const char *spectre_v2_strings[] = { + [SPECTRE_V2_NONE] = "Vulnerable", + [SPECTRE_V2_RETPOLINE_MINIMAL] = "Vulnerable: Minimal generic ASM retpoline", + [SPECTRE_V2_RETPOLINE_MINIMAL_AMD] = "Vulnerable: Minimal AMD ASM retpoline", + [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full generic retpoline", + [SPECTRE_V2_RETPOLINE_AMD] = "Mitigation: Full AMD retpoline", +}; + +#undef pr_fmt +#define pr_fmt(fmt) "Spectre V2 mitigation: " fmt + +static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE; + +static void __init spec2_print_if_insecure(const char *reason) +{ + if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) + pr_info("%s\n", reason); +} + +static void __init spec2_print_if_secure(const char *reason) +{ + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) + pr_info("%s\n", reason); +} + +static inline bool retp_compiler(void) +{ + return __is_defined(RETPOLINE); +} + +static inline bool match_option(const char *arg, int arglen, const char *opt) +{ + int len = strlen(opt); + + return len == arglen && !strncmp(arg, opt, len); +} + +static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) +{ + char arg[20]; + int ret; + + ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, + sizeof(arg)); + if (ret > 0) { + if (match_option(arg, ret, "off")) { + goto disable; + } else if (match_option(arg, ret, "on")) { + spec2_print_if_secure("force enabled on command line."); + return SPECTRE_V2_CMD_FORCE; + } else if (match_option(arg, ret, "retpoline")) { + spec2_print_if_insecure("retpoline selected on command line."); + return SPECTRE_V2_CMD_RETPOLINE; + } else if (match_option(arg, ret, "retpoline,amd")) { + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) { + pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n"); + return SPECTRE_V2_CMD_AUTO; + } + spec2_print_if_insecure("AMD retpoline selected on command line."); + return SPECTRE_V2_CMD_RETPOLINE_AMD; + } else if (match_option(arg, ret, "retpoline,generic")) { + spec2_print_if_insecure("generic retpoline selected on command line."); + return SPECTRE_V2_CMD_RETPOLINE_GENERIC; + } else if (match_option(arg, ret, "auto")) { + return SPECTRE_V2_CMD_AUTO; + } + } + + if (!cmdline_find_option_bool(boot_command_line, "nospectre_v2")) + return SPECTRE_V2_CMD_AUTO; +disable: + spec2_print_if_insecure("disabled on command line."); + return SPECTRE_V2_CMD_NONE; +} + +static void __init spectre_v2_select_mitigation(void) +{ + enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); + enum spectre_v2_mitigation mode = SPECTRE_V2_NONE; + + /* + * If the CPU is not affected and the command line mode is NONE or AUTO + * then nothing to do. + */ + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2) && + (cmd == SPECTRE_V2_CMD_NONE || cmd == SPECTRE_V2_CMD_AUTO)) + return; + + switch (cmd) { + case SPECTRE_V2_CMD_NONE: + return; + + case SPECTRE_V2_CMD_FORCE: + /* FALLTRHU */ + case SPECTRE_V2_CMD_AUTO: + goto retpoline_auto; + + case SPECTRE_V2_CMD_RETPOLINE_AMD: + if (IS_ENABLED(CONFIG_RETPOLINE)) + goto retpoline_amd; + break; + case SPECTRE_V2_CMD_RETPOLINE_GENERIC: + if (IS_ENABLED(CONFIG_RETPOLINE)) + goto retpoline_generic; + break; + case SPECTRE_V2_CMD_RETPOLINE: + if (IS_ENABLED(CONFIG_RETPOLINE)) + goto retpoline_auto; + break; + } + pr_err("kernel not compiled with retpoline; no mitigation available!"); + return; + +retpoline_auto: + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + retpoline_amd: + if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) { + pr_err("LFENCE not serializing. Switching to generic retpoline\n"); + goto retpoline_generic; + } + mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD : + SPECTRE_V2_RETPOLINE_MINIMAL_AMD; + setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD); + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); + } else { + retpoline_generic: + mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : + SPECTRE_V2_RETPOLINE_MINIMAL; + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); + } + + spectre_v2_enabled = mode; + pr_info("%s\n", spectre_v2_strings[mode]); +} + +#undef pr_fmt + #ifdef CONFIG_SYSFS ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) @@ -85,6 +240,7 @@ ssize_t cpu_show_spectre_v2(struct device *dev, { if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) return sprintf(buf, "Not affected\n"); - return sprintf(buf, "Vulnerable\n"); + + return sprintf(buf, "%s\n", spectre_v2_strings[spectre_v2_enabled]); } #endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5b3a6e888bc5..0531c1707b40 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -837,10 +837,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) setup_force_cpu_bug(X86_BUG_SPECTRE_V1); setup_force_cpu_bug(X86_BUG_SPECTRE_V2); -#ifdef CONFIG_RETPOLINE - setup_force_cpu_cap(X86_FEATURE_RETPOLINE); -#endif - fpu__init_system(c); #ifdef CONFIG_X86_32 From 9fe55976f0c8acfd7408bf693b6d171587b62129 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:27 +0000 Subject: [PATCH 012/427] x86/retpoline/crypto: Convert crypto assembler indirect jumps commit 9697fa39efd3fc3692f2949d4045f393ec58450b upstream. Convert all indirect jumps in crypto assembler code to use non-speculative sequences when CONFIG_RETPOLINE is enabled. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-6-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/x86/crypto/aesni-intel_asm.S | 5 +++-- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 3 ++- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 3 ++- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index 6bd2c6c95373..3f93dedb5a4d 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -31,6 +31,7 @@ #include #include +#include /* * The following macros are used to move an (un)aligned 16 byte value to/from @@ -2714,7 +2715,7 @@ ENTRY(aesni_xts_crypt8) pxor INC, STATE4 movdqu IV, 0x30(OUTP) - call *%r11 + CALL_NOSPEC %r11 movdqu 0x00(OUTP), INC pxor INC, STATE1 @@ -2759,7 +2760,7 @@ ENTRY(aesni_xts_crypt8) _aesni_gf128mul_x_ble() movups IV, (IVP) - call *%r11 + CALL_NOSPEC %r11 movdqu 0x40(OUTP), INC pxor INC, STATE1 diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S index ce71f9212409..5881756f78a2 100644 --- a/arch/x86/crypto/camellia-aesni-avx-asm_64.S +++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S @@ -16,6 +16,7 @@ */ #include +#include #define CAMELLIA_TABLE_BYTE_LEN 272 @@ -1210,7 +1211,7 @@ camellia_xts_crypt_16way: vpxor 14 * 16(%rax), %xmm15, %xmm14; vpxor 15 * 16(%rax), %xmm15, %xmm15; - call *%r9; + CALL_NOSPEC %r9; addq $(16 * 16), %rsp; diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S index 0e0b8863a34b..0d45b04b490a 100644 --- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S +++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S @@ -11,6 +11,7 @@ */ #include +#include #define CAMELLIA_TABLE_BYTE_LEN 272 @@ -1323,7 +1324,7 @@ camellia_xts_crypt_32way: vpxor 14 * 32(%rax), %ymm15, %ymm14; vpxor 15 * 32(%rax), %ymm15, %ymm15; - call *%r9; + CALL_NOSPEC %r9; addq $(16 * 32), %rsp; diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S index 4fe27e074194..48767520cbe0 100644 --- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S @@ -45,6 +45,7 @@ #include #include +#include ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction @@ -172,7 +173,7 @@ continue_block: movzxw (bufp, %rax, 2), len offset=crc_array-jump_table lea offset(bufp, len, 1), bufp - jmp *bufp + JMP_NOSPEC bufp ################################################################ ## 2a) PROCESS FULL BLOCKS: From 028083cb02db69237e73950576bc81ac579693dc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:28 +0000 Subject: [PATCH 013/427] x86/retpoline/entry: Convert entry assembler indirect jumps commit 2641f08bb7fc63a636a2b18173221d7040a3512e upstream. Convert indirect jumps in core 32/64bit entry assembler code to use non-speculative sequences when CONFIG_RETPOLINE is enabled. Don't use CALL_NOSPEC in entry_SYSCALL_64_fastpath because the return address after the 'call' instruction must be *precisely* at the .Lentry_SYSCALL_64_after_fastpath label for stub_ptregs_64 to work, and the use of alternatives will mess that up unless we play horrid games to prepend with NOPs and make the variants the same length. It's not worth it; in the case where we ALTERNATIVE out the retpoline, the first instruction at __x86.indirect_thunk.rax is going to be a bare jmp *%rax anyway. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Ingo Molnar Acked-by: Arjan van de Ven Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-7-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/entry_32.S | 6 ++++-- arch/x86/entry/entry_64.S | 14 +++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index ae678ad128a9..adbbd4f538e9 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -44,6 +44,7 @@ #include #include #include +#include .section .entry.text, "ax" @@ -226,7 +227,8 @@ ENTRY(ret_from_kernel_thread) pushl $0x0202 # Reset kernel eflags popfl movl PT_EBP(%esp), %eax - call *PT_EBX(%esp) + movl PT_EBX(%esp), %edx + CALL_NOSPEC %edx movl $0, PT_EAX(%esp) /* @@ -938,7 +940,7 @@ error_code: movl %ecx, %es TRACE_IRQS_OFF movl %esp, %eax # pt_regs pointer - call *%edi + CALL_NOSPEC %edi jmp ret_from_exception END(page_fault) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 952b23b5d4e9..81b1cd533965 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -36,6 +36,7 @@ #include #include #include +#include #include /* Avoid __ASSEMBLER__'ifying just for this. */ @@ -184,7 +185,13 @@ entry_SYSCALL_64_fastpath: #endif ja 1f /* return -ENOSYS (already in pt_regs->ax) */ movq %r10, %rcx +#ifdef CONFIG_RETPOLINE + movq sys_call_table(, %rax, 8), %rax + call __x86_indirect_thunk_rax +#else call *sys_call_table(, %rax, 8) +#endif + movq %rax, RAX(%rsp) 1: /* @@ -276,7 +283,12 @@ tracesys_phase2: #endif ja 1f /* return -ENOSYS (already in pt_regs->ax) */ movq %r10, %rcx /* fixup for C */ +#ifdef CONFIG_RETPOLINE + movq sys_call_table(, %rax, 8), %rax + call __x86_indirect_thunk_rax +#else call *sys_call_table(, %rax, 8) +#endif movq %rax, RAX(%rsp) 1: /* Use IRET because user could have changed pt_regs->foo */ @@ -491,7 +503,7 @@ ENTRY(ret_from_fork) * nb: we depend on RESTORE_EXTRA_REGS above */ movq %rbp, %rdi - call *%rbx + CALL_NOSPEC %rbx movl $0, RAX(%rsp) RESTORE_EXTRA_REGS jmp int_ret_from_sys_call From 7153a6d5ff050050555066f58ac3458c5efc699b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:29 +0000 Subject: [PATCH 014/427] x86/retpoline/ftrace: Convert ftrace assembler indirect jumps commit 9351803bd803cdbeb9b5a7850b7b6f464806e3db upstream. Convert all indirect jumps in ftrace assembler code to use non-speculative sequences when CONFIG_RETPOLINE is enabled. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-8-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/entry_32.S | 5 +++-- arch/x86/kernel/mcount_64.S | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index adbbd4f538e9..d437f3871e53 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -863,7 +863,8 @@ trace: movl 0x4(%ebp), %edx subl $MCOUNT_INSN_SIZE, %eax - call *ftrace_trace_function + movl ftrace_trace_function, %ecx + CALL_NOSPEC %ecx popl %edx popl %ecx @@ -898,7 +899,7 @@ return_to_handler: movl %eax, %ecx popl %edx popl %eax - jmp *%ecx + JMP_NOSPEC %ecx #endif #ifdef CONFIG_TRACING diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S index 5d9afbcb6074..09284cfab86f 100644 --- a/arch/x86/kernel/mcount_64.S +++ b/arch/x86/kernel/mcount_64.S @@ -7,7 +7,7 @@ #include #include #include - +#include .code64 .section .entry.text, "ax" @@ -285,8 +285,9 @@ trace: * ip and parent ip are used and the list function is called when * function tracing is enabled. */ - call *ftrace_trace_function + movq ftrace_trace_function, %r8 + CALL_NOSPEC %r8 restore_mcount_regs jmp fgraph_trace @@ -329,5 +330,5 @@ GLOBAL(return_to_handler) movq 8(%rsp), %rdx movq (%rsp), %rax addq $24, %rsp - jmp *%rdi + JMP_NOSPEC %rdi #endif From d2beed45635e3c430bc6d84ff8e6c6e8cb2e10b4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:30 +0000 Subject: [PATCH 015/427] x86/retpoline/hyperv: Convert assembler indirect jumps commit e70e5892b28c18f517f29ab6e83bd57705104b31 upstream. Convert all indirect jumps in hyperv inline asm code to use non-speculative sequences when CONFIG_RETPOLINE is enabled. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-9-git-send-email-dwmw@amazon.co.uk [ backport to 4.4, hopefully correct, not tested... - gregkh ] Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 8ce1f2e22912..d415a804fd26 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "hyperv_vmbus.h" /* The one and only */ @@ -103,9 +104,10 @@ static u64 do_hypercall(u64 control, void *input, void *output) return (u64)ULLONG_MAX; __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); - __asm__ __volatile__("call *%3" : "=a" (hv_status) : + __asm__ __volatile__(CALL_NOSPEC : + "=a" (hv_status) : "c" (control), "d" (input_address), - "m" (hypercall_page)); + THUNK_TARGET(hypercall_page)); return hv_status; @@ -123,11 +125,12 @@ static u64 do_hypercall(u64 control, void *input, void *output) if (!hypercall_page) return (u64)ULLONG_MAX; - __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), + __asm__ __volatile__ (CALL_NOSPEC : "=d"(hv_status_hi), "=a"(hv_status_lo) : "d" (control_hi), "a" (control_lo), "b" (input_address_hi), "c" (input_address_lo), "D"(output_address_hi), - "S"(output_address_lo), "m" (hypercall_page)); + "S"(output_address_lo), + THUNK_TARGET(hypercall_page)); return hv_status_lo | ((u64)hv_status_hi << 32); #endif /* !x86_64 */ From 6b222e7483af4fd8f632efbf3b91025c2359b10a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:31 +0000 Subject: [PATCH 016/427] x86/retpoline/xen: Convert Xen hypercall indirect jumps commit ea08816d5b185ab3d09e95e393f265af54560350 upstream. Convert indirect call in Xen hypercall to use non-speculative sequence, when CONFIG_RETPOLINE is enabled. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Reviewed-by: Juergen Gross Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-10-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/xen/hypercall.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 85133b2b8e99..0977e7607046 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -215,9 +216,9 @@ privcmd_call(unsigned call, __HYPERCALL_5ARG(a1, a2, a3, a4, a5); stac(); - asm volatile("call *%[call]" + asm volatile(CALL_NOSPEC : __HYPERCALL_5PARAM - : [call] "a" (&hypercall_page[call]) + : [thunk_target] "a" (&hypercall_page[call]) : __HYPERCALL_CLOBBER5); clac(); From 7e5bb301bd2fdd62cbee7b26a8234cccb6731849 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 11 Jan 2018 21:46:32 +0000 Subject: [PATCH 017/427] x86/retpoline/checksum32: Convert assembler indirect jumps commit 5096732f6f695001fa2d6f1335a2680b37912c69 upstream. Convert all indirect jumps in 32bit checksum assembler code to use non-speculative sequences when CONFIG_RETPOLINE is enabled. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-11-git-send-email-dwmw@amazon.co.uk Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/checksum_32.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S index c1e623209853..90353a26ed95 100644 --- a/arch/x86/lib/checksum_32.S +++ b/arch/x86/lib/checksum_32.S @@ -28,7 +28,8 @@ #include #include #include - +#include + /* * computes a partial checksum, e.g. for TCP/UDP fragments */ @@ -155,7 +156,7 @@ ENTRY(csum_partial) negl %ebx lea 45f(%ebx,%ebx,2), %ebx testl %esi, %esi - jmp *%ebx + JMP_NOSPEC %ebx # Handle 2-byte-aligned regions 20: addw (%esi), %ax @@ -437,7 +438,7 @@ ENTRY(csum_partial_copy_generic) andl $-32,%edx lea 3f(%ebx,%ebx), %ebx testl %esi, %esi - jmp *%ebx + JMP_NOSPEC %ebx 1: addl $64,%esi addl $64,%edi SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) From f72655b837eb4320a1ffebbd0e0ebe92ce1e5314 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 11 Jan 2018 21:46:33 +0000 Subject: [PATCH 018/427] x86/retpoline/irq32: Convert assembler indirect jumps commit 7614e913db1f40fff819b36216484dc3808995d4 upstream. Convert all indirect jumps in 32bit irq inline asm code to use non speculative sequences. Signed-off-by: Andi Kleen Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Acked-by: Ingo Molnar Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515707194-20531-12-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/irq_32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 647089c64d13..528b7aa1780d 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -20,6 +20,7 @@ #include #include +#include #ifdef CONFIG_DEBUG_STACKOVERFLOW @@ -55,11 +56,11 @@ DEFINE_PER_CPU(struct irq_stack *, softirq_stack); static void call_on_stack(void *func, void *stack) { asm volatile("xchgl %%ebx,%%esp \n" - "call *%%edi \n" + CALL_NOSPEC "movl %%ebx,%%esp \n" : "=b" (stack) : "0" (stack), - "D"(func) + [thunk_target] "D"(func) : "memory", "cc", "edx", "ecx", "eax"); } @@ -95,11 +96,11 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc) call_on_stack(print_stack_overflow, isp); asm volatile("xchgl %%ebx,%%esp \n" - "call *%%edi \n" + CALL_NOSPEC "movl %%ebx,%%esp \n" : "=a" (arg1), "=b" (isp) : "0" (desc), "1" (isp), - "D" (desc->handle_irq) + [thunk_target] "D" (desc->handle_irq) : "memory", "cc", "ecx"); return 1; } From eebc3f8adee0a6f43a4789ef0bf5c5b35de8cfe4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 12 Jan 2018 11:11:27 +0000 Subject: [PATCH 019/427] x86/retpoline: Fill return stack buffer on vmexit commit 117cc7a908c83697b0b737d15ae1eb5943afe35b upstream. In accordance with the Intel and AMD documentation, we need to overwrite all entries in the RSB on exiting a guest, to prevent malicious branch target predictions from affecting the host kernel. This is needed both for retpoline and for IBRS. [ak: numbers again for the RSB stuffing labels] Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Tested-by: Peter Zijlstra (Intel) Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515755487-8524-1-git-send-email-dwmw@amazon.co.uk Signed-off-by: David Woodhouse Signed-off-by: Razvan Ghitulete Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/nospec-branch.h | 76 +++++++++++++++++++++++++++- arch/x86/kvm/svm.c | 4 ++ arch/x86/kvm/vmx.c | 4 ++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index fe48aeee79d1..1afd04eb5fb7 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -7,6 +7,48 @@ #include #include +/* + * Fill the CPU return stack buffer. + * + * Each entry in the RSB, if used for a speculative 'ret', contains an + * infinite 'pause; jmp' loop to capture speculative execution. + * + * This is required in various cases for retpoline and IBRS-based + * mitigations for the Spectre variant 2 vulnerability. Sometimes to + * eliminate potentially bogus entries from the RSB, and sometimes + * purely to ensure that it doesn't get empty, which on some CPUs would + * allow predictions from other (unwanted!) sources to be used. + * + * We define a CPP macro such that it can be used from both .S files and + * inline assembly. It's possible to do a .macro and then include that + * from C via asm(".include ") but let's not go there. + */ + +#define RSB_CLEAR_LOOPS 32 /* To forcibly overwrite all entries */ +#define RSB_FILL_LOOPS 16 /* To avoid underflow */ + +/* + * Google experimented with loop-unrolling and this turned out to be + * the optimal version — two calls, each with their own speculation + * trap should their return address end up getting used, in a loop. + */ +#define __FILL_RETURN_BUFFER(reg, nr, sp) \ + mov $(nr/2), reg; \ +771: \ + call 772f; \ +773: /* speculation trap */ \ + pause; \ + jmp 773b; \ +772: \ + call 774f; \ +775: /* speculation trap */ \ + pause; \ + jmp 775b; \ +774: \ + dec reg; \ + jnz 771b; \ + add $(BITS_PER_LONG/8) * nr, sp; + #ifdef __ASSEMBLY__ /* @@ -59,6 +101,19 @@ #else call *\reg #endif +.endm + + /* + * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP + * monstrosity above, manually. + */ +.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req +#ifdef CONFIG_RETPOLINE + ALTERNATIVE "jmp .Lskip_rsb_\@", \ + __stringify(__FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)) \ + \ftr +.Lskip_rsb_\@: +#endif .endm #else /* __ASSEMBLY__ */ @@ -97,7 +152,7 @@ X86_FEATURE_RETPOLINE) # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) -#else /* No retpoline */ +#else /* No retpoline for C / inline asm */ # define CALL_NOSPEC "call *%[thunk_target]\n" # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) #endif @@ -112,5 +167,24 @@ enum spectre_v2_mitigation { SPECTRE_V2_IBRS, }; +/* + * On VMEXIT we must ensure that no RSB predictions learned in the guest + * can be followed in the host, by overwriting the RSB completely. Both + * retpoline and IBRS mitigations for Spectre v2 need this; only on future + * CPUs with IBRS_ATT *might* it be avoided. + */ +static inline void vmexit_fill_RSB(void) +{ +#ifdef CONFIG_RETPOLINE + unsigned long loops = RSB_CLEAR_LOOPS / 2; + + asm volatile (ALTERNATIVE("jmp 910f", + __stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)), + X86_FEATURE_RETPOLINE) + "910:" + : "=&r" (loops), ASM_CALL_CONSTRAINT + : "r" (loops) : "memory" ); +#endif +} #endif /* __ASSEMBLY__ */ #endif /* __NOSPEC_BRANCH_H__ */ diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 900ffb6c28b5..2038e5bacce6 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "trace.h" @@ -3904,6 +3905,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) #endif ); + /* Eliminate branch target predictions from guest mode */ + vmexit_fill_RSB(); + #ifdef CONFIG_X86_64 wrmsrl(MSR_GS_BASE, svm->host.gs_base); #else diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c26255f19603..75d60e40c389 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "trace.h" #include "pmu.h" @@ -8701,6 +8702,9 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) #endif ); + /* Eliminate branch target predictions from guest mode */ + vmexit_fill_RSB(); + /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */ if (debugctlmsr) update_debugctlmsr(debugctlmsr); From 451725c3e785dfc3ede6c65184b96c213181995a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 14 Jan 2018 22:13:29 +0100 Subject: [PATCH 020/427] x86/retpoline: Remove compile time warning commit b8b9ce4b5aec8de9e23cabb0a26b78641f9ab1d6 upstream. Remove the compile time warning when CONFIG_RETPOLINE=y and the compiler does not have retpoline support. Linus rationale for this is: It's wrong because it will just make people turn off RETPOLINE, and the asm updates - and return stack clearing - that are independent of the compiler are likely the most important parts because they are likely the ones easiest to target. And it's annoying because most people won't be able to do anything about it. The number of people building their own compiler? Very small. So if their distro hasn't got a compiler yet (and pretty much nobody does), the warning is just annoying crap. It is already properly reported as part of the sysfs interface. The compile-time warning only encourages bad things. Fixes: 76b043848fd2 ("x86/retpoline: Add initial retpoline support") Requested-by: Linus Torvalds Signed-off-by: Thomas Gleixner Cc: David Woodhouse Cc: Peter Zijlstra (Intel) Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Link: https://lkml.kernel.org/r/CA+55aFzWgquv4i6Mab6bASqYXg3ErV3XDFEYf=GEcCDQg5uAtw@mail.gmail.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 34fdac520edb..1f9caa041bf7 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -194,8 +194,6 @@ ifdef CONFIG_RETPOLINE RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) ifneq ($(RETPOLINE_CFLAGS),) KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE - else - $(warning CONFIG_RETPOLINE=y, but not supported by the compiler. Toolchain update recommended.) endif endif From f1fcb9d2926c378e39adf42ef3446e08b2d63895 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 7 Apr 2017 09:34:12 +0200 Subject: [PATCH 021/427] scsi: sg: disable SET_FORCE_LOW_DMA commit 745dfa0d8ec26b24f3304459ff6e9eacc5c8351b upstream. The ioctl SET_FORCE_LOW_DMA has never worked since the initial git check-in, and the respective setting is nowadays handled correctly. So disable it entirely. Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Tested-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sg.c | 30 +++++++++--------------------- include/scsi/sg.h | 1 - 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 38f77e127349..0f0ff75755e0 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -160,7 +160,6 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ struct list_head rq_list; /* head of request list */ struct fasync_struct *async_qp; /* used by asynchronous notification */ Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */ - char low_dma; /* as in parent but possibly overridden to 1 */ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ @@ -932,24 +931,14 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) /* strange ..., for backward compatibility */ return sfp->timeout_user; case SG_SET_FORCE_LOW_DMA: - result = get_user(val, ip); - if (result) - return result; - if (val) { - sfp->low_dma = 1; - if ((0 == sfp->low_dma) && !sfp->res_in_use) { - val = (int) sfp->reserve.bufflen; - sg_remove_scat(sfp, &sfp->reserve); - sg_build_reserve(sfp, val); - } - } else { - if (atomic_read(&sdp->detaching)) - return -ENODEV; - sfp->low_dma = sdp->device->host->unchecked_isa_dma; - } + /* + * N.B. This ioctl never worked properly, but failed to + * return an error value. So returning '0' to keep compability + * with legacy applications. + */ return 0; case SG_GET_LOW_DMA: - return put_user((int) sfp->low_dma, ip); + return put_user((int) sdp->device->host->unchecked_isa_dma, ip); case SG_GET_SCSI_ID: if (!access_ok(VERIFY_WRITE, p, sizeof (sg_scsi_id_t))) return -EFAULT; @@ -1870,6 +1859,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) int sg_tablesize = sfp->parentdp->sg_tablesize; int blk_size = buff_size, order; gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; + struct sg_device *sdp = sfp->parentdp; if (blk_size < 0) return -EFAULT; @@ -1895,7 +1885,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = num; } - if (sfp->low_dma) + if (sdp->device->host->unchecked_isa_dma) gfp_mask |= GFP_DMA; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) @@ -2158,8 +2148,6 @@ sg_add_sfp(Sg_device * sdp) sfp->timeout = SG_DEFAULT_TIMEOUT; sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER; sfp->force_packid = SG_DEF_FORCE_PACK_ID; - sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ? - sdp->device->host->unchecked_isa_dma : 1; sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; @@ -2618,7 +2606,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) jiffies_to_msecs(fp->timeout), fp->reserve.bufflen, (int) fp->reserve.k_use_sg, - (int) fp->low_dma); + (int) sdp->device->host->unchecked_isa_dma); seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n", (int) fp->cmd_q, (int) fp->force_packid, (int) fp->keep_orphan); diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 3afec7032448..20bc71c3e0b8 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -197,7 +197,6 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ #define SG_DEFAULT_RETRIES 0 /* Defaults, commented if they differ from original sg driver */ -#define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */ #define SG_DEF_FORCE_PACK_ID 0 #define SG_DEF_KEEP_ORPHAN 0 #define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */ From 58c82be944f58561e77eb9db5039a4b0eca96ac5 Mon Sep 17 00:00:00 2001 From: Li Jinyue Date: Thu, 14 Dec 2017 17:04:54 +0800 Subject: [PATCH 022/427] futex: Prevent overflow by strengthen input validation commit fbe0e839d1e22d88810f3ee3e2f1479be4c0aa4a upstream. UBSAN reports signed integer overflow in kernel/futex.c: UBSAN: Undefined behaviour in kernel/futex.c:2041:18 signed integer overflow: 0 - -2147483648 cannot be represented in type 'int' Add a sanity check to catch negative values of nr_wake and nr_requeue. Signed-off-by: Li Jinyue Signed-off-by: Thomas Gleixner Cc: peterz@infradead.org Cc: dvhart@infradead.org Link: https://lkml.kernel.org/r/1513242294-31786-1-git-send-email-lijinyue@huawei.com Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/futex.c b/kernel/futex.c index fc68462801de..1fce19fc824c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1621,6 +1621,9 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, struct futex_q *this, *next; WAKE_Q(wake_q); + if (nr_wake < 0 || nr_requeue < 0) + return -EINVAL; + if (requeue_pi) { /* * Requeue PI only works on two distinct uaddrs. This From 80547bb6154d02279e446526a7d3daf7d5aa15db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Jan 2018 23:48:05 +0100 Subject: [PATCH 023/427] ALSA: pcm: Remove yet superfluous WARN_ON() commit 23b19b7b50fe1867da8d431eea9cd3e4b6328c2c upstream. muldiv32() contains a snd_BUG_ON() (which is morphed as WARN_ON() with debug option) for checking the case of 0 / 0. This would be helpful if this happens only as a logical error; however, since the hw refine is performed with any data set provided by user, the inconsistent values that can trigger such a condition might be passed easily. Actually, syzbot caught this by passing some zero'ed old hw_params ioctl. So, having snd_BUG_ON() there is simply superfluous and rather harmful to give unnecessary confusions. Let's get rid of it. Reported-by: syzbot+7e6ee55011deeebce15d@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/pcm_lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 7b805766306e..4c145d6bccd4 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -578,7 +578,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, { u_int64_t n = (u_int64_t) a * b; if (c == 0) { - snd_BUG_ON(!n); *r = 0; return UINT_MAX; } From a4d7639d5fb65070e43f679493341f1ec4212e6e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Jan 2018 08:34:28 +0100 Subject: [PATCH 024/427] ALSA: hda - Apply headphone noise quirk for another Dell XPS 13 variant commit e4c9fd10eb21376f44723c40ad12395089251c28 upstream. There is another Dell XPS 13 variant (SSID 1028:082a) that requires the existing fixup for reducing the headphone noise. This patch adds the quirk entry for that. BugLink: http://lkml.kernel.org/r/CAHXyb9ZCZJzVisuBARa+UORcjRERV8yokez=DP1_5O5isTz0ZA@mail.gmail.com Reported-and-tested-by: Francisco G. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5875a08d555e..f14c1f288443 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5600,6 +5600,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), + SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), From 478a7fa82ff78be3b7aa94a9994fe0544b931f53 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Jan 2018 10:53:18 +0100 Subject: [PATCH 025/427] ALSA: hda - Apply the existing quirk to iMac 14,1 commit 031f335cda879450095873003abb03ae8ed3b74a upstream. iMac 14,1 requires the same quirk as iMac 12,2, using GPIO 2 and 3 for headphone and speaker output amps. Add the codec SSID quirk entry (106b:0600) accordingly. BugLink: http://lkml.kernel.org/r/CAEw6Zyteav09VGHRfD5QwsfuWv5a43r0tFBNbfcHXoNrxVz7ew@mail.gmail.com Reported-by: Freaky Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 80bbadc83721..d6e079f4ec09 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -408,6 +408,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ /* codec SSID */ + SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), From 48907f2535aa4b5951a0863b8bc7526402388c8d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Dec 2017 18:13:05 -0600 Subject: [PATCH 026/427] af_key: fix buffer overread in verify_address_len() commit 06b335cb51af018d5feeff5dd4fd53847ddb675a upstream. If a message sent to a PF_KEY socket ended with one of the extensions that takes a 'struct sadb_address' but there were not enough bytes remaining in the message for the ->sa_family member of the 'struct sockaddr' which is supposed to follow, then verify_address_len() read past the end of the message, into uninitialized memory. Fix it by returning -EINVAL in this case. This bug was found using syzkaller with KMSAN. Reproducer: #include #include #include int main() { int sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); char buf[24] = { 0 }; struct sadb_msg *msg = (void *)buf; struct sadb_address *addr = (void *)(msg + 1); msg->sadb_msg_version = PF_KEY_V2; msg->sadb_msg_type = SADB_DELETE; msg->sadb_msg_len = 3; addr->sadb_address_len = 1; addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; write(sock, buf, 24); } Reported-by: Alexander Potapenko Signed-off-by: Eric Biggers Signed-off-by: Steffen Klassert Signed-off-by: Greg Kroah-Hartman --- net/key/af_key.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/key/af_key.c b/net/key/af_key.c index 94bf810ad242..ea81a58a4ff6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -401,6 +401,11 @@ static int verify_address_len(const void *p) #endif int len; + if (sp->sadb_address_len < + DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family), + sizeof(uint64_t))) + return -EINVAL; + switch (addr->sa_family) { case AF_INET: len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t)); From b78f2d36e7378f43ba849e90e1f9dbfedd09eaf9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Dec 2017 18:15:23 -0600 Subject: [PATCH 027/427] af_key: fix buffer overread in parse_exthdrs() commit 4e765b4972af7b07adcb1feb16e7a525ce1f6b28 upstream. If a message sent to a PF_KEY socket ended with an incomplete extension header (fewer than 4 bytes remaining), then parse_exthdrs() read past the end of the message, into uninitialized memory. Fix it by returning -EINVAL in this case. Reproducer: #include #include #include int main() { int sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); char buf[17] = { 0 }; struct sadb_msg *msg = (void *)buf; msg->sadb_msg_version = PF_KEY_V2; msg->sadb_msg_type = SADB_DELETE; msg->sadb_msg_len = 2; write(sock, buf, 17); } Signed-off-by: Eric Biggers Signed-off-by: Steffen Klassert Signed-off-by: Greg Kroah-Hartman --- net/key/af_key.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/key/af_key.c b/net/key/af_key.c index ea81a58a4ff6..6482b001f19a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -516,6 +516,9 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void * uint16_t ext_type; int ext_len; + if (len < sizeof(*ehdr)) + return -EINVAL; + ext_len = ehdr->sadb_ext_len; ext_len *= sizeof(uint64_t); ext_type = ehdr->sadb_ext_type; From ec7a002d7796a1831d171159366d71fbcc8bf049 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Mon, 20 Mar 2017 16:42:48 +0100 Subject: [PATCH 028/427] scsi: hpsa: fix volume offline state commit eb94588dabec82e012281608949a860f64752914 upstream. In a previous patch a hpsa_scsi_dev_t.volume_offline update line has been removed, so let us put it back.. Fixes: 85b29008d8 (hpsa: update check for logical volume status) Signed-off-by: Tomas Henzl Acked-by: Don Brace Signed-off-by: Martin K. Petersen Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0c87f341fed4..910b795fc5eb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3638,6 +3638,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, if (h->fw_support & MISC_FW_RAID_OFFLOAD_BASIC) hpsa_get_ioaccel_status(h, scsi3addr, this_device); volume_offline = hpsa_volume_offline(h, scsi3addr); + this_device->volume_offline = volume_offline; if (volume_offline == HPSA_LV_FAILED) { rc = HPSA_LV_FAILED; dev_err(&h->pdev->dev, From 8bd58b61d2faacdacd05287a3bbb32ad226b5428 Mon Sep 17 00:00:00 2001 From: Xunlei Pang Date: Wed, 10 May 2017 21:03:37 +0800 Subject: [PATCH 029/427] sched/deadline: Zero out positive runtime after throttling constrained tasks commit ae83b56a56f8d9643dedbee86b457fa1c5d42f59 upstream. When a contrained task is throttled by dl_check_constrained_dl(), it may carry the remaining positive runtime, as a result when dl_task_timer() fires and calls replenish_dl_entity(), it will not be replenished correctly due to the positive dl_se->runtime. This patch assigns its runtime to 0 if positive after throttling. Signed-off-by: Xunlei Pang Signed-off-by: Peter Zijlstra (Intel) Acked-by: Daniel Bristot de Oliveira Cc: Juri Lelli Cc: Linus Torvalds Cc: Luca Abeni Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Thomas Gleixner Fixes: df8eac8cafce ("sched/deadline: Throttle a constrained deadline task activated after the deadline) Link: http://lkml.kernel.org/r/1494421417-27550-1-git-send-email-xlpang@redhat.com Signed-off-by: Ingo Molnar Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- kernel/sched/deadline.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index a996f7356216..6be2afd9bfd6 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -732,6 +732,8 @@ static inline void dl_check_constrained_dl(struct sched_dl_entity *dl_se) if (unlikely(dl_se->dl_boosted || !start_dl_timer(p))) return; dl_se->dl_throttled = 1; + if (dl_se->runtime > 0) + dl_se->runtime = 0; } } From fba063e6dfb413e06b9daa5d45b164761172f5ed Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Sat, 13 Jan 2018 17:27:30 -0600 Subject: [PATCH 030/427] x86/retpoline: Add LFENCE to the retpoline/RSB filling RSB macros commit 28d437d550e1e39f805d99f9f8ac399c778827b7 upstream. The PAUSE instruction is currently used in the retpoline and RSB filling macros as a speculation trap. The use of PAUSE was originally suggested because it showed a very, very small difference in the amount of cycles/time used to execute the retpoline as compared to LFENCE. On AMD, the PAUSE instruction is not a serializing instruction, so the pause/jmp loop will use excess power as it is speculated over waiting for return to mispredict to the correct target. The RSB filling macro is applicable to AMD, and, if software is unable to verify that LFENCE is serializing on AMD (possible when running under a hypervisor), the generic retpoline support will be used and, so, is also applicable to AMD. Keep the current usage of PAUSE for Intel, but add an LFENCE instruction to the speculation trap for AMD. The same sequence has been adopted by GCC for the GCC generated retpolines. Signed-off-by: Tom Lendacky Signed-off-by: Thomas Gleixner Reviewed-by: Borislav Petkov Acked-by: David Woodhouse Acked-by: Arjan van de Ven Cc: Rik van Riel Cc: Andi Kleen Cc: Paul Turner Cc: Peter Zijlstra Cc: Tim Chen Cc: Jiri Kosina Cc: Dave Hansen Cc: Andy Lutomirski Cc: Josh Poimboeuf Cc: Dan Williams Cc: Linus Torvalds Cc: Greg Kroah-Hartman Cc: Kees Cook Link: https://lkml.kernel.org/r/20180113232730.31060.36287.stgit@tlendack-t1.amdoffice.net Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/nospec-branch.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 1afd04eb5fb7..e28a9ff1246c 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -11,7 +11,7 @@ * Fill the CPU return stack buffer. * * Each entry in the RSB, if used for a speculative 'ret', contains an - * infinite 'pause; jmp' loop to capture speculative execution. + * infinite 'pause; lfence; jmp' loop to capture speculative execution. * * This is required in various cases for retpoline and IBRS-based * mitigations for the Spectre variant 2 vulnerability. Sometimes to @@ -38,11 +38,13 @@ call 772f; \ 773: /* speculation trap */ \ pause; \ + lfence; \ jmp 773b; \ 772: \ call 774f; \ 775: /* speculation trap */ \ pause; \ + lfence; \ jmp 775b; \ 774: \ dec reg; \ @@ -60,6 +62,7 @@ call .Ldo_rop_\@ .Lspec_trap_\@: pause + lfence jmp .Lspec_trap_\@ .Ldo_rop_\@: mov \reg, (%_ASM_SP) @@ -142,6 +145,7 @@ " .align 16\n" \ "901: call 903f;\n" \ "902: pause;\n" \ + " lfence;\n" \ " jmp 902b;\n" \ " .align 16\n" \ "903: addl $4, %%esp;\n" \ From 1782af2835fe6fbff6265a53fb85847fb9c58137 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 16 Jan 2018 12:52:28 -0800 Subject: [PATCH 031/427] module: Add retpoline tag to VERMAGIC commit 6cfb521ac0d5b97470883ff9b7facae264b7ab12 upstream. Add a marker for retpoline to the module VERMAGIC. This catches the case when a non RETPOLINE compiled module gets loaded into a retpoline kernel, making it insecure. It doesn't handle the case when retpoline has been runtime disabled. Even in this case the match of the retcompile status will be enforced. This implies that even with retpoline run time disabled all modules loaded need to be recompiled. Signed-off-by: Andi Kleen Signed-off-by: Thomas Gleixner Reviewed-by: Greg Kroah-Hartman Acked-by: David Woodhouse Cc: rusty@rustcorp.com.au Cc: arjan.van.de.ven@intel.com Cc: jeyu@kernel.org Cc: torvalds@linux-foundation.org Link: https://lkml.kernel.org/r/20180116205228.4890-1-andi@firstfloor.org Signed-off-by: Greg Kroah-Hartman --- include/linux/vermagic.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h index 6f8fbcf10dfb..a3d04934aa96 100644 --- a/include/linux/vermagic.h +++ b/include/linux/vermagic.h @@ -24,10 +24,16 @@ #ifndef MODULE_ARCH_VERMAGIC #define MODULE_ARCH_VERMAGIC "" #endif +#ifdef RETPOLINE +#define MODULE_VERMAGIC_RETPOLINE "retpoline " +#else +#define MODULE_VERMAGIC_RETPOLINE "" +#endif #define VERMAGIC_STRING \ UTS_RELEASE " " \ MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \ - MODULE_ARCH_VERMAGIC + MODULE_ARCH_VERMAGIC \ + MODULE_VERMAGIC_RETPOLINE From aa041f13f8c6761ba985a4aab42c0dab49ec4202 Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Fri, 17 Nov 2017 15:29:21 -0800 Subject: [PATCH 032/427] pipe: avoid round_pipe_size() nr_pages overflow on 32-bit commit d3f14c485867cfb2e0c48aa88c41d0ef4bf5209c upstream. round_pipe_size() contains a right-bit-shift expression which may overflow, which would cause undefined results in a subsequent roundup_pow_of_two() call. static inline unsigned int round_pipe_size(unsigned int size) { unsigned long nr_pages; nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; } PAGE_SIZE is defined as (1UL << PAGE_SHIFT), so: - 4 bytes wide on 32-bit (0 to 0xffffffff) - 8 bytes wide on 64-bit (0 to 0xffffffffffffffff) That means that 32-bit round_pipe_size(), nr_pages may overflow to 0: size=0x00000000 nr_pages=0x0 size=0x00000001 nr_pages=0x1 size=0xfffff000 nr_pages=0xfffff size=0xfffff001 nr_pages=0x0 << ! size=0xffffffff nr_pages=0x0 << ! This is bad because roundup_pow_of_two(n) is undefined when n == 0! 64-bit is not a problem as the unsigned int size is 4 bytes wide (similar to 32-bit) and the larger, 8 byte wide unsigned long, is sufficient to handle the largest value of the bit shift expression: size=0xffffffff nr_pages=100000 Modify round_pipe_size() to return 0 if n == 0 and updates its callers to handle accordingly. Link: http://lkml.kernel.org/r/1507658689-11669-3-git-send-email-joe.lawrence@redhat.com Signed-off-by: Joe Lawrence Reported-by: Mikulas Patocka Reviewed-by: Mikulas Patocka Cc: Al Viro Cc: Jens Axboe Cc: Michael Kerrisk Cc: Randy Dunlap Cc: Josh Poimboeuf Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Dong Jinguang Signed-off-by: Greg Kroah-Hartman --- fs/pipe.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index ab8dad3ccb6a..39eff9a67253 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1001,6 +1001,9 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) { struct pipe_buffer *bufs; + if (!nr_pages) + return -EINVAL; + /* * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't * expect a lot of shrink+grow operations, just free and allocate @@ -1045,13 +1048,19 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) /* * Currently we rely on the pipe array holding a power-of-2 number - * of pages. + * of pages. Returns 0 on error. */ static inline unsigned int round_pipe_size(unsigned int size) { unsigned long nr_pages; + if (size < pipe_min_size) + size = pipe_min_size; + nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (nr_pages == 0) + return 0; + return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; } @@ -1062,13 +1071,18 @@ static inline unsigned int round_pipe_size(unsigned int size) int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, size_t *lenp, loff_t *ppos) { + unsigned int rounded_pipe_max_size; int ret; ret = proc_dointvec_minmax(table, write, buf, lenp, ppos); if (ret < 0 || !write) return ret; - pipe_max_size = round_pipe_size(pipe_max_size); + rounded_pipe_max_size = round_pipe_size(pipe_max_size); + if (rounded_pipe_max_size == 0) + return -EINVAL; + + pipe_max_size = rounded_pipe_max_size; return ret; } From 7fd1335392891188b022f5fa518201710d5be3ac Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 16 Jan 2018 12:20:18 +0100 Subject: [PATCH 033/427] x86/apic/vector: Fix off by one in error path commit 45d55e7bac4028af93f5fa324e69958a0b868e96 upstream. Keith reported the following warning: WARNING: CPU: 28 PID: 1420 at kernel/irq/matrix.c:222 irq_matrix_remove_managed+0x10f/0x120 x86_vector_free_irqs+0xa1/0x180 x86_vector_alloc_irqs+0x1e4/0x3a0 msi_domain_alloc+0x62/0x130 The reason for this is that if the vector allocation fails the error handling code tries to free the failed vector as well, which causes the above imbalance warning to trigger. Adjust the error path to handle this correctly. Fixes: b5dc8e6c21e7 ("x86/irq: Use hierarchical irqdomain to manage CPU interrupt vectors") Reported-by: Keith Busch Signed-off-by: Thomas Gleixner Tested-by: Keith Busch Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1801161217300.1823@nanos Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/vector.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 0988e204f1e3..a41e523536a2 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -359,14 +359,17 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq, irq_data->chip_data = data; irq_data->hwirq = virq + i; err = assign_irq_vector_policy(virq + i, node, data, info); - if (err) + if (err) { + irq_data->chip_data = NULL; + free_apic_chip_data(data); goto error; + } } return 0; error: - x86_vector_free_irqs(domain, virq, i + 1); + x86_vector_free_irqs(domain, virq, i); return err; } From 47970b4ea09c7dc4bb610825a1e72915abb63aca Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 8 Jan 2018 17:20:18 -0800 Subject: [PATCH 034/427] Input: 88pm860x-ts - fix child-node lookup commit 906bf7daa0618d0ef39f4872ca42218c29a3631f upstream. Fix child node-lookup during probe, which ended up searching the whole device tree depth-first starting at parent rather than just matching on its children. To make things worse, the parent node was prematurely freed, while the child node was leaked. Fixes: 2e57d56747e6 ("mfd: 88pm860x: Device tree support") Signed-off-by: Johan Hovold Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/88pm860x-ts.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 251ff2aa0633..7a0dbce4dae9 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -126,7 +126,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, int data, n, ret; if (!np) return -ENODEV; - np = of_find_node_by_name(np, "touch"); + np = of_get_child_by_name(np, "touch"); if (!np) { dev_err(&pdev->dev, "Can't find touch node\n"); return -EINVAL; @@ -144,13 +144,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, if (data) { ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); if (ret < 0) - return -EINVAL; + goto err_put_node; } /* set tsi prebias time */ if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) { ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); if (ret < 0) - return -EINVAL; + goto err_put_node; } /* set prebias & prechg time of pen detect */ data = 0; @@ -161,10 +161,18 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, if (data) { ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); if (ret < 0) - return -EINVAL; + goto err_put_node; } of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x); + + of_node_put(np); + return 0; + +err_put_node: + of_node_put(np); + + return -EINVAL; } #else #define pm860x_touch_dt_init(x, y, z) (-1) From 8e70d4862271b9c7a8300273a3bb895a5c9dbc97 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 9 May 2016 17:01:01 -0700 Subject: [PATCH 035/427] Input: twl6040-vibra - fix DT node memory management commit c52c545ead97fcc2f4f8ea38f1ae3c23211e09a8 upstream. commit e7ec014a47e4 ("Input: twl6040-vibra - update for device tree support") made the separate vibra DT node to a subnode of the twl6040. It now calls of_find_node_by_name() to locate the "vibra" subnode. This function has a side effect to call of_node_put on() for the twl6040 parent node passed in as a parameter. This causes trouble later on. Solution: we must call of_node_get() before of_find_node_by_name() Signed-off-by: H. Nikolaus Schaller Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/twl6040-vibra.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index ea63fad48de6..7221a00168bd 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -262,6 +262,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) int vddvibr_uV = 0; int error; + of_node_get(twl6040_core_dev->of_node); twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node, "vibra"); if (!twl6040_core_node) { From a89e1ac9b0da065fa95ddd33030dcd38231f2b27 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 8 Jan 2018 17:17:48 -0800 Subject: [PATCH 036/427] Input: twl6040-vibra - fix child-node lookup commit dcaf12a8b0bbdbfcfa2be8dff2c4948d9844b4ad upstream. Fix child-node lookup during probe, which ended up searching the whole device tree depth-first starting at parent rather than just matching on its children. Later sanity checks on node properties (which would likely be missing) should prevent this from causing much trouble however, especially as the original premature free of the parent node has already been fixed separately (but that "fix" was apparently never backported to stable). Fixes: e7ec014a47e4 ("Input: twl6040-vibra - update for device tree support") Fixes: c52c545ead97 ("Input: twl6040-vibra - fix DT node memory management") Signed-off-by: Johan Hovold Acked-by: Peter Ujfalusi Tested-by: H. Nikolaus Schaller (on Pyra OMAP5 hardware) Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/twl6040-vibra.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 7221a00168bd..1e968ae37f60 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -262,8 +262,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) int vddvibr_uV = 0; int error; - of_node_get(twl6040_core_dev->of_node); - twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node, + twl6040_core_node = of_get_child_by_name(twl6040_core_dev->of_node, "vibra"); if (!twl6040_core_node) { dev_err(&pdev->dev, "parent of node is missing?\n"); From b6306f3fdcaa21b1544433de50004d13ce59042b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 8 Jan 2018 17:15:06 -0800 Subject: [PATCH 037/427] Input: twl4030-vibra - fix sibling-node lookup commit 5b189201993ab03001a398de731045bfea90c689 upstream. A helper purported to look up a child node based on its name was using the wrong of-helper and ended up prematurely freeing the parent of-node while searching the whole device tree depth-first starting at the parent node. Fixes: 64b9e4d803b1 ("input: twl4030-vibra: Support for DT booted kernel") Fixes: e661d0a04462 ("Input: twl4030-vibra - fix ERROR: Bad of_node_put() warning") Signed-off-by: Johan Hovold Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/twl4030-vibra.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 10c4e3d462f1..7233db002588 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -178,12 +178,14 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, twl4030_vibra_suspend, twl4030_vibra_resume); static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, - struct device_node *node) + struct device_node *parent) { + struct device_node *node; + if (pdata && pdata->coexist) return true; - node = of_find_node_by_name(node, "codec"); + node = of_get_child_by_name(parent, "codec"); if (node) { of_node_put(node); return true; From cf3625004e6c9093dcaa233c6f553b7eba269b50 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 18 Jan 2018 15:53:10 -0500 Subject: [PATCH 038/427] tracing: Fix converting enum's from the map in trace_event_eval_update() commit 1ebe1eaf2f02784921759992ae1fde1a9bec8fd0 upstream. Since enums do not get converted by the TRACE_EVENT macro into their values, the event format displaces the enum name and not the value. This breaks tools like perf and trace-cmd that need to interpret the raw binary data. To solve this, an enum map was created to convert these enums into their actual numbers on boot up. This is done by TRACE_EVENTS() adding a TRACE_DEFINE_ENUM() macro. Some enums were not being converted. This was caused by an optization that had a bug in it. All calls get checked against this enum map to see if it should be converted or not, and it compares the call's system to the system that the enum map was created under. If they match, then they call is processed. To cut down on the number of iterations needed to find the maps with a matching system, since calls and maps are grouped by system, when a match is made, the index into the map array is saved, so that the next call, if it belongs to the same system as the previous call, could start right at that array index and not have to scan all the previous arrays. The problem was, the saved index was used as the variable to know if this is a call in a new system or not. If the index was zero, it was assumed that the call is in a new system and would keep incrementing the saved index until it found a matching system. The issue arises when the first matching system was at index zero. The next map, if it belonged to the same system, would then think it was the first match and increment the index to one. If the next call belong to the same system, it would begin its search of the maps off by one, and miss the first enum that should be converted. This left a single enum not converted properly. Also add a comment to describe exactly what that index was for. It took me a bit too long to figure out what I was thinking when debugging this issue. Link: http://lkml.kernel.org/r/717BE572-2070-4C1E-9902-9F2E0FEDA4F8@oracle.com Fixes: 0c564a538aa93 ("tracing: Add TRACE_DEFINE_ENUM() macro to map enums to their values") Reported-by: Chuck Lever Teste-by: Chuck Lever Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 996f0fd34312..ba5392807912 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2300,6 +2300,7 @@ void trace_event_enum_update(struct trace_enum_map **map, int len) { struct trace_event_call *call, *p; const char *last_system = NULL; + bool first = false; int last_i; int i; @@ -2307,15 +2308,28 @@ void trace_event_enum_update(struct trace_enum_map **map, int len) list_for_each_entry_safe(call, p, &ftrace_events, list) { /* events are usually grouped together with systems */ if (!last_system || call->class->system != last_system) { + first = true; last_i = 0; last_system = call->class->system; } + /* + * Since calls are grouped by systems, the likelyhood that the + * next call in the iteration belongs to the same system as the + * previous call is high. As an optimization, we skip seaching + * for a map[] that matches the call's system if the last call + * was from the same system. That's what last_i is for. If the + * call has the same system as the previous call, then last_i + * will be the index of the first map[] that has a matching + * system. + */ for (i = last_i; i < len; i++) { if (call->class->system == map[i]->system) { /* Save the first system if need be */ - if (!last_i) + if (first) { last_i = i; + first = false; + } update_event_printk(call, map[i]); } } From d5276c0137137dfa89402c52eceeb406f4950404 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 12 Jan 2018 11:12:05 +0100 Subject: [PATCH 039/427] phy: work around 'phys' references to usb-nop-xceiv devices commit b7563e2796f8b23c98afcfea7363194227fa089d upstream. Stefan Wahren reports a problem with a warning fix that was merged for v4.15: we had lots of device nodes with a 'phys' property pointing to a device node that is not compliant with the binding documented in Documentation/devicetree/bindings/phy/phy-bindings.txt This generally works because USB HCD drivers that support both the generic phy subsystem and the older usb-phy subsystem ignore most errors from phy_get() and related calls and then use the usb-phy driver instead. However, it turns out that making the usb-nop-xceiv device compatible with the generic-phy binding changes the phy_get() return code from -EINVAL to -EPROBE_DEFER, and the dwc2 usb controller driver for bcm2835 now returns -EPROBE_DEFER from its probe function rather than ignoring the failure, breaking all USB support on raspberry-pi when CONFIG_GENERIC_PHY is enabled. The same code is used in the dwc3 driver and the usb_add_hcd() function, so a reasonable assumption would be that many other platforms are affected as well. I have reviewed all the related patches and concluded that "usb-nop-xceiv" is the only USB phy that is affected by the change, and since it is by far the most commonly referenced phy, all the other USB phy drivers appear to be used in ways that are are either safe in DT (they don't use the 'phys' property), or in the driver (they already ignore -EPROBE_DEFER from generic-phy when usb-phy is available). To work around the problem, this adds a special case to _of_phy_get() so we ignore any PHY node that is compatible with "usb-nop-xceiv", as we know that this can never load no matter how much we defer. In the future, we might implement a generic-phy driver for "usb-nop-xceiv" and then remove this workaround. Since we generally want older kernels to also want to work with the fixed devicetree files, it would be good to backport the patch into stable kernels as well (3.13+ are possibly affected), even though they don't contain any of the patches that may have caused regressions. Fixes: 014d6da6cb25 ARM: dts: bcm283x: Fix DTC warnings about missing phy-cells Fixes: c5bbf358b790 arm: dts: nspire: Add missing #phy-cells to usb-nop-xceiv Fixes: 44e5dced2ef6 arm: dts: marvell: Add missing #phy-cells to usb-nop-xceiv Fixes: f568f6f554b8 ARM: dts: omap: Add missing #phy-cells to usb-nop-xceiv Fixes: d745d5f277bf ARM: dts: imx51-zii-rdu1: Add missing #phy-cells to usb-nop-xceiv Fixes: 915fbe59cbf2 ARM: dts: imx: Add missing #phy-cells to usb-nop-xceiv Link: https://marc.info/?l=linux-usb&m=151518314314753&w=2 Link: https://patchwork.kernel.org/patch/10158145/ Cc: Felipe Balbi Cc: Eric Anholt Tested-by: Stefan Wahren Acked-by: Rob Herring Tested-by: Hans Verkuil Acked-by: Kishon Vijay Abraham I Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index e7e574dc667a..be1f0276ab23 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -365,6 +365,10 @@ static struct phy *_of_phy_get(struct device_node *np, int index) if (ret) return ERR_PTR(-ENODEV); + /* This phy type handled by the usb-phy subsystem for now */ + if (of_device_is_compatible(args.np, "usb-nop-xceiv")) + return ERR_PTR(-ENODEV); + mutex_lock(&phy_provider_mutex); phy_provider = of_phy_provider_lookup(args.np); if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { From 2d5523bf47b4326ff1279613bfe69982bc4675c1 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 4 Jan 2018 17:53:12 +0100 Subject: [PATCH 040/427] ARM: dts: kirkwood: fix pin-muxing of MPP7 on OpenBlocks A7 commit 56aeb07c914a616ab84357d34f8414a69b140cdf upstream. MPP7 is currently muxed as "gpio", but this function doesn't exist for MPP7, only "gpo" is available. This causes the following error: kirkwood-pinctrl f1010000.pin-controller: unsupported function gpio on pin mpp7 pinctrl core: failed to register map default (6): invalid type given kirkwood-pinctrl f1010000.pin-controller: error claiming hogs: -22 kirkwood-pinctrl f1010000.pin-controller: could not claim hogs: -22 kirkwood-pinctrl f1010000.pin-controller: unable to register pinctrl driver kirkwood-pinctrl: probe of f1010000.pin-controller failed with error -22 So the pinctrl driver is not probed, all device drivers (including the UART driver) do a -EPROBE_DEFER, and therefore the system doesn't really boot (well, it boots, but with no UART, and no devices that require pin-muxing). Back when the Device Tree file for this board was introduced, the definition was already wrong. The pinctrl driver also always described as "gpo" this function for MPP7. However, between Linux 4.10 and 4.11, a hog pin failing to be muxed was turned from a simple warning to a hard error that caused the entire pinctrl driver probe to bail out. This is probably the result of commit 6118714275f0a ("pinctrl: core: Fix pinctrl_register_and_init() with pinctrl_enable()"). This commit fixes the Device Tree to use the proper "gpo" function for MPP7, which fixes the boot of OpenBlocks A7, which was broken since Linux 4.11. Fixes: f24b56cbcd9d ("ARM: kirkwood: add support for OpenBlocks A7 platform") Signed-off-by: Thomas Petazzoni Reviewed-by: Andrew Lunn Signed-off-by: Gregory CLEMENT Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/kirkwood-openblocks_a7.dts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts index d5e3bc518968..d57f48543f76 100644 --- a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts +++ b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts @@ -53,7 +53,8 @@ }; pinctrl: pin-controller@10000 { - pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>; + pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header + &pmx_gpio_header_gpo>; pinctrl-names = "default"; pmx_uart0: pmx-uart0 { @@ -85,11 +86,16 @@ * ground. */ pmx_gpio_header: pmx-gpio-header { - marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28", + marvell,pins = "mpp17", "mpp29", "mpp28", "mpp35", "mpp34", "mpp40"; marvell,function = "gpio"; }; + pmx_gpio_header_gpo: pxm-gpio-header-gpo { + marvell,pins = "mpp7"; + marvell,function = "gpo"; + }; + pmx_gpio_init: pmx-init { marvell,pins = "mpp38"; marvell,function = "gpio"; From 082dfe6141f3a8adab45c7def0d1b1da17545f7c Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Mon, 15 Jan 2018 16:31:19 +0100 Subject: [PATCH 041/427] can: peak: fix potential bug in packet fragmentation commit d8a243af1a68395e07ac85384a2740d4134c67f4 upstream. In some rare conditions when running one PEAK USB-FD interface over a non high-speed USB controller, one useless USB fragment might be sent. This patch fixes the way a USB command is fragmented when its length is greater than 64 bytes and when the underlying USB controller is not a high-speed one. Signed-off-by: Stephane Grosjean Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index ce44a033f63b..64cc86a82b2d 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -184,7 +184,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) void *cmd_head = pcan_usb_fd_cmd_buffer(dev); int err = 0; u8 *packet_ptr; - int i, n = 1, packet_len; + int packet_len; ptrdiff_t cmd_len; /* usb device unregistered? */ @@ -201,17 +201,13 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) } packet_ptr = cmd_head; + packet_len = cmd_len; /* firmware is not able to re-assemble 512 bytes buffer in full-speed */ - if ((dev->udev->speed != USB_SPEED_HIGH) && - (cmd_len > PCAN_UFD_LOSPD_PKT_SIZE)) { - packet_len = PCAN_UFD_LOSPD_PKT_SIZE; - n += cmd_len / packet_len; - } else { - packet_len = cmd_len; - } + if (unlikely(dev->udev->speed != USB_SPEED_HIGH)) + packet_len = min(packet_len, PCAN_UFD_LOSPD_PKT_SIZE); - for (i = 0; i < n; i++) { + do { err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT), @@ -224,7 +220,12 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) } packet_ptr += packet_len; - } + cmd_len -= packet_len; + + if (cmd_len < PCAN_UFD_LOSPD_PKT_SIZE) + packet_len = cmd_len; + + } while (packet_len > 0); return err; } From b7bd013a3fe033280bcc58903c51f087e4989229 Mon Sep 17 00:00:00 2001 From: Xinyu Lin Date: Sun, 17 Dec 2017 20:13:39 +0800 Subject: [PATCH 042/427] libata: apply MAX_SEC_1024 to all LITEON EP1 series devices commit db5ff909798ef0099004ad50a0ff5fde92426fd1 upstream. LITEON EP1 has the same timeout issues as CX1 series devices. Revert max_sectors to the value of 1024. Fixes: e0edc8c54646 ("libata: apply MAX_SEC_1024 to all CX1-JB*-HP devices") Signed-off-by: Xinyu Lin Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b0b77b61c40c..69ec1c5d7152 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4143,6 +4143,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { * https://bugzilla.kernel.org/show_bug.cgi?id=121671 */ { "LITEON CX1-JB*-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 }, + { "LITEON EP1-*", NULL, ATA_HORKAGE_MAX_SEC_1024 }, /* Devices we expect to fail diagnostics */ From 9c7755af771ac1b4ef1fc0e552749aa80d23af32 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 20 Dec 2017 09:56:06 +0000 Subject: [PATCH 043/427] dm btree: fix serious bug in btree_split_beneath() commit bc68d0a43560e950850fc69b58f0f8254b28f6d6 upstream. When inserting a new key/value pair into a btree we walk down the spine of btree nodes performing the following 2 operations: i) space for a new entry ii) adjusting the first key entry if the new key is lower than any in the node. If the _root_ node is full, the function btree_split_beneath() allocates 2 new nodes, and redistibutes the root nodes entries between them. The root node is left with 2 entries corresponding to the 2 new nodes. btree_split_beneath() then adjusts the spine to point to one of the two new children. This means the first key is never adjusted if the new key was lower, ie. operation (ii) gets missed out. This can result in the new key being 'lost' for a period; until another low valued key is inserted that will uncover it. This is a serious bug, and quite hard to make trigger in normal use. A reproducing test case ("thin create devices-in-reverse-order") is available as part of the thin-provision-tools project: https://github.com/jthornber/thin-provisioning-tools/blob/master/functional-tests/device-mapper/dm-tests.scm#L593 Fix the issue by changing btree_split_beneath() so it no longer adjusts the spine. Instead it unlocks both the new nodes, and lets the main loop in btree_insert_raw() relock the appropriate one and make any neccessary adjustments. Reported-by: Monty Pavel Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/persistent-data/dm-btree.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index a1a68209bd36..880b7dee9c52 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -671,23 +671,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) pn->keys[1] = rn->keys[0]; memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64)); - /* - * rejig the spine. This is ugly, since it knows too - * much about the spine - */ - if (s->nodes[0] != new_parent) { - unlock_block(s->info, s->nodes[0]); - s->nodes[0] = new_parent; - } - if (key < le64_to_cpu(rn->keys[0])) { - unlock_block(s->info, right); - s->nodes[1] = left; - } else { - unlock_block(s->info, left); - s->nodes[1] = right; - } - s->count = 2; - + unlock_block(s->info, left); + unlock_block(s->info, right); return 0; } From 7e7b086ef2fec6b1bca061a3082fc1c2701999d5 Mon Sep 17 00:00:00 2001 From: Dennis Yang Date: Tue, 12 Dec 2017 18:21:40 +0800 Subject: [PATCH 044/427] dm thin metadata: THIN_MAX_CONCURRENT_LOCKS should be 6 commit 490ae017f54e55bde382d45ea24bddfb6d1a0aaf upstream. For btree removal, there is a corner case that a single thread could takes 6 locks which is more than THIN_MAX_CONCURRENT_LOCKS(5) and leads to deadlock. A btree removal might eventually call rebalance_children()->rebalance3() to rebalance entries of three neighbor child nodes when shadow_spine has already acquired two write locks. In rebalance3(), it tries to shadow and acquire the write locks of all three child nodes. However, shadowing a child node requires acquiring a read lock of the original child node and a write lock of the new block. Although the read lock will be released after block shadowing, shadowing the third child node in rebalance3() could still take the sixth lock. (2 write locks for shadow_spine + 2 write locks for the first two child nodes's shadow + 1 write lock for the last child node's shadow + 1 read lock for the last child node) Signed-off-by: Dennis Yang Acked-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin-metadata.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 3b67afda430b..e339f4288e8f 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -81,10 +81,14 @@ #define SECTOR_TO_BLOCK_SHIFT 3 /* + * For btree insert: * 3 for btree insert + * 2 for btree lookup used within space map + * For btree remove: + * 2 for shadow spine + + * 4 for rebalance 3 child node */ -#define THIN_MAX_CONCURRENT_LOCKS 5 +#define THIN_MAX_CONCURRENT_LOCKS 6 /* This should be plenty */ #define SPACE_MAP_ROOT_SIZE 128 From 5ecd5c8388f060a02a6b97d9b99d9ea885903568 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 16 Jan 2018 10:23:47 +0000 Subject: [PATCH 045/427] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls commit acfb3b883f6d6a4b5d27ad7fdded11f6a09ae6dd upstream. KVM doesn't follow the SMCCC when it comes to unimplemented calls, and inject an UNDEF instead of returning an error. Since firmware calls are now used for security mitigation, they are becoming more common, and the undef is counter productive. Instead, let's follow the SMCCC which states that -1 must be returned to the caller when getting an unknown function number. Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kvm/handle_exit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index ba93a09eb536..5295aef7c8f0 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -42,7 +42,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) ret = kvm_psci_call(vcpu); if (ret < 0) { - kvm_inject_undefined(vcpu); + vcpu_set_reg(vcpu, 0, ~0UL); return 1; } @@ -51,7 +51,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) { - kvm_inject_undefined(vcpu); + vcpu_set_reg(vcpu, 0, ~0UL); return 1; } From 6b1c99e275c034e4650044a7bb1a0bc274e1eb45 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 26 Dec 2017 23:43:54 -0600 Subject: [PATCH 046/427] x86/cpu, x86/pti: Do not enable PTI on AMD processors commit 694d99d40972f12e59a3696effee8a376b79d7c8 upstream. AMD processors are not subject to the types of attacks that the kernel page table isolation feature protects against. The AMD microarchitecture does not allow memory references, including speculative references, that access higher privileged data when running in a lesser privileged mode when that access would result in a page fault. Disable page table isolation by default on AMD processors by not setting the X86_BUG_CPU_INSECURE feature, which controls whether X86_FEATURE_PTI is set. Signed-off-by: Tom Lendacky Signed-off-by: Thomas Gleixner Reviewed-by: Borislav Petkov Cc: Dave Hansen Cc: Andy Lutomirski Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20171227054354.20369.94587.stgit@tlendack-t1.amdoffice.net Cc: Nick Lowe Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0531c1707b40..f7f2ad3687ee 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -831,8 +831,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) setup_force_cpu_cap(X86_FEATURE_ALWAYS); - /* Assume for now that ALL x86 CPUs are insecure */ - setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); + if (c->x86_vendor != X86_VENDOR_AMD) + setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); setup_force_cpu_bug(X86_BUG_SPECTRE_V1); setup_force_cpu_bug(X86_BUG_SPECTRE_V2); From ff535919c1366b0218113f95c447d92c3aac0c1f Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Tue, 1 Nov 2016 12:46:19 +1100 Subject: [PATCH 047/427] kbuild: modversions for EXPORT_SYMBOL() for asm commit 4efca4ed05cbdfd13ec3e8cb623fb77d6e4ab187 upstream. Allow architectures to create asm/asm-prototypes.h file that provides C prototypes for exported asm functions, which enables proper CRC versions to be generated for them. Signed-off-by: Nicholas Piggin Signed-off-by: Michal Marek [jkosina@suse.cz: folded cc6acc11cad1 fixup in as well ] Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- scripts/Makefile.build | 87 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 01df30af4d4a..18209917e379 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -158,7 +158,8 @@ cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< $(obj)/%.i: $(src)/%.c FORCE $(call if_changed_dep,cc_i_c) -cmd_gensymtypes = \ +# These mirror gensymtypes_S and co below, keep them in synch. +cmd_gensymtypes_c = \ $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ $(GENKSYMS) $(if $(1), -T $(2)) \ $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ @@ -168,7 +169,7 @@ cmd_gensymtypes = \ quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ cmd_cc_symtypes_c = \ set -e; \ - $(call cmd_gensymtypes,true,$@) >/dev/null; \ + $(call cmd_gensymtypes_c,true,$@) >/dev/null; \ test -s $@ || rm -f $@ $(obj)/%.symtypes : $(src)/%.c FORCE @@ -197,9 +198,10 @@ else # the actual value of the checksum generated by genksyms cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< -cmd_modversions = \ + +cmd_modversions_c = \ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ - $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ > $(@D)/.tmp_$(@F:.o=.ver); \ \ $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ @@ -244,7 +246,7 @@ endif define rule_cc_o_c $(call echo-cmd,checksrc) $(cmd_checksrc) \ $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ - $(cmd_modversions) \ + $(cmd_modversions_c) \ $(call echo-cmd,record_mcount) \ $(cmd_record_mcount) \ scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ @@ -253,6 +255,15 @@ define rule_cc_o_c mv -f $(dot-target).tmp $(dot-target).cmd endef +define rule_as_o_S + $(call echo-cmd,as_o_S) $(cmd_as_o_S); \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' > \ + $(dot-target).tmp; \ + $(cmd_modversions_S) \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd +endef + # Built-in and composite module parts $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call cmd,force_checksrc) @@ -281,6 +292,38 @@ modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) $(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) $(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) +# .S file exports must have their C prototypes defined in asm/asm-prototypes.h +# or a file that it includes, in order to get versioned symbols. We build a +# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from +# the .S file (with trailing ';'), and run genksyms on that, to extract vers. +# +# This is convoluted. The .S file must first be preprocessed to run guards and +# expand names, then the resulting exports must be constructed into plain +# EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed +# to make the genksyms input. +# +# These mirror gensymtypes_c and co above, keep them in synch. +cmd_gensymtypes_S = \ + (echo "\#include " ; \ + echo "\#include " ; \ + $(CPP) $(a_flags) $< | \ + grep "\<___EXPORT_SYMBOL\>" | \ + sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ) | \ + $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \ + $(GENKSYMS) $(if $(1), -T $(2)) \ + $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ + $(if $(KBUILD_PRESERVE),-p) \ + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + +quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ +cmd_cc_symtypes_S = \ + set -e; \ + $(call cmd_gensymtypes_S,true,$@) >/dev/null; \ + test -s $@ || rm -f $@ + +$(obj)/%.symtypes : $(src)/%.S FORCE + $(call cmd,cc_symtypes_S) + quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< @@ -288,10 +331,40 @@ $(obj)/%.s: $(src)/%.S FORCE $(call if_changed_dep,as_s_S) quiet_cmd_as_o_S = AS $(quiet_modtag) $@ -cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +ifndef CONFIG_MODVERSIONS +cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +else + +ASM_PROTOTYPES := $(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/asm-prototypes.h) + +ifeq ($(ASM_PROTOTYPES),) +cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +else + +# versioning matches the C process described above, with difference that +# we parse asm-prototypes.h C header to get function definitions. + +cmd_as_o_S = $(CC) $(a_flags) -c -o $(@D)/.tmp_$(@F) $< + +cmd_modversions_S = \ + if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ + $(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + else \ + mv -f $(@D)/.tmp_$(@F) $@; \ + fi; +endif +endif $(obj)/%.o: $(src)/%.S FORCE - $(call if_changed_dep,as_o_S) + $(call if_changed_rule,as_o_S) targets += $(real-objs-y) $(real-objs-m) $(lib-y) targets += $(extra-y) $(MAKECMDGOALS) $(always) From f59e7ce17ba327245c8feb312d447b09d3b98eba Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 18 Jan 2018 16:28:26 +0100 Subject: [PATCH 048/427] x86/mce: Make machine check speculation protected commit 6f41c34d69eb005e7848716bbcafc979b35037d5 upstream. The machine check idtentry uses an indirect branch directly from the low level code. This evades the speculation protection. Replace it by a direct call into C code and issue the indirect call there so the compiler can apply the proper speculation protection. Signed-off-by: Thomas Gleixner Reviewed-by:Borislav Petkov Reviewed-by: David Woodhouse Niced-by: Peter Zijlstra Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1801181626290.1847@nanos Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/entry_64.S | 2 +- arch/x86/include/asm/traps.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 81b1cd533965..a03b22c615d9 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -1031,7 +1031,7 @@ idtentry async_page_fault do_async_page_fault has_error_code=1 #endif #ifdef CONFIG_X86_MCE -idtentry machine_check has_error_code=0 paranoid=1 do_sym=*machine_check_vector(%rip) +idtentry machine_check do_mce has_error_code=0 paranoid=1 #endif /* diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index c3496619740a..156959ca49ce 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -92,6 +92,7 @@ dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long); #ifdef CONFIG_X86_32 dotraplinkage void do_iret_error(struct pt_regs *, long); #endif +dotraplinkage void do_mce(struct pt_regs *, long); static inline int get_si_code(unsigned long condition) { diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 7e8a736d09db..364fbad72e60 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1672,6 +1672,11 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code) void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; +dotraplinkage void do_mce(struct pt_regs *regs, long error_code) +{ + machine_check_vector(regs, error_code); +} + /* * Called for each booted CPU to set up machine checks. * Must be called with preempt off: From 799dc737680a8074a0c7c2d3426b85f4c439377f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 19 Jan 2018 01:14:21 +0900 Subject: [PATCH 049/427] retpoline: Introduce start/end markers of indirect thunk commit 736e80a4213e9bbce40a7c050337047128b472ac upstream. Introduce start/end markers of __x86_indirect_thunk_* functions. To make it easy, consolidate .text.__x86.indirect_thunk.* sections to one .text.__x86.indirect_thunk section and put it in the end of kernel text section and adds __indirect_thunk_start/end so that other subsystem (e.g. kprobes) can identify it. Signed-off-by: Masami Hiramatsu Signed-off-by: Thomas Gleixner Acked-by: David Woodhouse Cc: Andi Kleen Cc: Peter Zijlstra Cc: Ananth N Mavinakayanahalli Cc: Arjan van de Ven Cc: Greg Kroah-Hartman Link: https://lkml.kernel.org/r/151629206178.10241.6828804696410044771.stgit@devbox Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/nospec-branch.h | 3 +++ arch/x86/kernel/vmlinux.lds.S | 7 +++++++ arch/x86/lib/retpoline.S | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index e28a9ff1246c..4f7a5d3fed91 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -171,6 +171,9 @@ enum spectre_v2_mitigation { SPECTRE_V2_IBRS, }; +extern char __indirect_thunk_start[]; +extern char __indirect_thunk_end[]; + /* * On VMEXIT we must ensure that no RSB predictions learned in the guest * can be followed in the host, by overwriting the RSB completely. Both diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 74e4bf11f562..e065065a4dfb 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -104,6 +104,13 @@ SECTIONS IRQENTRY_TEXT *(.fixup) *(.gnu.warning) + +#ifdef CONFIG_RETPOLINE + __indirect_thunk_start = .; + *(.text.__x86.indirect_thunk) + __indirect_thunk_end = .; +#endif + /* End of text section */ _etext = .; } :text = 0x9090 diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index 019a03599bb0..8a8093e9cf01 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -9,7 +9,7 @@ #include .macro THUNK reg - .section .text.__x86.indirect_thunk.\reg + .section .text.__x86.indirect_thunk ENTRY(__x86_indirect_thunk_\reg) CFI_STARTPROC From 9b8bd0d3586842716f5673e7a0922a9c9e1fcbfd Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 19 Jan 2018 01:14:51 +0900 Subject: [PATCH 050/427] kprobes/x86: Blacklist indirect thunk functions for kprobes commit c1804a236894ecc942da7dc6c5abe209e56cba93 upstream. Mark __x86_indirect_thunk_* functions as blacklist for kprobes because those functions can be called from anywhere in the kernel including blacklist functions of kprobes. Signed-off-by: Masami Hiramatsu Signed-off-by: Thomas Gleixner Acked-by: David Woodhouse Cc: Andi Kleen Cc: Peter Zijlstra Cc: Ananth N Mavinakayanahalli Cc: Arjan van de Ven Cc: Greg Kroah-Hartman Link: https://lkml.kernel.org/r/151629209111.10241.5444852823378068683.stgit@devbox Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/retpoline.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index 8a8093e9cf01..e611a124c442 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -25,7 +25,8 @@ ENDPROC(__x86_indirect_thunk_\reg) * than one per register with the correct names. So we do it * the simple and nasty way... */ -#define EXPORT_THUNK(reg) EXPORT_SYMBOL(__x86_indirect_thunk_ ## reg) +#define __EXPORT_THUNK(sym) _ASM_NOKPROBE(sym); EXPORT_SYMBOL(sym) +#define EXPORT_THUNK(reg) __EXPORT_THUNK(__x86_indirect_thunk_ ## reg) #define GENERATE_THUNK(reg) THUNK reg ; EXPORT_THUNK(reg) GENERATE_THUNK(_ASM_AX) From 6cb73eb8045157ea280f0a047777ea1f56547375 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 19 Jan 2018 01:15:20 +0900 Subject: [PATCH 051/427] kprobes/x86: Disable optimizing on the function jumps to indirect thunk commit c86a32c09f8ced67971a2310e3b0dda4d1749007 upstream. Since indirect jump instructions will be replaced by jump to __x86_indirect_thunk_*, those jmp instruction must be treated as an indirect jump. Since optprobe prohibits to optimize probes in the function which uses an indirect jump, it also needs to find out the function which jump to __x86_indirect_thunk_* and disable optimization. Add a check that the jump target address is between the __indirect_thunk_start/end when optimizing kprobe. Signed-off-by: Masami Hiramatsu Signed-off-by: Thomas Gleixner Acked-by: David Woodhouse Cc: Andi Kleen Cc: Peter Zijlstra Cc: Ananth N Mavinakayanahalli Cc: Arjan van de Ven Cc: Greg Kroah-Hartman Link: https://lkml.kernel.org/r/151629212062.10241.6991266100233002273.stgit@devbox Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/kprobes/opt.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index c9d488f3e4cd..ea8e2b846101 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "common.h" @@ -191,7 +192,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src) } /* Check whether insn is indirect jump */ -static int insn_is_indirect_jump(struct insn *insn) +static int __insn_is_indirect_jump(struct insn *insn) { return ((insn->opcode.bytes[0] == 0xff && (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */ @@ -225,6 +226,26 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len) return (start <= target && target <= start + len); } +static int insn_is_indirect_jump(struct insn *insn) +{ + int ret = __insn_is_indirect_jump(insn); + +#ifdef CONFIG_RETPOLINE + /* + * Jump to x86_indirect_thunk_* is treated as an indirect jump. + * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with + * older gcc may use indirect jump. So we add this check instead of + * replace indirect-jump check. + */ + if (!ret) + ret = insn_jump_into_range(insn, + (unsigned long)__indirect_thunk_start, + (unsigned long)__indirect_thunk_end - + (unsigned long)__indirect_thunk_start); +#endif + return ret; +} + /* Decode whole function to ensure any instructions don't jump into target */ static int can_optimize(unsigned long paddr) { From 58f96ac5dba6b66d9fb4e0072e0e01df0360a43f Mon Sep 17 00:00:00 2001 From: "zhenwei.pi" Date: Thu, 18 Jan 2018 09:04:52 +0800 Subject: [PATCH 052/427] x86/pti: Document fix wrong index commit 98f0fceec7f84d80bc053e49e596088573086421 upstream. In section <2. Runtime Cost>, fix wrong index. Signed-off-by: zhenwei.pi Signed-off-by: Thomas Gleixner Cc: dave.hansen@linux.intel.com Link: https://lkml.kernel.org/r/1516237492-27739-1-git-send-email-zhenwei.pi@youruncloud.com Signed-off-by: Greg Kroah-Hartman --- Documentation/x86/pti.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/x86/pti.txt b/Documentation/x86/pti.txt index d11eff61fc9a..5cd58439ad2d 100644 --- a/Documentation/x86/pti.txt +++ b/Documentation/x86/pti.txt @@ -78,7 +78,7 @@ this protection comes at a cost: non-PTI SYSCALL entry code, so requires mapping fewer things into the userspace page tables. The downside is that stacks must be switched at entry time. - d. Global pages are disabled for all kernel structures not + c. Global pages are disabled for all kernel structures not mapped into both kernel and userspace page tables. This feature of the MMU allows different processes to share TLB entries mapping the kernel. Losing the feature means more From 11e619414b69b7f1e47baac72c5be589d86e5393 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 17 Jan 2018 14:53:28 -0800 Subject: [PATCH 053/427] x86/retpoline: Optimize inline assembler for vmexit_fill_RSB commit 3f7d875566d8e79c5e0b2c9a413e91b2c29e0854 upstream. The generated assembler for the C fill RSB inline asm operations has several issues: - The C code sets up the loop register, which is then immediately overwritten in __FILL_RETURN_BUFFER with the same value again. - The C code also passes in the iteration count in another register, which is not used at all. Remove these two unnecessary operations. Just rely on the single constant passed to the macro for the iterations. Signed-off-by: Andi Kleen Signed-off-by: Thomas Gleixner Acked-by: David Woodhouse Cc: dave.hansen@intel.com Cc: gregkh@linuxfoundation.org Cc: torvalds@linux-foundation.org Cc: arjan@linux.intel.com Link: https://lkml.kernel.org/r/20180117225328.15414-1-andi@firstfloor.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/nospec-branch.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 4f7a5d3fed91..492370b9b35b 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -183,15 +183,16 @@ extern char __indirect_thunk_end[]; static inline void vmexit_fill_RSB(void) { #ifdef CONFIG_RETPOLINE - unsigned long loops = RSB_CLEAR_LOOPS / 2; + unsigned long loops; asm volatile (ALTERNATIVE("jmp 910f", __stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)), X86_FEATURE_RETPOLINE) "910:" - : "=&r" (loops), ASM_CALL_CONSTRAINT - : "r" (loops) : "memory" ); + : "=r" (loops), ASM_CALL_CONSTRAINT + : : "memory" ); #endif } + #endif /* __ASSEMBLY__ */ #endif /* __NOSPEC_BRANCH_H__ */ From 38bc402237f8cb68c5f3ab0292c6d5537af38847 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 29 Oct 2017 16:27:21 +0100 Subject: [PATCH 054/427] MIPS: AR7: ensure the port type's FCR value is used commit 0a5191efe06b5103909206e4fbcff81d30283f8e upstream. Since commit aef9a7bd9b67 ("serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers"), the port's default FCR value isn't used in serial8250_do_set_termios anymore, but copied over once in serial8250_config_port and then modified as needed. Unfortunately, serial8250_config_port will never be called if the port is shared between kernel and userspace, and the port's flag doesn't have UPF_BOOT_AUTOCONF, which would trigger a serial8250_config_port as well. This causes garbled output from userspace: [ 5.220000] random: procd urandom read with 49 bits of entropy available ers [kee Fix this by forcing it to be configured on boot, resulting in the expected output: [ 5.250000] random: procd urandom read with 50 bits of entropy available Press the [f] key and hit [enter] to enter failsafe mode Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level Fixes: aef9a7bd9b67 ("serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers") Signed-off-by: Jonas Gorski Cc: Greg Kroah-Hartman Cc: Yoshihiro YUNOMAE Cc: Florian Fainelli Cc: Nicolas Schichan Cc: linux-mips@linux-mips.org Cc: linux-serial@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/17544/ Signed-off-by: Ralf Baechle Cc: James Hogan Signed-off-by: Greg Kroah-Hartman --- arch/mips/ar7/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 3446b6fb3acb..9da4e2292fc7 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -576,7 +576,7 @@ static int __init ar7_register_uarts(void) uart_port.type = PORT_AR7; uart_port.uartclk = clk_get_rate(bus_clk) / 2; uart_port.iotype = UPIO_MEM32; - uart_port.flags = UPF_FIXED_TYPE; + uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF; uart_port.regshift = 2; uart_port.line = 0; From f0d0a93b0e81278e86c7d81c25a54ac4f4b739d2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Jan 2018 19:50:18 +0100 Subject: [PATCH 055/427] Linux 4.4.113 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 07070a1e6292..39019c9d205c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 112 +SUBLEVEL = 113 EXTRAVERSION = NAME = Blurry Fish Butt From e5e9f55c57414100ee436ade5b22918519968e60 Mon Sep 17 00:00:00 2001 From: Meiyou Chen Date: Thu, 25 Jan 2018 14:09:00 +0800 Subject: [PATCH 056/427] drm/rockchip: priority use of highmem Change-Id: Ib1f65ef5ed8afe15bc40b78cb756f6be6ba7687d Signed-off-by: Meiyou Chen --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 51922ef25816..212d9fbc6595 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -593,7 +593,8 @@ rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) drm_gem_object_init(drm, obj, size); mapping = file_inode(obj->filp)->i_mapping; - mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32); + mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE + | __GFP_DMA32); return rk_obj; } From 752d7732ad55c81066e0be035a7fa5b503ed50e7 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Mon, 29 Jan 2018 17:18:18 +0800 Subject: [PATCH 057/427] pwm: rockchip: add pwm en for voppwm voppwm is frame effect, so we need add vop pwm en to indicate the pwm en state. Change-Id: I1492322f99b638c8dc6cf03c87035f28dca3de8f Signed-off-by: Sandy Huang --- drivers/pwm/pwm-rockchip.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 3cc7fce9f5b2..4889c5a0cbc2 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -38,6 +38,7 @@ struct rockchip_pwm_chip { struct clk *pclk; const struct rockchip_pwm_data *data; void __iomem *base; + bool vop_pwm_en; /* indicate voppwm mirror register state */ }; struct rockchip_pwm_regs { @@ -52,6 +53,7 @@ struct rockchip_pwm_data { unsigned int prescaler; bool supports_polarity; bool supports_lock; + bool vop_pwm; u32 enable_conf; u32 enable_conf_mask; }; @@ -129,6 +131,12 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * change the duty and period, that would not be effective. */ ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); + if (pc->data->vop_pwm) { + if (pc->vop_pwm_en) + ctrl |= PWM_ENABLE; + else + ctrl &= ~PWM_ENABLE; + } if (pc->data->supports_lock) { ctrl |= PWM_LOCK_EN; writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); @@ -180,6 +188,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, val &= ~enable_conf; writel_relaxed(val, pc->base + pc->data->regs.ctrl); + if (pc->data->vop_pwm) + pc->vop_pwm_en = enable; if (!enable) clk_disable(pc->clk); @@ -245,6 +255,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = { .prescaler = 2, .supports_polarity = false, .supports_lock = false, + .vop_pwm = false, .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, .enable_conf_mask = BIT(1) | BIT(3), }; @@ -259,6 +270,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = { .prescaler = 1, .supports_polarity = true, .supports_lock = false, + .vop_pwm = false, .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), @@ -274,6 +286,7 @@ static const struct rockchip_pwm_data pwm_data_vop = { .prescaler = 1, .supports_polarity = true, .supports_lock = false, + .vop_pwm = true, .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), @@ -289,6 +302,7 @@ static const struct rockchip_pwm_data pwm_data_v3 = { .prescaler = 1, .supports_polarity = true, .supports_lock = true, + .vop_pwm = false, .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), From d7f22ab4c135b0c69435c4b54a56ee0939a8abe5 Mon Sep 17 00:00:00 2001 From: Huicong Xu Date: Tue, 23 Jan 2018 16:45:34 +0800 Subject: [PATCH 058/427] drm: bridge: dw-hdmi: fix wrong color if get edid error at bootup if get edid error at bootup the input bus format will be set as rgb and hdmi is no reinit, so hdmi color will be wrong if set yuv in uboot, now reinit hdmi in this case. Change-Id: I8d117b6e241079ceab44793f6566adf91e9d84c6 Signed-off-by: Huicong Xu --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 3616265dae0c..3769eed481da 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2598,6 +2598,9 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, connector); struct drm_display_mode *mode = NULL; void *data = hdmi->plat_data->phy_data; + unsigned int in_bus_format = hdmi->hdmi_data.enc_in_bus_format; + unsigned int out_bus_format = hdmi->hdmi_data.enc_out_bus_format; + if (!hdmi->hpd_state || !conn_state->crtc) return; @@ -2629,7 +2632,11 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, hdmi->hdmi_data.video_mode.previous_tmdsclock = mode->clock; hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); hdmi->phy.enabled = true; - return; + if (in_bus_format != hdmi->hdmi_data.enc_in_bus_format || + out_bus_format != hdmi->hdmi_data.enc_out_bus_format) + hdmi->hdmi_data.update = true; + else + return; } if (hdmi->hdmi_data.update) { @@ -3019,6 +3026,20 @@ static void dw_hdmi_attatch_properties(struct dw_hdmi *hdmi) dev_err(hdmi->dev, "unexpected mapping: 0x%x\n", video_mapping); } + + hdmi->hdmi_data.enc_in_bus_format = color; + hdmi->hdmi_data.enc_out_bus_format = color; + /* + * input format will be set as yuv444 when output + * format is yuv420 + */ + if (color == MEDIA_BUS_FMT_UYVY10_1X20) + hdmi->hdmi_data.enc_in_bus_format = + MEDIA_BUS_FMT_YUV10_1X30; + else if (color == MEDIA_BUS_FMT_UYVY8_1X16) + hdmi->hdmi_data.enc_in_bus_format = + MEDIA_BUS_FMT_YUV8_1X24; + } if (ops && ops->attatch_properties) From 408f2a3e6f915ff82fdb246524d76c8524b02f20 Mon Sep 17 00:00:00 2001 From: Huicong Xu Date: Wed, 24 Jan 2018 15:24:30 +0800 Subject: [PATCH 059/427] drm/bridge/synopsys: initialize hdmi variable when bootup with hdmi plugin if bootup with hdmi plugin initialize mtmdsclock to modify voicelessness and set bridge_is_on true to modify green screen when reboot from recovery Change-Id: I0ed9f956d62ab4087cb42a54dafba6a0fc9e5a7e Signed-off-by: Huicong Xu --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 3769eed481da..473358a27f8f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2598,6 +2598,7 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, connector); struct drm_display_mode *mode = NULL; void *data = hdmi->plat_data->phy_data; + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; unsigned int in_bus_format = hdmi->hdmi_data.enc_in_bus_format; unsigned int out_bus_format = hdmi->hdmi_data.enc_out_bus_format; @@ -2611,7 +2612,7 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, * If HDMI is enabled in uboot, it's need to record * drm_display_mode and set phy status to enabled. */ - if (!hdmi->hdmi_data.video_mode.mpixelclock) { + if (!vmode->mpixelclock) { if (hdmi->plat_data->get_enc_in_encoding) hdmi->hdmi_data.enc_in_encoding = hdmi->plat_data->get_enc_in_encoding(data); @@ -2627,11 +2628,17 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, mode = &conn_state->crtc->mode; memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); - hdmi->hdmi_data.video_mode.mpixelclock = mode->clock; - hdmi->hdmi_data.video_mode.previous_pixelclock = mode->clock; - hdmi->hdmi_data.video_mode.previous_tmdsclock = mode->clock; + vmode->mpixelclock = mode->crtc_clock * 1000; + vmode->previous_pixelclock = mode->clock; + vmode->previous_tmdsclock = mode->clock; + vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, + vmode->mpixelclock); + if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) + vmode->mtmdsclock /= 2; + hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); hdmi->phy.enabled = true; + hdmi->bridge_is_on = true; if (in_bus_format != hdmi->hdmi_data.enc_in_bus_format || out_bus_format != hdmi->hdmi_data.enc_out_bus_format) hdmi->hdmi_data.update = true; From d4953cfed336fc3197ba8e98d69ea6a37f2b5fdc Mon Sep 17 00:00:00 2001 From: Huicong Xu Date: Wed, 24 Jan 2018 13:58:39 +0800 Subject: [PATCH 060/427] phy: rockchip: inno-hdmi: fix 4k10 bit display abnormal avoid out of value range calculate catmdsclk when 4k10bit and set scdc high tmds clock ratio when mtmdsclock is more than 340000000 Change-Id: I8aed4c99813e43c69526f3918d5e7024879d3288 Signed-off-by: Huicong Xu --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 14 ++++++++++++++ drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 12 ++++++------ include/drm/bridge/dw_hdmi.h | 1 + 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 473358a27f8f..1f705f0d81b4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1270,6 +1270,20 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) return true; } +void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) +{ + unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock; + + /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ + if (hdmi->connector.display_info.hdmi.scdc.supported) { + if (mtmdsclock > 340000000) + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); + else + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 0); + } +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio); + void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, unsigned char addr) { diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 257d0d0dcc3d..0cb40e2008d6 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -121,6 +121,7 @@ inno_dw_hdmi_phy_init(struct dw_hdmi *dw_hdmi, void *data, struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; inno_dw_hdmi_phy_disable(dw_hdmi, data); + dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi); return phy_power_on(hdmi->phy); } diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c index 5b28b33e8be4..6aea5b23067f 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c @@ -337,22 +337,22 @@ static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, int rate) switch (bus_width) { case 4: - tmdsclk = rate / 2; + tmdsclk = (u32)rate / 2; break; case 5: - tmdsclk = rate * 5 / 8; + tmdsclk = (u32)rate * 5 / 8; break; case 6: - tmdsclk = rate * 3 / 4; + tmdsclk = (u32)rate * 3 / 4; break; case 10: - tmdsclk = rate * 5 / 4; + tmdsclk = (u32)rate * 5 / 4; break; case 12: - tmdsclk = rate * 3 / 2; + tmdsclk = (u32)rate * 3 / 2; break; case 16: - tmdsclk = rate * 2; + tmdsclk = (u32)rate * 2; break; default: tmdsclk = rate; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 29c7c832cb9b..8119bb98f257 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -198,6 +198,7 @@ enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); +void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi); /* PHY configuration */ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, From a25c80973c849fef06b4f3d94af73adcd2df2866 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Mon, 29 Jan 2018 14:52:17 +0800 Subject: [PATCH 061/427] arm64: dts: rockchip: enable usb for 3326/px30 board Change-Id: Id2c4326c9385f4a06a81dbad73d84e207bf9c5c4 Signed-off-by: Weixin Zhou --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 24 +++++++++++++++++++ .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 24 +++++++++++++++++++ .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 16 +++++++++++++ .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 8 ------- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 6d00a0555fed..74a2b948aa45 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -352,6 +352,30 @@ status = "okay"; }; +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + &vopb { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 4bd958e56bea..59b19a7682e8 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -367,6 +367,30 @@ status = "okay"; }; +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + &vopb { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 1f2a258f0f21..ae5e6a3c4f82 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -271,6 +271,22 @@ status = "okay"; }; +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_xfer &uart1_cts>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index f1c4a2cd4f49..1caf72c229f5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -420,14 +420,6 @@ status = "okay"; }; -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host0_ohci { - status = "okay"; -}; - &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_xfer &uart1_cts>; From dc26e28d833b9bd6dbfda6839e82ff068ea43886 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Tue, 30 Jan 2018 09:46:01 +0800 Subject: [PATCH 062/427] arm64: dts: rockchip: enable rk_rga for 3326/px30 board Change-Id: I5f98d63b2073c037a41d367639c19a962dbf79c4 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 74a2b948aa45..87f2ebdd1ac6 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -316,6 +316,10 @@ status = "okay"; }; +&rk_rga { + status = "okay"; +}; + &route_dsi { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 59b19a7682e8..96edcec81dbd 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -331,6 +331,10 @@ status = "okay"; }; +&rk_rga { + status = "okay"; +}; + &route_dsi { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index ae5e6a3c4f82..289d0f363cba 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -241,6 +241,10 @@ }; }; +&rk_rga { + status = "okay"; +}; + &route_dsi { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 1caf72c229f5..1e7c22e0a72a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -400,6 +400,10 @@ status = "okay"; }; +&rk_rga { + status = "okay"; +}; + &route_lvds { status = "disabled"; }; From f479e502c8abece5402e0936da50d363a2121327 Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 30 Jan 2018 19:31:44 +0800 Subject: [PATCH 063/427] pinctrl: rockchip: Fix some clang warnings This patch fixes the following warnings: drivers/pinctrl/pinctrl-rockchip.c:1869:9: warning: 1st function call argument is an uninitialized value ret = regmap_read(extra_regmap, extra_reg, &temp); ^ drivers/pinctrl/pinctrl-rockchip.c:1999:48: warning: The left operand of '+' is a garbage value data = ((1 << rmask_bits) - 1) << (extra_bit + 16); ^ Change-Id: Ie1bfe825925505314d5d9a4d5491e38768916dbd Signed-off-by: David Wu --- drivers/pinctrl/pinctrl-rockchip.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 3ff72716424b..a76248afba1f 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1844,6 +1844,9 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, break; case DRV_TYPE_IO_WIDE_LEVEL: + if (!ctrl->drv_calc_extra_reg) + return -EINVAL; + rmask_bits = RK3288_DRV_BITS_PER_PIN; /* enable the write to the equivalent lower bits */ ret = regmap_read(regmap, reg, &data); @@ -1856,11 +1859,10 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, * assume the drive strength of N channel and * P channel are the same. */ - if (ctrl->drv_calc_extra_reg) - ctrl->drv_calc_extra_reg(bank, pin_num, - &extra_regmap, - &extra_reg, - &extra_bit); + ctrl->drv_calc_extra_reg(bank, pin_num, + &extra_regmap, + &extra_reg, + &extra_bit); /* * It is enough to read one channel drive strength, @@ -1981,6 +1983,9 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, } break; case DRV_TYPE_IO_WIDE_LEVEL: + if (!ctrl->drv_calc_extra_reg) + return -EINVAL; + extra_value = ((strength - rockchip_perpin_drv_list[drv_type][ret])) >> 1; rmask_bits = RK3288_DRV_BITS_PER_PIN; @@ -1989,11 +1994,10 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, * assume the drive strength of N channel and * P channel are the same. */ - if (ctrl->drv_calc_extra_reg) - extra_drv_type = ctrl->drv_calc_extra_reg(bank, pin_num, - &extra_regmap, - &extra_reg, - &extra_bit); + extra_drv_type = ctrl->drv_calc_extra_reg(bank, pin_num, + &extra_regmap, + &extra_reg, + &extra_bit); /* enable the write to the equivalent lower bits */ data = ((1 << rmask_bits) - 1) << (extra_bit + 16); From 6a9f858a8de468e6b74e3fd884ff73fea72bb1e2 Mon Sep 17 00:00:00 2001 From: Meng Dongyang Date: Mon, 29 Jan 2018 18:30:39 +0800 Subject: [PATCH 064/427] phy: rockchip: rockchip-inno-usb2: tuning pre-emphasize for rk3399 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In current code, the pre-emphasize in eop state and chirp state are disabled only if we add “rockchip,u2phy-tuning†property in RK3399 dts, But we find that if we enable the pre-emphasize of sop/eop/chirp state for rk3399 by default, it will cause usb2 compliance test item - EL_8 and EL_9 failure, so disable the pre-emphasize of sop/eop/chirp state by default. And this can also help to avoid mis-trigger the disconnect detection or high-speed handshake failure. Change-Id: I5ceac9c88de4cdae5af904e973124c194f7718f6 Signed-off-by: Meng Dongyang --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 1eeffd1ed2bb..078d535585cc 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -1827,6 +1827,30 @@ static int rk3399_usb2phy_tuning(struct rockchip_usb2phy *rphy) struct device_node *node = rphy->dev->of_node; int ret = 0; + if (rphy->phy_cfg->reg == 0xe450) { + /* + * Disable the pre-emphasize in eop state + * and chirp state to avoid mis-trigger the + * disconnect detection and also avoid hs + * handshake fail for PHY0. + */ + ret |= regmap_write(rphy->grf, 0x4480, + GENMASK(17, 16) | 0x0); + ret |= regmap_write(rphy->grf, 0x44b4, + GENMASK(17, 16) | 0x0); + } else { + /* + * Disable the pre-emphasize in eop state + * and chirp state to avoid mis-trigger the + * disconnect detection and also avoid hs + * handshake fail for PHY1. + */ + ret |= regmap_write(rphy->grf, 0x4500, + GENMASK(17, 16) | 0x0); + ret |= regmap_write(rphy->grf, 0x4534, + GENMASK(17, 16) | 0x0); + } + if (!of_property_read_bool(node, "rockchip,u2phy-tuning")) return ret; @@ -1842,17 +1866,6 @@ static int rk3399_usb2phy_tuning(struct rockchip_usb2phy *rphy) ret |= regmap_write(rphy->grf, 0x44b0, GENMASK(18, 16) | 0x07); - /* - * Disable the pre-emphasize in eop state - * and chirp state to avoid mis-trigger the - * disconnect detection and also avoid hs - * handshake fail for PHY0. - */ - ret |= regmap_write(rphy->grf, 0x4480, - GENMASK(17, 16) | 0x0); - ret |= regmap_write(rphy->grf, 0x44b4, - GENMASK(17, 16) | 0x0); - /* * Set PHY0 A port squelch trigger point to 125mv */ @@ -1870,17 +1883,6 @@ static int rk3399_usb2phy_tuning(struct rockchip_usb2phy *rphy) ret |= regmap_write(rphy->grf, 0x4530, GENMASK(18, 16) | 0x07); - /* - * Disable the pre-emphasize in eop state - * and chirp state to avoid mis-trigger the - * disconnect detection and also avoid hs - * handshake fail for PHY1. - */ - ret |= regmap_write(rphy->grf, 0x4500, - GENMASK(17, 16) | 0x0); - ret |= regmap_write(rphy->grf, 0x4534, - GENMASK(17, 16) | 0x0); - /* * Set PHY1 A port squelch trigger point to 125mv */ From e9e837490f7d01a2013446af76537282caae077b Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Thu, 25 Jan 2018 08:56:40 +0800 Subject: [PATCH 065/427] drm/rockchip: lvds: remove unused code Change-Id: I88eedd97d926017a350f76085b5d4292caa6d0e4 Signed-off-by: Wyon Bi --- .../display/rockchip/rockchip-lvds.txt | 10 +- drivers/gpu/drm/rockchip/rockchip_lvds.c | 141 ++++-------------- 2 files changed, 31 insertions(+), 120 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt index 837f9e9c6cd5..cbf4a75ba1df 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt @@ -1,4 +1,4 @@ -Rockchip RK3288 LVDS interface +Rockchip SoCs LVDS interface ================================ Required properties: @@ -29,10 +29,6 @@ For px30 rgb output: - pinctrl-names: must contain a "m0" or "m1" entry. - pinctrl-0: pin control group to be used for this controller. -Optional properties -- pinctrl-names: must contain a "lcdc" entry. -- pinctrl-0: pin control group to be used for this controller. - Required nodes: The lvds has two video ports as described by @@ -95,8 +91,6 @@ For Rockchip RK3288: reg = <0xff96c000 0x4000>; clocks = <&cru PCLK_LVDS_PHY>; clock-names = "pclk_lvds"; - pinctrl-names = "lcdc"; - pinctrl-0 = <&lcdc_ctl>; avdd1v0-supply = <&vdd10_lcd>; avdd1v8-supply = <&vcc18_lcd>; avdd3v3-supply = <&vcca_33>; @@ -140,8 +134,6 @@ For Rockchip RK3368: clock-names = "pclk_lvds", "pclk_lvds_ctl"; power-domains = <&power RK3368_PD_VIO>; rockchip,grf = <&grf>; - pinctrl-names = "lcdc"; - pinctrl-0 = <&lcdc_lcdc>; ports { diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 10f1cfe24361..17f24b292483 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -16,13 +16,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -60,7 +60,6 @@ struct rockchip_lvds_soc_data { }; struct rockchip_lvds { - void *base; struct device *dev; void __iomem *regs; void __iomem *regs_ctrl; @@ -73,19 +72,15 @@ struct rockchip_lvds { int output; int format; - struct drm_device *drm_dev; struct drm_panel *panel; struct drm_bridge *bridge; struct drm_connector connector; struct drm_encoder encoder; + struct drm_display_mode mode; - struct mutex suspend_lock; - int suspend; struct pinctrl *pinctrl; - struct pinctrl_state *pins_lcdc; struct pinctrl_state *pins_m0; struct pinctrl_state *pins_m1; - struct drm_display_mode mode; }; static inline void lvds_writel(struct rockchip_lvds *lvds, u32 offset, u32 val) @@ -431,9 +426,8 @@ static const struct drm_connector_funcs rockchip_lvds_connector_funcs = { static int rockchip_lvds_connector_get_modes(struct drm_connector *connector) { struct rockchip_lvds *lvds = connector_to_lvds(connector); - struct drm_panel *panel = lvds->panel; - return panel->funcs->get_modes(panel); + return drm_panel_get_modes(lvds->panel); } static struct drm_encoder * @@ -444,13 +438,6 @@ rockchip_lvds_connector_best_encoder(struct drm_connector *connector) return &lvds->encoder; } -static enum drm_mode_status rockchip_lvds_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode) -{ - return MODE_OK; -} - static int rockchip_lvds_connector_loader_protect(struct drm_connector *connector, bool on) @@ -466,61 +453,10 @@ int rockchip_lvds_connector_loader_protect(struct drm_connector *connector, static const struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs = { .get_modes = rockchip_lvds_connector_get_modes, - .mode_valid = rockchip_lvds_connector_mode_valid, .best_encoder = rockchip_lvds_connector_best_encoder, .loader_protect = rockchip_lvds_connector_loader_protect, }; -static void rockchip_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct rockchip_lvds *lvds = encoder_to_lvds(encoder); - int ret; - - mutex_lock(&lvds->suspend_lock); - - switch (mode) { - case DRM_MODE_DPMS_ON: - if (!lvds->suspend) - goto out; - - drm_panel_prepare(lvds->panel); - ret = rockchip_lvds_poweron(lvds); - if (ret < 0) { - drm_panel_unprepare(lvds->panel); - goto out; - } - drm_panel_enable(lvds->panel); - - lvds->suspend = false; - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - if (lvds->suspend) - goto out; - - drm_panel_disable(lvds->panel); - rockchip_lvds_poweroff(lvds); - drm_panel_unprepare(lvds->panel); - - lvds->suspend = true; - break; - default: - break; - } - -out: - mutex_unlock(&lvds->suspend_lock); -} - -static bool -rockchip_lvds_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted) @@ -540,11 +476,6 @@ static void rockchip_lvds_grf_config(struct drm_encoder *encoder, u32 val; int ret; - /* iomux to LCD data/sync mode */ - if (lvds->output == DISPLAY_OUTPUT_RGB) - if (lvds->pins_lcdc) - pinctrl_select_state(lvds->pinctrl, lvds->pins_lcdc); - if (LVDS_CHIP(lvds) == RK3288_LVDS) { val = lvds->format; if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) @@ -743,14 +674,29 @@ static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) { struct rockchip_lvds *lvds = encoder_to_lvds(encoder); - rockchip_lvds_encoder_dpms(encoder, DRM_MODE_DPMS_ON); + if (lvds->panel) + drm_panel_prepare(lvds->panel); + + rockchip_lvds_poweron(lvds); + + if (lvds->panel) + drm_panel_enable(lvds->panel); + rockchip_lvds_grf_config(encoder, &lvds->mode); rockchip_lvds_set_vop_source(lvds, encoder); } static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) { - rockchip_lvds_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + + if (lvds->panel) + drm_panel_disable(lvds->panel); + + rockchip_lvds_poweroff(lvds); + + if (lvds->panel) + drm_panel_unprepare(lvds->panel); } static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, @@ -768,7 +714,6 @@ static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, static const struct drm_encoder_helper_funcs rockchip_lvds_encoder_helper_funcs = { - .mode_fixup = rockchip_lvds_encoder_mode_fixup, .mode_set = rockchip_lvds_encoder_mode_set, .enable = rockchip_lvds_encoder_enable, .disable = rockchip_lvds_encoder_disable, @@ -854,7 +799,6 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master, struct device_node *port, *endpoint; int ret, i; const char *name; - lvds->drm_dev = drm_dev; port = of_graph_get_port_by_id(dev->of_node, 1); if (!port) { @@ -948,7 +892,6 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master, if (lvds->panel) { connector = &lvds->connector; - connector->dpms = DRM_MODE_DPMS_OFF; ret = drm_connector_init(drm_dev, connector, &rockchip_lvds_connector_funcs, DRM_MODE_CONNECTOR_LVDS); @@ -1005,8 +948,6 @@ static void rockchip_lvds_unbind(struct device *dev, struct device *master, { struct rockchip_lvds *lvds = dev_get_drvdata(dev); - rockchip_lvds_encoder_dpms(&lvds->encoder, DRM_MODE_DPMS_OFF); - drm_panel_detach(lvds->panel); drm_connector_cleanup(&lvds->connector); @@ -1024,37 +965,23 @@ static int rockchip_lvds_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_lvds *lvds; - const struct of_device_id *match; struct resource *res; int ret; - if (!dev->of_node) - return -ENODEV; - - lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); + lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL); if (!lvds) return -ENOMEM; lvds->dev = dev; - lvds->suspend = true; - match = of_match_node(rockchip_lvds_dt_ids, dev->of_node); - lvds->soc_data = match->data; + lvds->soc_data = of_device_get_match_data(dev); + platform_set_drvdata(pdev, lvds); - if (LVDS_CHIP(lvds) == RK3288_LVDS) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lvds->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(lvds->regs)) - return PTR_ERR(lvds->regs); - } else { - /* lvds regs on MIPIPHY_REG */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "mipi_lvds_phy"); - lvds->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(lvds->regs)) { - dev_err(&pdev->dev, "ioremap lvds phy reg failed\n"); - return PTR_ERR(lvds->regs); - } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lvds->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(lvds->regs)) + return PTR_ERR(lvds->regs); + if (!(LVDS_CHIP(lvds) == RK3288_LVDS)) { /* pll lock on status reg that is MIPICTRL Register */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_lvds_ctl"); @@ -1075,7 +1002,8 @@ static int rockchip_lvds_probe(struct platform_device *pdev) lvds->hclk_ctrl = NULL; } } - lvds->pclk = devm_clk_get(&pdev->dev, "pclk_lvds"); + + lvds->pclk = devm_clk_get(dev, "pclk_lvds"); if (IS_ERR(lvds->pclk)) { dev_err(dev, "could not get pclk_lvds\n"); return PTR_ERR(lvds->pclk); @@ -1086,12 +1014,6 @@ static int rockchip_lvds_probe(struct platform_device *pdev) dev_info(dev, "no pinctrl handle\n"); lvds->pinctrl = NULL; } else { - lvds->pins_lcdc = pinctrl_lookup_state(lvds->pinctrl, "lcdc"); - if (IS_ERR(lvds->pins_lcdc)) { - dev_info(dev, "no lcdc pinctrl state\n"); - lvds->pins_lcdc = NULL; - } - lvds->pins_m0 = pinctrl_lookup_state(lvds->pinctrl, "m0"); if (IS_ERR(lvds->pins_m0)) { dev_info(dev, "no m0 pinctrl state\n"); @@ -1112,9 +1034,6 @@ static int rockchip_lvds_probe(struct platform_device *pdev) return PTR_ERR(lvds->grf); } - dev_set_drvdata(dev, lvds); - mutex_init(&lvds->suspend_lock); - if (lvds->pclk) { ret = clk_prepare(lvds->pclk); if (ret < 0) { From beec40337357808cf351afa5f5b57826255797a3 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 08:56:14 +0800 Subject: [PATCH 066/427] drm/rockchip: lvds: Fix clock handing Change-Id: I59bf0aa2969b3e9a192ec8c0cd785906951f4980 Signed-off-by: Wyon Bi --- drivers/gpu/drm/rockchip/rockchip_lvds.c | 94 +++--------------------- 1 file changed, 12 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 17f24b292483..be84f48a17dd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -312,35 +312,6 @@ static int rk336x_lvds_poweron(struct rockchip_lvds *lvds) static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) { - int ret; - - if (lvds->pclk) { - ret = clk_enable(lvds->pclk); - if (ret < 0) { - dev_err(lvds->dev, "failed to enable lvds pclk %d\n", ret); - return ret; - } - } - if (lvds->pclk_ctrl) { - ret = clk_enable(lvds->pclk_ctrl); - if (ret < 0) { - dev_err(lvds->dev, "failed to enable lvds pclk_ctrl %d\n", ret); - return ret; - } - } - - if (lvds->hclk_ctrl) { - ret = clk_enable(lvds->hclk_ctrl); - if (ret < 0) { - dev_err(lvds->dev, "failed to enable lvds hclk_ctrl %d\n", ret); - return ret; - } - } - ret = pm_runtime_get_sync(lvds->dev); - if (ret < 0) { - dev_err(lvds->dev, "failed to get pm runtime: %d\n", ret); - return ret; - } if (LVDS_CHIP(lvds) == RK3288_LVDS) rk3288_lvds_poweron(lvds); else @@ -363,10 +334,6 @@ static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) lvds->soc_data->grf_soc_con7, 0xffff8000); if (ret != 0) dev_err(lvds->dev, "Could not write to GRF: %d\n", ret); - - pm_runtime_put(lvds->dev); - if (lvds->pclk) - clk_disable(lvds->pclk); } else if ((LVDS_CHIP(lvds) == RK336X_LVDS) || (LVDS_CHIP(lvds) == RK3126_LVDS)) { if (LVDS_CHIP(lvds) == RK336X_LVDS) @@ -392,13 +359,6 @@ static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) /* disable lvds */ lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN, v_LVDS_EN(0) | v_TTL_EN(0)); - pm_runtime_put(lvds->dev); - if (lvds->pclk) - clk_disable(lvds->pclk); - if (lvds->pclk_ctrl) - clk_disable(lvds->pclk_ctrl); - if (lvds->hclk_ctrl) - clk_disable(lvds->hclk_ctrl); } } @@ -674,6 +634,11 @@ static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) { struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + clk_prepare_enable(lvds->pclk); + clk_prepare_enable(lvds->pclk_ctrl); + clk_prepare_enable(lvds->hclk_ctrl); + pm_runtime_get_sync(lvds->dev); + if (lvds->panel) drm_panel_prepare(lvds->panel); @@ -697,6 +662,11 @@ static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) if (lvds->panel) drm_panel_unprepare(lvds->panel); + + pm_runtime_put(lvds->dev); + clk_disable_unprepare(lvds->hclk_ctrl); + clk_disable_unprepare(lvds->pclk_ctrl); + clk_disable_unprepare(lvds->pclk); } static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, @@ -966,7 +936,6 @@ static int rockchip_lvds_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rockchip_lvds *lvds; struct resource *res; - int ret; lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL); if (!lvds) @@ -1034,52 +1003,13 @@ static int rockchip_lvds_probe(struct platform_device *pdev) return PTR_ERR(lvds->grf); } - if (lvds->pclk) { - ret = clk_prepare(lvds->pclk); - if (ret < 0) { - dev_err(dev, "failed to prepare pclk_lvds\n"); - return ret; - } - } - if (lvds->pclk_ctrl) { - ret = clk_prepare(lvds->pclk_ctrl); - if (ret < 0) { - dev_err(dev, "failed to prepare pclk_ctrl lvds\n"); - return ret; - } - } - - if (lvds->hclk_ctrl) { - ret = clk_prepare(lvds->hclk_ctrl); - if (ret < 0) { - dev_err(dev, "failed to prepare hclk_ctrl lvds\n"); - return ret; - } - } - ret = component_add(&pdev->dev, &rockchip_lvds_component_ops); - if (ret < 0) { - if (lvds->pclk) - clk_unprepare(lvds->pclk); - if (lvds->pclk_ctrl) - clk_unprepare(lvds->pclk_ctrl); - if (lvds->hclk_ctrl) - clk_unprepare(lvds->hclk_ctrl); - } - - return ret; + return component_add(dev, &rockchip_lvds_component_ops); } static int rockchip_lvds_remove(struct platform_device *pdev) { - struct rockchip_lvds *lvds = dev_get_drvdata(&pdev->dev); - component_del(&pdev->dev, &rockchip_lvds_component_ops); - if (lvds->pclk) - clk_unprepare(lvds->pclk); - if (lvds->pclk_ctrl) - clk_unprepare(lvds->pclk_ctrl); - if (lvds->hclk_ctrl) - clk_unprepare(lvds->hclk_ctrl); + return 0; } From 036d3e05f3f8b99111b1c0d05737289bb3dda9ee Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 16:22:14 +0800 Subject: [PATCH 067/427] arm64: dts: rockchip: rk3368: remove pinctrl settings from lvds node Change-Id: I89244be50902f7f76cc6e776decb93a83bbb063b Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/rk3368.dtsi | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index 4c30cc98af91..91c37468acde 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -1540,9 +1540,6 @@ clock-names = "pclk_lvds", "pclk_lvds_ctl"; power-domains = <&power RK3368_PD_VIO>; rockchip,grf = <&grf>; - pinctrl-names = "lcdc", "gpio"; - pinctrl-0 = <&lcdc_lcdc>; - pinctrl-1 = <&lcdc_gpio>; status = "disabled"; ports { From 145c5d7914e1147a956198daa67ee06409950c0e Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 30 Jan 2018 15:21:31 +0800 Subject: [PATCH 068/427] arm64: dts: rockchip: rk3368-r88: add pinctrl settings for lvds node Change-Id: I00dac84176e81332d16408e987e4873d17de37e6 Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index ec5cd25ee877..2d8254f30408 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -469,6 +469,9 @@ }; &lvds { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lcdc_lcdc>; + pinctrl-1 = <&lcdc_gpio>; status = "okay"; ports { From 01007bae4db8a86c6b2a2814b846a1dede70cce8 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 16:21:16 +0800 Subject: [PATCH 069/427] arm64: dts: rockchip: rk3366: remove pinctrl settings from lvds node Change-Id: I07b01df67c006d14d19bc2277dc90d0e947793dd Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/rk3366.dtsi | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3366.dtsi b/arch/arm64/boot/dts/rockchip/rk3366.dtsi index d9891e96a030..8032a7ee20c9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3366.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3366.dtsi @@ -1078,9 +1078,6 @@ clocks = <&cru PCLK_DPHYTX>, <&cru PCLK_MIPI_DSI0>; clock-names = "pclk_lvds", "pclk_lvds_ctl"; power-domains = <&power RK3366_PD_VIO>; - pinctrl-names = "lcdc", "gpio"; - pinctrl-0 = <&lcdc_lcdc>; - pinctrl-1 = <&lcdc_gpio>; rockchip,grf = <&grf>; status = "disabled"; From ba7bf2b5327a26a7f2f263ba667faa8c908a6dd2 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 16:22:51 +0800 Subject: [PATCH 070/427] ARM: dts: rockchip: rk3288: remove pinctrl settings from lvds node Change-Id: I22d95e660cba8f982ad6fbc869ea8b8286d5a641 Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3288.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 0af92bd2a723..e3b526f03339 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1490,8 +1490,6 @@ reg = <0x0 0xff96c000 0x0 0x4000>; clocks = <&cru PCLK_LVDS_PHY>; clock-names = "pclk_lvds"; - pinctrl-names = "lcdc"; - pinctrl-0 = <&lcdc_ctl>; power-domains = <&power RK3288_PD_VIO>; rockchip,grf = <&grf>; status = "disabled"; From df99532769388f4b40343b39ff784a718516f426 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 30 Jan 2018 15:32:38 +0800 Subject: [PATCH 071/427] ARM: dts: rockchip: rk3288-popmetal-android: add pinctrl settings for lvds node Change-Id: I435afb883ec6d3ee07523e1e933dfb3c564cd504 Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3288-popmetal-android.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-popmetal-android.dts b/arch/arm/boot/dts/rk3288-popmetal-android.dts index bac65797fd3b..faac6f5abadd 100644 --- a/arch/arm/boot/dts/rk3288-popmetal-android.dts +++ b/arch/arm/boot/dts/rk3288-popmetal-android.dts @@ -223,6 +223,8 @@ }; &lvds { + pinctrl-names = "default"; + pinctrl-0 = <&lcdc_ctl>; status = "okay"; }; From 5aca9d69acfb8292a0c9738ea8e7f44a348678ba Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 30 Jan 2018 15:34:36 +0800 Subject: [PATCH 072/427] ARM: dts: rockchip: rk3288-popmetal-android-vga: add pinctrl settings for lvds node Change-Id: I75466dc63ba9f0761c64df30c9fd7288cfd8fe8b Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3288-popmetal-android-vga.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-popmetal-android-vga.dts b/arch/arm/boot/dts/rk3288-popmetal-android-vga.dts index e799e276ead7..216e44fb11c0 100644 --- a/arch/arm/boot/dts/rk3288-popmetal-android-vga.dts +++ b/arch/arm/boot/dts/rk3288-popmetal-android-vga.dts @@ -262,6 +262,8 @@ }; &lvds { + pinctrl-names = "default"; + pinctrl-0 = <&lcdc_ctl>; status = "okay"; ports { From 3e0cd87ecdbfee05af1debde55740bccc5d7ae7a Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 16:23:51 +0800 Subject: [PATCH 073/427] ARM: dts: rockchip: rk3126-evb: Fix lvds pinctrl-names Change-Id: Iebb49608373efd4927b11f55f901c43017502f94 Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3126-evb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3126-evb.dts b/arch/arm/boot/dts/rk3126-evb.dts index 7cea13eb1863..6d41cbba83d3 100644 --- a/arch/arm/boot/dts/rk3126-evb.dts +++ b/arch/arm/boot/dts/rk3126-evb.dts @@ -351,7 +351,7 @@ &lvds { status = "okay"; - pinctrl-names = "lcdc"; + pinctrl-names = "default"; pinctrl-0 = <&lcdc_lcdc>; ports { lvds_out: port@1 { From 1414eb5ed8eb5783f342a3fddaa3a18a1c721f42 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 16:24:30 +0800 Subject: [PATCH 074/427] ARM: dts: rockchip: rk3128-fireprime: Fix lvds pinctrl-names Change-Id: I0b1ba2f930bfe6b8541f5e980ec114240460f877 Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3128-fireprime.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3128-fireprime.dts b/arch/arm/boot/dts/rk3128-fireprime.dts index 368197402fbe..0aa459285f86 100644 --- a/arch/arm/boot/dts/rk3128-fireprime.dts +++ b/arch/arm/boot/dts/rk3128-fireprime.dts @@ -342,7 +342,7 @@ &lvds { status = "disabled"; - pinctrl-names = "lcdc"; + pinctrl-names = "default"; pinctrl-0 = <&lcdc_lcdc>; ports { lvds_out: port@1 { From c27c1942671696c531eadeb1e559faf5b210cb26 Mon Sep 17 00:00:00 2001 From: Kaige Li Date: Wed, 31 Jan 2018 08:39:06 +0800 Subject: [PATCH 075/427] misc: fixed gpio-detection error This patch can fix the following issue: The gpio is not invalid when configured as active low. Change-Id: Idc0618db3c20534ad5c952a4c9b4d4a366599cbf Signed-off-by: Kaige Li --- drivers/misc/gpio-detection.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/misc/gpio-detection.c b/drivers/misc/gpio-detection.c index 38378c3290de..69eda8e5e0ef 100644 --- a/drivers/misc/gpio-detection.c +++ b/drivers/misc/gpio-detection.c @@ -35,7 +35,6 @@ struct gpio_data { struct device dev; int notify; struct gpio_desc *gpio; - int atv_val; int val; int irq; struct delayed_work work; @@ -104,7 +103,7 @@ static void gpio_det_report_event(struct gpio_data *gpiod) char *status = NULL; char *envp[2]; - event.val = gpiod->val ^ gpiod->atv_val; + event.val = gpiod->val; event.name = gpiod->name; status = kasprintf(GFP_KERNEL, "GPIO_NAME=%s GPIO_STATE=%s", gpiod->name, event.val ? "over" : "on"); @@ -137,7 +136,7 @@ static void gpio_det_work_func(struct work_struct *work) static irqreturn_t gpio_det_interrupt(int irq, void *dev_id) { struct gpio_data *gpiod = dev_id; - int val = gpiod_get_value(gpiod->gpio); + int val = gpiod_get_raw_value(gpiod->gpio); unsigned int irqflags = IRQF_ONESHOT; if (val) @@ -160,7 +159,7 @@ static int gpio_det_init_status_check(struct gpio_detection *gpio_det) for (i = 0; i < gpio_det->num; i++) { gpiod = &gpio_det->data[i]; gpiod->val = gpiod_get_value(gpiod->gpio); - if (gpiod->atv_val == gpiod->val) + if (gpiod->val) gpio_det_report_event(gpiod); } @@ -212,7 +211,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, struct gpio_data *gpiod = container_of(dev, struct gpio_data, dev); unsigned int val = gpiod_get_value(gpiod->gpio); - return sprintf(buf, "%d\n", val == gpiod->atv_val); + return sprintf(buf, "%d\n", val); } static ssize_t status_store(struct device *dev, struct device_attribute *attr, @@ -301,7 +300,6 @@ static int gpio_det_parse_dt(struct gpio_detection *gpio_det, gpiod = &data[i++]; gpiod->parent = gpio_det; gpiod->notify = 1; - gpiod->atv_val = !OF_GPIO_ACTIVE_LOW; gpiod->name = of_get_property(node, "label", NULL); gpiod->wakeup = !!of_get_property(node, "gpio,wakeup", NULL); of_property_read_u32(node, "linux,debounce-ms", @@ -367,7 +365,7 @@ static int gpio_det_probe(struct platform_device *pdev) if (ret < 0) return ret; INIT_DELAYED_WORK(&gpiod->work, gpio_det_work_func); - gpiod->val = gpiod_get_value(gpiod->gpio); + gpiod->val = gpiod_get_raw_value(gpiod->gpio); if (gpiod->val) irqflags |= IRQ_TYPE_EDGE_FALLING; else From e680ddfb7003a5fc2b879a98972acf02ca3460ed Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 30 Jan 2018 20:05:49 +0800 Subject: [PATCH 076/427] drm/rockchip: vop: correct register config Change-Id: I5923580552d14dc25b61524e500b7449401b1cca Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index d626acf00f10..134969cd0c5f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -886,6 +886,7 @@ static const struct vop_ctrl rk3328_ctrl_data = { .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), .core_dclk_div = VOP_REG(RK3328_DSP_CTRL0, 0x1, 4), + .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), .p2i_en = VOP_REG(RK3328_DSP_CTRL0, 0x1, 5), .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), From 345820113a8fa8ae7b437c03574437fc3c7d7a67 Mon Sep 17 00:00:00 2001 From: Kaige Li Date: Wed, 31 Jan 2018 09:16:51 +0800 Subject: [PATCH 077/427] ARM64: dts: rockchip: rk3368-px5-evb-android: add gpio detection node Change-Id: Ifb002c1211e1e92d759fbd2cc9ac3eb649167701 Signed-off-by: Kaige Li --- .../dts/rockchip/rk3368-px5-evb-android.dts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb-android.dts b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb-android.dts index 1b937f1b96ff..17cd6a723119 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb-android.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb-android.dts @@ -250,6 +250,28 @@ status = "okay"; }; + gpio_det: gpio-det { + compatible = "gpio-detection"; + status = "okay"; + + pinctrl-0 = <&gpio3_b1 &gpio3_b2>; + pinctrl-names = "default"; + + car-reverse { + car-reverse-gpios = <&gpio3 10 GPIO_ACTIVE_LOW>; + linux,debounce-ms = <5>; + label = "car-reverse"; + gpio,wakeup; + }; + + car-acc { + car-acc-gpios = <&gpio3 9 GPIO_ACTIVE_LOW>; + linux,debounce-ms = <5>; + label = "car-acc"; + gpio,wakeup; + }; + }; + vcc_sys: vcc-sys-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_sys"; From 401c07e068d25ef3d26643a284173bd189415388 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 31 Jan 2018 16:05:50 +0800 Subject: [PATCH 078/427] clk: rockchip: px30: Fix div_core_mask Change-Id: I985d27841de00ec7e6f9ca3454c0c4c4f8debacb Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 733018ecd213..7b9c3f68d7b6 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -123,7 +123,7 @@ static struct rockchip_cpuclk_rate_table px30_cpuclk_rates[] __initdata = { static const struct rockchip_cpuclk_reg_data px30_cpuclk_data = { .core_reg = PX30_CLKSEL_CON(0), .div_core_shift = 0, - .div_core_mask = 0x1f, + .div_core_mask = 0xf, .mux_core_alt = 1, .mux_core_main = 0, .mux_core_shift = 7, From 7bd13a986e5fe75a4b87f9779a3b5fe58f70e825 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 31 Jan 2018 13:05:19 +0800 Subject: [PATCH 079/427] clk: rockchip: px30: Modify SRST ID according to latest document Change-Id: Idb6b845581a18082f851c4b67e1ef5bd3a5bc886 Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 +- include/dt-bindings/clock/px30-cru.h | 38 +++++++++++++++----------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index fa4dc95774a3..f6237192998c 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -902,7 +902,7 @@ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>, <&cru SCLK_CORE_VPU>; clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core"; resets = <&cru SRST_VPU_A>, <&cru SRST_VPU_H>, - <&cru SRST_IVPU_NIU_A>, <&cru SRST_VPU_NIU_H>; + <&cru SRST_VPU_NIU_A>, <&cru SRST_VPU_NIU_H>; reset-names = "video_a", "video_h", "niu_a", "niu_h"; mode_bit = <15>; mode_ctrl = <0x410>; diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h index b508d638b00a..0873db1498b4 100644 --- a/include/dt-bindings/clock/px30-cru.h +++ b/include/dt-bindings/clock/px30-cru.h @@ -218,12 +218,13 @@ #define SRST_CORE2_DBG 10 #define SRST_CORE3_DBG 11 #define SRST_TOPDBG 12 -#define SRST_CORE_NIU 13 +#define SRST_CORE_NOC 13 #define SRST_STRC_A 14 #define SRST_L2C 15 #define SRST_DAP 16 -#define SRST_GPU_A 18 +#define SRST_CORE_PVTM 17 +#define SRST_GPU 18 #define SRST_GPU_NIU 19 #define SRST_UPCTL2 20 #define SRST_UPCTL2_A 21 @@ -241,9 +242,8 @@ #define SRST_DDRPHY 32 #define SRST_DDRPHYDIV 33 #define SRST_DDRPHY_P 34 -#define SRST_MSCH_SRV_p 35 #define SRST_VPU_A 36 -#define SRST_IVPU_NIU_A 37 +#define SRST_VPU_NIU_A 37 #define SRST_VPU_H 38 #define SRST_VPU_NIU_H 39 #define SRST_VI_NIU_A 40 @@ -258,18 +258,19 @@ #define SRST_VO_NIU_A 48 #define SRST_VO_NIU_H 49 #define SRST_VO_NIU_P 50 -#define SRST_VOPM_A 51 -#define SRST_VOPM_H 52 -#define SRST_VOPM 53 -#define SRST_PWM_VOPM 54 -#define SRST_VOPS_A 55 -#define SRST_VOPS_H 56 -#define SRST_VOPS 57 +#define SRST_VOPB_A 51 +#define SRST_VOPB_H 52 +#define SRST_VOPB 53 +#define SRST_PWM_VOPB 54 +#define SRST_VOPL_A 55 +#define SRST_VOPL_H 56 +#define SRST_VOPL 57 #define SRST_RGA_A 58 #define SRST_RGA_H 59 #define SRST_RGA 60 #define SRST_MIPIDSI_HOST_P 61 #define SRST_MIPIDSIPHY_P 62 +#define SRST_VPU_CORE 63 #define SRST_PERI_NIU_A 64 #define SRST_USB_NIU_H 65 @@ -294,7 +295,7 @@ #define SRST_SFC_H 83 #define SRST_SFC 84 #define SRST_SDCARD_NIU_H 85 -#define SRST_SDCARD_H 86 +#define SRST_SDMMC_H 86 #define SRST_NANDC_H 89 #define SRST_NANDC 90 #define SRST_GMAC_NIU_A 92 @@ -311,6 +312,12 @@ #define SRST_PMU_CRU_P 103 #define SRST_PMU_PVTM 104 #define SRST_PMU_UART 105 +#define SRST_PMU_NIU_H 106 +#define SRST_PMU_DDR_FAIL_SAVE 107 +#define SRST_PMU_CORE_PERF_A 108 +#define SRST_PMU_CORE_GRF_P 109 +#define SRST_PMU_GPU_PERF_A 110 +#define SRST_PMU_GPU_GRF_P 111 #define SRST_CRYPTO_NIU_A 112 #define SRST_CRYPTO_NIU_H 113 @@ -323,7 +330,6 @@ #define SRST_BUS_TOP_NIU_P 122 #define SRST_INTMEM_A 123 #define SRST_GIC_A 124 -#define SRST_DMAC_A 125 #define SRST_ROM_H 126 #define SRST_DCF_A 127 @@ -331,7 +337,7 @@ #define SRST_PDM_H 129 #define SRST_PDM 130 #define SRST_I2S0_H 131 -#define SRST_I2S0 132 +#define SRST_I2S0_TX 132 #define SRST_I2S1_H 133 #define SRST_I2S1 134 #define SRST_I2S2_H 135 @@ -355,8 +361,6 @@ #define SRST_I2C2 152 #define SRST_I2C3_P 153 #define SRST_I2C3 154 -#define SRST_I2C4_P 155 -#define SRST_I2C4 156 #define SRST_PWM0_P 157 #define SRST_PWM0 158 #define SRST_PWM1_P 159 @@ -387,6 +391,8 @@ #define SRST_GPIO1_P 182 #define SRST_GPIO2_P 183 #define SRST_GPIO3_P 184 +#define SRST_SGRF_P 185 #define SRST_GRF_P 186 +#define SRST_I2S0_RX 191 #endif From 62779bcb89c9e84d5dc4f5b274c9357c773f94ec Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 31 Jan 2018 10:20:48 +0800 Subject: [PATCH 080/427] drm/rockchip: backlight: fix compile warning warning: Access to field 'dev' results in a dereference of a null pointer (loaded from variable 'panel') Change-Id: I0f4224b47b3b7c16a9022e19f8de28df66784a7f Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_backlight.c b/drivers/gpu/drm/rockchip/rockchip_drm_backlight.c index 21a743052cb0..52c761f79978 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_backlight.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_backlight.c @@ -307,7 +307,7 @@ static int rockchip_drm_backlight_bind(struct device *dev, drm_for_each_connector(connector, drm_dev) { panel = drm_find_panel_by_connector(connector); - if (!panel && !panel->dev) + if (!panel || !panel->dev) continue; backlight_np = of_parse_phandle(panel->dev->of_node, "backlight", 0); From 8bb0c6a1b3b2fe92707ee6f6901bfdfc392f8cd1 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 9 Dec 2016 10:24:05 -0800 Subject: [PATCH 081/427] x86/asm/32: Make sync_core() handle missing CPUID on all 32-bit kernels commit 1c52d859cb2d417e7216d3e56bb7fea88444cec9 upstream. We support various non-Intel CPUs that don't have the CPUID instruction, so the M486 test was wrong. For now, fix it with a big hammer: handle missing CPUID on all 32-bit CPUs. Reported-by: One Thousand Gnomes Signed-off-by: Andy Lutomirski Cc: Juergen Gross Cc: Peter Zijlstra Cc: Brian Gerst Cc: Matthew Whitehead Cc: Borislav Petkov Cc: Henrique de Moraes Holschuh Cc: Andrew Cooper Cc: Boris Ostrovsky Cc: xen-devel Link: http://lkml.kernel.org/r/685bd083a7c036f7769510b6846315b17d6ba71f.1481307769.git.luto@kernel.org Signed-off-by: Thomas Gleixner Cc: "Zhang, Ning A" Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c124d6ab4bf9..86bccb4bd4dc 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -574,7 +574,7 @@ static inline void sync_core(void) { int tmp; -#ifdef CONFIG_M486 +#ifdef CONFIG_X86_32 /* * Do a CPUID if available, otherwise do a jump. The jump * can conveniently enough be the jump around CPUID. From 28f467e0bdda754aa36390fd90b01823f0d3b18d Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 7 Dec 2017 14:16:49 -0700 Subject: [PATCH 082/427] usbip: prevent vhci_hcd driver from leaking a socket pointer address commit 2f2d0088eb93db5c649d2a5e34a3800a8a935fc5 upstream. When a client has a USB device attached over IP, the vhci_hcd driver is locally leaking a socket pointer address via the /sys/devices/platform/vhci_hcd/status file (world-readable) and in debug output when "usbip --debug port" is run. Fix it to not leak. The socket pointer address is not used at the moment and it was made visible as a convenient way to find IP address from socket pointer address by looking up /proc/net/{tcp,tcp6}. As this opens a security hole, the fix replaces socket pointer address with sockfd. Reported-by: Secunia Research Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_common.h | 1 + drivers/usb/usbip/vhci_sysfs.c | 25 +++++++++++++++---------- tools/usb/usbip/libsrc/vhci_driver.c | 8 ++++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index 86b08475c254..f875ccaa55f9 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -261,6 +261,7 @@ struct usbip_device { /* lock for status */ spinlock_t lock; + int sockfd; struct socket *tcp_socket; struct task_struct *tcp_rx; diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 211f43f67ea2..84c21c4ccf46 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -39,16 +39,20 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, /* * output example: - * prt sta spd dev socket local_busid - * 000 004 000 000 c5a7bb80 1-2.3 - * 001 004 000 000 d8cee980 2-3.4 + * port sta spd dev sockfd local_busid + * 0000 004 000 00000000 000003 1-2.3 + * 0001 004 000 00000000 000004 2-3.4 * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. + * Output includes socket fd instead of socket pointer address to + * avoid leaking kernel memory address in: + * /sys/devices/platform/vhci_hcd.0/status and in debug output. + * The socket pointer address is not used at the moment and it was + * made visible as a convenient way to find IP address from socket + * pointer address by looking up /proc/net/{tcp,tcp6}. As this opens + * a security hole, the change is made to use sockfd instead. */ out += sprintf(out, - "prt sta spd bus dev socket local_busid\n"); + "prt sta spd bus dev sockfd local_busid\n"); for (i = 0; i < VHCI_NPORTS; i++) { struct vhci_device *vdev = port_to_vdev(i); @@ -60,11 +64,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, out += sprintf(out, "%03u %08x ", vdev->speed, vdev->devid); out += sprintf(out, "%16p ", vdev->ud.tcp_socket); + out += sprintf(out, "%06u", vdev->ud.sockfd); out += sprintf(out, "%s", dev_name(&vdev->udev->dev)); - } else { - out += sprintf(out, "000 000 000 0000000000000000 0-0"); - } + } else + out += sprintf(out, "000 000 000 000000 0-0"); out += sprintf(out, "\n"); spin_unlock(&vdev->ud.lock); @@ -223,6 +227,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, vdev->devid = devid; vdev->speed = speed; + vdev->ud.sockfd = sockfd; vdev->ud.tcp_socket = socket; vdev->ud.status = VDEV_ST_NOTASSIGNED; diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c index ad9204773533..1274f326242c 100644 --- a/tools/usb/usbip/libsrc/vhci_driver.c +++ b/tools/usb/usbip/libsrc/vhci_driver.c @@ -55,12 +55,12 @@ static int parse_status(const char *value) while (*c != '\0') { int port, status, speed, devid; - unsigned long socket; + int sockfd; char lbusid[SYSFS_BUS_ID_SIZE]; - ret = sscanf(c, "%d %d %d %x %lx %31s\n", + ret = sscanf(c, "%d %d %d %x %u %31s\n", &port, &status, &speed, - &devid, &socket, lbusid); + &devid, &sockfd, lbusid); if (ret < 5) { dbg("sscanf failed: %d", ret); @@ -69,7 +69,7 @@ static int parse_status(const char *value) dbg("port %d status %d speed %d devid %x", port, status, speed, devid); - dbg("socket %lx lbusid %s", socket, lbusid); + dbg("sockfd %u lbusid %s", sockfd, lbusid); /* if a device is connected, look at it */ From 4493f49816acc5531ed31ffc600073330393cc61 Mon Sep 17 00:00:00 2001 From: Jonathan Dieter Date: Mon, 27 Feb 2017 10:31:04 +0200 Subject: [PATCH 083/427] usbip: Fix implicit fallthrough warning commit cfd6ed4537a9e938fa76facecd4b9cd65b6d1563 upstream. GCC 7 now warns when switch statements fall through implicitly, and with -Werror enabled in configure.ac, that makes these tools unbuildable. We fix this by notifying the compiler that this particular case statement is meant to fall through. Reviewed-by: Peter Senna Tschudin Signed-off-by: Jonathan Dieter Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/src/usbip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/usb/usbip/src/usbip.c b/tools/usb/usbip/src/usbip.c index d7599d943529..73d8eee8130b 100644 --- a/tools/usb/usbip/src/usbip.c +++ b/tools/usb/usbip/src/usbip.c @@ -176,6 +176,8 @@ int main(int argc, char *argv[]) break; case '?': printf("usbip: invalid option\n"); + /* Terminate after printing error */ + /* FALLTHRU */ default: usbip_usage(); goto out; From 579a9885cfe40645bc62207f318d172c4cad7942 Mon Sep 17 00:00:00 2001 From: Jonathan Dieter Date: Mon, 27 Feb 2017 10:31:03 +0200 Subject: [PATCH 084/427] usbip: Fix potential format overflow in userspace tools commit e5dfa3f902b9a642ae8c6997d57d7c41e384a90b upstream. The usbip userspace tools call sprintf()/snprintf() and don't check for the return value which can lead the paths to overflow, truncating the final file in the path. More urgently, GCC 7 now warns that these aren't checked with -Wformat-overflow, and with -Werror enabled in configure.ac, that makes these tools unbuildable. This patch fixes these problems by replacing sprintf() with snprintf() in one place and adding checks for the return value of snprintf(). Reviewed-by: Peter Senna Tschudin Signed-off-by: Jonathan Dieter Acked-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/libsrc/usbip_common.c | 9 +++++++- tools/usb/usbip/libsrc/usbip_host_driver.c | 27 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c index ac73710473de..8000445ff884 100644 --- a/tools/usb/usbip/libsrc/usbip_common.c +++ b/tools/usb/usbip/libsrc/usbip_common.c @@ -215,9 +215,16 @@ int read_usb_interface(struct usbip_usb_device *udev, int i, struct usbip_usb_interface *uinf) { char busid[SYSFS_BUS_ID_SIZE]; + int size; struct udev_device *sif; - sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i); + size = snprintf(busid, sizeof(busid), "%s:%d.%d", + udev->busid, udev->bConfigurationValue, i); + if (size < 0 || (unsigned int)size >= sizeof(busid)) { + err("busid length %i >= %lu or < 0", size, + (unsigned long)sizeof(busid)); + return -1; + } sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid); if (!sif) { diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c index bef08d5c44e8..071b9ce99420 100644 --- a/tools/usb/usbip/libsrc/usbip_host_driver.c +++ b/tools/usb/usbip/libsrc/usbip_host_driver.c @@ -39,13 +39,19 @@ struct udev *udev_context; static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { char status_attr_path[SYSFS_PATH_MAX]; + int size; int fd; int length; char status; int value = 0; - snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", - udev->path); + size = snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", + udev->path); + if (size < 0 || (unsigned int)size >= sizeof(status_attr_path)) { + err("usbip_status path length %i >= %lu or < 0", size, + (unsigned long)sizeof(status_attr_path)); + return -1; + } fd = open(status_attr_path, O_RDONLY); if (fd < 0) { @@ -225,6 +231,7 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) { char attr_name[] = "usbip_sockfd"; char sockfd_attr_path[SYSFS_PATH_MAX]; + int size; char sockfd_buff[30]; int ret; @@ -244,10 +251,20 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) } /* only the first interface is true */ - snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", - edev->udev.path, attr_name); + size = snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", + edev->udev.path, attr_name); + if (size < 0 || (unsigned int)size >= sizeof(sockfd_attr_path)) { + err("exported device path length %i >= %lu or < 0", size, + (unsigned long)sizeof(sockfd_attr_path)); + return -1; + } - snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); + size = snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); + if (size < 0 || (unsigned int)size >= sizeof(sockfd_buff)) { + err("socket length %i >= %lu or < 0", size, + (unsigned long)sizeof(sockfd_buff)); + return -1; + } ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, strlen(sockfd_buff)); From 20e3fa5dd5818b425b18528571e133034833df27 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 24 Jan 2018 02:31:19 +0000 Subject: [PATCH 085/427] x86/microcode/intel: Fix BDW late-loading revision check The backport of commit b94b73733171 ("x86/microcode/intel: Extend BDW late-loading with a revision check") to 4.4-stable deleted a "return true" statement. This bug is not present upstream or other stable branches. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/microcode/intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index b428a8174be1..ee011bd7934d 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -1005,6 +1005,7 @@ static bool is_blacklisted(unsigned int cpu) c->microcode < 0x0b000021) { pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); + return true; } return false; From 0dfd5fbcae5d40e5e58bc7c34305498e965bf1ef Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Thu, 2 Jun 2016 17:19:27 -0700 Subject: [PATCH 086/427] x86/cpu/intel: Introduce macros for Intel family numbers commit 970442c599b22ccd644ebfe94d1d303bf6f87c05 upstream. Problem: We have a boatload of open-coded family-6 model numbers. Half of them have these model numbers in hex and the other half in decimal. This makes grepping for them tons of fun, if you were to try. Solution: Consolidate all the magic numbers. Put all the definitions in one header. The names here are closely derived from the comments describing the models from arch/x86/events/intel/core.c. We could easily make them shorter by doing things like s/SANDYBRIDGE/SNB/, but they seemed fine even with the longer versions to me. Do not take any of these names too literally, like "DESKTOP" or "MOBILE". These are all colloquial names and not precise descriptions of everywhere a given model will show up. Signed-off-by: Dave Hansen Cc: Adrian Hunter Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Darren Hart Cc: Dave Hansen Cc: Denys Vlasenko Cc: Doug Thompson Cc: Eduardo Valentin Cc: H. Peter Anvin Cc: Jacob Pan Cc: Kan Liang Cc: Len Brown Cc: Linus Torvalds Cc: Mauro Carvalho Chehab Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Rajneesh Bhardwaj Cc: Souvik Kumar Chakravarty Cc: Srinivas Pandruvada Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Tony Luck Cc: Ulf Hansson Cc: Viresh Kumar Cc: Vishwanath Somayaji Cc: Zhang Rui Cc: jacob.jun.pan@intel.com Cc: linux-acpi@vger.kernel.org Cc: linux-edac@vger.kernel.org Cc: linux-mmc@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Link: http://lkml.kernel.org/r/20160603001927.F2A7D828@viggo.jf.intel.com Signed-off-by: Ingo Molnar Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/intel-family.h | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 arch/x86/include/asm/intel-family.h diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h new file mode 100644 index 000000000000..6999f7d01a0d --- /dev/null +++ b/arch/x86/include/asm/intel-family.h @@ -0,0 +1,68 @@ +#ifndef _ASM_X86_INTEL_FAMILY_H +#define _ASM_X86_INTEL_FAMILY_H + +/* + * "Big Core" Processors (Branded as Core, Xeon, etc...) + * + * The "_X" parts are generally the EP and EX Xeons, or the + * "Extreme" ones, like Broadwell-E. + * + * Things ending in "2" are usually because we have no better + * name for them. There's no processor called "WESTMERE2". + */ + +#define INTEL_FAM6_CORE_YONAH 0x0E +#define INTEL_FAM6_CORE2_MEROM 0x0F +#define INTEL_FAM6_CORE2_MEROM_L 0x16 +#define INTEL_FAM6_CORE2_PENRYN 0x17 +#define INTEL_FAM6_CORE2_DUNNINGTON 0x1D + +#define INTEL_FAM6_NEHALEM 0x1E +#define INTEL_FAM6_NEHALEM_EP 0x1A +#define INTEL_FAM6_NEHALEM_EX 0x2E +#define INTEL_FAM6_WESTMERE 0x25 +#define INTEL_FAM6_WESTMERE2 0x1F +#define INTEL_FAM6_WESTMERE_EP 0x2C +#define INTEL_FAM6_WESTMERE_EX 0x2F + +#define INTEL_FAM6_SANDYBRIDGE 0x2A +#define INTEL_FAM6_SANDYBRIDGE_X 0x2D +#define INTEL_FAM6_IVYBRIDGE 0x3A +#define INTEL_FAM6_IVYBRIDGE_X 0x3E + +#define INTEL_FAM6_HASWELL_CORE 0x3C +#define INTEL_FAM6_HASWELL_X 0x3F +#define INTEL_FAM6_HASWELL_ULT 0x45 +#define INTEL_FAM6_HASWELL_GT3E 0x46 + +#define INTEL_FAM6_BROADWELL_CORE 0x3D +#define INTEL_FAM6_BROADWELL_XEON_D 0x56 +#define INTEL_FAM6_BROADWELL_GT3E 0x47 +#define INTEL_FAM6_BROADWELL_X 0x4F + +#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E +#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E +#define INTEL_FAM6_SKYLAKE_X 0x55 +#define INTEL_FAM6_KABYLAKE_MOBILE 0x8E +#define INTEL_FAM6_KABYLAKE_DESKTOP 0x9E + +/* "Small Core" Processors (Atom) */ + +#define INTEL_FAM6_ATOM_PINEVIEW 0x1C +#define INTEL_FAM6_ATOM_LINCROFT 0x26 +#define INTEL_FAM6_ATOM_PENWELL 0x27 +#define INTEL_FAM6_ATOM_CLOVERVIEW 0x35 +#define INTEL_FAM6_ATOM_CEDARVIEW 0x36 +#define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */ +#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */ +#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */ +#define INTEL_FAM6_ATOM_MERRIFIELD1 0x4A /* Tangier */ +#define INTEL_FAM6_ATOM_MERRIFIELD2 0x5A /* Annidale */ +#define INTEL_FAM6_ATOM_GOLDMONT 0x5C +#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ + +/* Xeon Phi */ + +#define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ + +#endif /* _ASM_X86_INTEL_FAMILY_H */ From 18bb117d1b7690181346e6365c6237b6ceaac4c4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 12 Jan 2018 17:49:25 +0000 Subject: [PATCH 087/427] x86/retpoline: Fill RSB on context switch for affected CPUs commit c995efd5a740d9cbafbf58bde4973e8b50b4d761 upstream. On context switch from a shallow call stack to a deeper one, as the CPU does 'ret' up the deeper side it may encounter RSB entries (predictions for where the 'ret' goes to) which were populated in userspace. This is problematic if neither SMEP nor KPTI (the latter of which marks userspace pages as NX for the kernel) are active, as malicious code in userspace may then be executed speculatively. Overwrite the CPU's return prediction stack with calls which are predicted to return to an infinite loop, to "capture" speculation if this happens. This is required both for retpoline, and also in conjunction with IBRS for !SMEP && !KPTI. On Skylake+ the problem is slightly different, and an *underflow* of the RSB may cause errant branch predictions to occur. So there it's not so much overwrite, as *filling* the RSB to attempt to prevent it getting empty. This is only a partial solution for Skylake+ since there are many other conditions which may result in the RSB becoming empty. The full solution on Skylake+ is to use IBRS, which will prevent the problem even when the RSB becomes empty. With IBRS, the RSB-stuffing will not be required on context switch. [ tglx: Added missing vendor check and slighty massaged comments and changelog ] [js] backport to 4.4 -- __switch_to_asm does not exist there, we have to patch the switch_to macros for both x86_32 and x86_64. Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Acked-by: Arjan van de Ven Cc: gnomes@lxorguk.ukuu.org.uk Cc: Rik van Riel Cc: Andi Kleen Cc: Josh Poimboeuf Cc: thomas.lendacky@amd.com Cc: Peter Zijlstra Cc: Linus Torvalds Cc: Jiri Kosina Cc: Andy Lutomirski Cc: Dave Hansen Cc: Kees Cook Cc: Tim Chen Cc: Greg Kroah-Hartman Cc: Paul Turner Link: https://lkml.kernel.org/r/1515779365-9032-1-git-send-email-dwmw@amazon.co.uk Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/switch_to.h | 38 +++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/bugs.c | 36 +++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0fbc98568018..641f0f2c2982 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -199,6 +199,7 @@ #define X86_FEATURE_HWP_EPP ( 7*32+13) /* Intel HWP_EPP */ #define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */ #define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ +#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */ #define X86_FEATURE_RETPOLINE ( 7*32+29) /* Generic Retpoline mitigation for Spectre variant 2 */ #define X86_FEATURE_RETPOLINE_AMD ( 7*32+30) /* AMD Retpoline mitigation for Spectre variant 2 */ diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h index 751bf4b7bf11..025ecfaba9c9 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_SWITCH_TO_H #define _ASM_X86_SWITCH_TO_H +#include + struct task_struct; /* one of the stranger aspects of C forward declarations */ __visible struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next); @@ -24,6 +26,23 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, #define __switch_canary_iparam #endif /* CC_STACKPROTECTOR */ +#ifdef CONFIG_RETPOLINE + /* + * When switching from a shallower to a deeper call stack + * the RSB may either underflow or use entries populated + * with userspace addresses. On CPUs where those concerns + * exist, overwrite the RSB with entries which capture + * speculative execution to prevent attack. + */ +#define __retpoline_fill_return_buffer \ + ALTERNATIVE("jmp 910f", \ + __stringify(__FILL_RETURN_BUFFER(%%ebx, RSB_CLEAR_LOOPS, %%esp)),\ + X86_FEATURE_RSB_CTXSW) \ + "910:\n\t" +#else +#define __retpoline_fill_return_buffer +#endif + /* * Saving eflags is important. It switches not only IOPL between tasks, * it also protects other tasks from NT leaking through sysenter etc. @@ -46,6 +65,7 @@ do { \ "movl $1f,%[prev_ip]\n\t" /* save EIP */ \ "pushl %[next_ip]\n\t" /* restore EIP */ \ __switch_canary \ + __retpoline_fill_return_buffer \ "jmp __switch_to\n" /* regparm call */ \ "1:\t" \ "popl %%ebp\n\t" /* restore EBP */ \ @@ -100,6 +120,23 @@ do { \ #define __switch_canary_iparam #endif /* CC_STACKPROTECTOR */ +#ifdef CONFIG_RETPOLINE + /* + * When switching from a shallower to a deeper call stack + * the RSB may either underflow or use entries populated + * with userspace addresses. On CPUs where those concerns + * exist, overwrite the RSB with entries which capture + * speculative execution to prevent attack. + */ +#define __retpoline_fill_return_buffer \ + ALTERNATIVE("jmp 910f", \ + __stringify(__FILL_RETURN_BUFFER(%%r12, RSB_CLEAR_LOOPS, %%rsp)),\ + X86_FEATURE_RSB_CTXSW) \ + "910:\n\t" +#else +#define __retpoline_fill_return_buffer +#endif + /* * There is no need to save or restore flags, because flags are always * clean in kernel mode, with the possible exception of IOPL. Kernel IOPL @@ -112,6 +149,7 @@ do { \ "call __switch_to\n\t" \ "movq "__percpu_arg([current_task])",%%rsi\n\t" \ __switch_canary \ + __retpoline_fill_return_buffer \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ "movq %%rax,%%rdi\n\t" \ "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" \ diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 49d25ddf0e9f..8cacf62ec458 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -22,6 +22,7 @@ #include #include #include +#include static void __init spectre_v2_select_mitigation(void); @@ -154,6 +155,23 @@ disable: return SPECTRE_V2_CMD_NONE; } +/* Check for Skylake-like CPUs (for RSB handling) */ +static bool __init is_skylake_era(void) +{ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6) { + switch (boot_cpu_data.x86_model) { + case INTEL_FAM6_SKYLAKE_MOBILE: + case INTEL_FAM6_SKYLAKE_DESKTOP: + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_KABYLAKE_MOBILE: + case INTEL_FAM6_KABYLAKE_DESKTOP: + return true; + } + } + return false; +} + static void __init spectre_v2_select_mitigation(void) { enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); @@ -212,6 +230,24 @@ retpoline_auto: spectre_v2_enabled = mode; pr_info("%s\n", spectre_v2_strings[mode]); + + /* + * If neither SMEP or KPTI are available, there is a risk of + * hitting userspace addresses in the RSB after a context switch + * from a shallow call stack to a deeper one. To prevent this fill + * the entire RSB, even when using IBRS. + * + * Skylake era CPUs have a separate issue with *underflow* of the + * RSB, when they will predict 'ret' targets from the generic BTB. + * The proper mitigation for this is IBRS. If IBRS is not supported + * or deactivated in favour of retpolines the RSB fill on context + * switch is required. + */ + if ((!boot_cpu_has(X86_FEATURE_KAISER) && + !boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) { + setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); + pr_info("Filling RSB on context switch\n"); + } } #undef pr_fmt From 1d00e3d9b7ed8fbf6729b7c5a8aae9f2711d2655 Mon Sep 17 00:00:00 2001 From: Daniel Bristot de Oliveira Date: Mon, 29 May 2017 16:24:03 +0200 Subject: [PATCH 088/427] sched/deadline: Use the revised wakeup rule for suspending constrained dl tasks commit 3effcb4247e74a51f5d8b775a1ee4abf87cc089a upstream. We have been facing some problems with self-suspending constrained deadline tasks. The main reason is that the original CBS was not designed for such sort of tasks. One problem reported by Xunlei Pang takes place when a task suspends, and then is awakened before the deadline, but so close to the deadline that its remaining runtime can cause the task to have an absolute density higher than allowed. In such situation, the original CBS assumes that the task is facing an early activation, and so it replenishes the task and set another deadline, one deadline in the future. This rule works fine for implicit deadline tasks. Moreover, it allows the system to adapt the period of a task in which the external event source suffered from a clock drift. However, this opens the window for bandwidth leakage for constrained deadline tasks. For instance, a task with the following parameters: runtime = 5 ms deadline = 7 ms [density] = 5 / 7 = 0.71 period = 1000 ms If the task runs for 1 ms, and then suspends for another 1ms, it will be awakened with the following parameters: remaining runtime = 4 laxity = 5 presenting a absolute density of 4 / 5 = 0.80. In this case, the original CBS would assume the task had an early wakeup. Then, CBS will reset the runtime, and the absolute deadline will be postponed by one relative deadline, allowing the task to run. The problem is that, if the task runs this pattern forever, it will keep receiving bandwidth, being able to run 1ms every 2ms. Following this behavior, the task would be able to run 500 ms in 1 sec. Thus running more than the 5 ms / 1 sec the admission control allowed it to run. Trying to address the self-suspending case, Luca Abeni, Giuseppe Lipari, and Juri Lelli [1] revisited the CBS in order to deal with self-suspending tasks. In the new approach, rather than replenishing/postponing the absolute deadline, the revised wakeup rule adjusts the remaining runtime, reducing it to fit into the allowed density. A revised version of the idea is: At a given time t, the maximum absolute density of a task cannot be higher than its relative density, that is: runtime / (deadline - t) <= dl_runtime / dl_deadline Knowing the laxity of a task (deadline - t), it is possible to move it to the other side of the equality, thus enabling to define max remaining runtime a task can use within the absolute deadline, without over-running the allowed density: runtime = (dl_runtime / dl_deadline) * (deadline - t) For instance, in our previous example, the task could still run: runtime = ( 5 / 7 ) * 5 runtime = 3.57 ms Without causing damage for other deadline tasks. It is note worthy that the laxity cannot be negative because that would cause a negative runtime. Thus, this patch depends on the patch: df8eac8cafce ("sched/deadline: Throttle a constrained deadline task activated after the deadline") Which throttles a constrained deadline task activated after the deadline. Finally, it is also possible to use the revised wakeup rule for all other tasks, but that would require some more discussions about pros and cons. [The main difference from the original commit is that the BW_SHIFT define was not present yet. As BW_SHIFT was introduced in a new feature, I just used the value (20), likewise we used to use before the #define. Other changes were required because of comments. - bistrot] Reported-by: Xunlei Pang Signed-off-by: Daniel Bristot de Oliveira [peterz: replaced dl_is_constrained with dl_is_implicit] Signed-off-by: Peter Zijlstra (Intel) Cc: Juri Lelli Cc: Linus Torvalds Cc: Luca Abeni Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Romulo Silva de Oliveira Cc: Steven Rostedt Cc: Thomas Gleixner Cc: Tommaso Cucinotta Link: http://lkml.kernel.org/r/5c800ab3a74a168a84ee5f3f84d12a02e11383be.1495803804.git.bristot@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Daniel Bristot de Oliveira Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 1 + kernel/sched/core.c | 2 + kernel/sched/deadline.c | 98 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index e887c8d6f395..90bea398e5e0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1313,6 +1313,7 @@ struct sched_dl_entity { u64 dl_deadline; /* relative deadline of each instance */ u64 dl_period; /* separation of two instances (period) */ u64 dl_bw; /* dl_runtime / dl_deadline */ + u64 dl_density; /* dl_runtime / dl_deadline */ /* * Actual scheduling parameters. Initialized with the values above, diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9d6b3d869592..e6d1173a2046 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2109,6 +2109,7 @@ void __dl_clear_params(struct task_struct *p) dl_se->dl_period = 0; dl_se->flags = 0; dl_se->dl_bw = 0; + dl_se->dl_density = 0; dl_se->dl_throttled = 0; dl_se->dl_new = 1; @@ -3647,6 +3648,7 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr) dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline; dl_se->flags = attr->sched_flags; dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime); + dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime); /* * Changing the parameters of a task is 'tricky' and we're not doing diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 6be2afd9bfd6..e12b0a4df891 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -480,13 +480,84 @@ static bool dl_entity_overflow(struct sched_dl_entity *dl_se, } /* - * When a -deadline entity is queued back on the runqueue, its runtime and - * deadline might need updating. + * Revised wakeup rule [1]: For self-suspending tasks, rather then + * re-initializing task's runtime and deadline, the revised wakeup + * rule adjusts the task's runtime to avoid the task to overrun its + * density. * - * The policy here is that we update the deadline of the entity only if: - * - the current deadline is in the past, - * - using the remaining runtime with the current deadline would make - * the entity exceed its bandwidth. + * Reasoning: a task may overrun the density if: + * runtime / (deadline - t) > dl_runtime / dl_deadline + * + * Therefore, runtime can be adjusted to: + * runtime = (dl_runtime / dl_deadline) * (deadline - t) + * + * In such way that runtime will be equal to the maximum density + * the task can use without breaking any rule. + * + * [1] Luca Abeni, Giuseppe Lipari, and Juri Lelli. 2015. Constant + * bandwidth server revisited. SIGBED Rev. 11, 4 (January 2015), 19-24. + */ +static void +update_dl_revised_wakeup(struct sched_dl_entity *dl_se, struct rq *rq) +{ + u64 laxity = dl_se->deadline - rq_clock(rq); + + /* + * If the task has deadline < period, and the deadline is in the past, + * it should already be throttled before this check. + * + * See update_dl_entity() comments for further details. + */ + WARN_ON(dl_time_before(dl_se->deadline, rq_clock(rq))); + + dl_se->runtime = (dl_se->dl_density * laxity) >> 20; +} + +/* + * Regarding the deadline, a task with implicit deadline has a relative + * deadline == relative period. A task with constrained deadline has a + * relative deadline <= relative period. + * + * We support constrained deadline tasks. However, there are some restrictions + * applied only for tasks which do not have an implicit deadline. See + * update_dl_entity() to know more about such restrictions. + * + * The dl_is_implicit() returns true if the task has an implicit deadline. + */ +static inline bool dl_is_implicit(struct sched_dl_entity *dl_se) +{ + return dl_se->dl_deadline == dl_se->dl_period; +} + +/* + * When a deadline entity is placed in the runqueue, its runtime and deadline + * might need to be updated. This is done by a CBS wake up rule. There are two + * different rules: 1) the original CBS; and 2) the Revisited CBS. + * + * When the task is starting a new period, the Original CBS is used. In this + * case, the runtime is replenished and a new absolute deadline is set. + * + * When a task is queued before the begin of the next period, using the + * remaining runtime and deadline could make the entity to overflow, see + * dl_entity_overflow() to find more about runtime overflow. When such case + * is detected, the runtime and deadline need to be updated. + * + * If the task has an implicit deadline, i.e., deadline == period, the Original + * CBS is applied. the runtime is replenished and a new absolute deadline is + * set, as in the previous cases. + * + * However, the Original CBS does not work properly for tasks with + * deadline < period, which are said to have a constrained deadline. By + * applying the Original CBS, a constrained deadline task would be able to run + * runtime/deadline in a period. With deadline < period, the task would + * overrun the runtime/period allowed bandwidth, breaking the admission test. + * + * In order to prevent this misbehave, the Revisited CBS is used for + * constrained deadline tasks when a runtime overflow is detected. In the + * Revisited CBS, rather than replenishing & setting a new absolute deadline, + * the remaining runtime of the task is reduced to avoid runtime overflow. + * Please refer to the comments update_dl_revised_wakeup() function to find + * more about the Revised CBS rule. */ static void update_dl_entity(struct sched_dl_entity *dl_se, struct sched_dl_entity *pi_se) @@ -505,6 +576,14 @@ static void update_dl_entity(struct sched_dl_entity *dl_se, if (dl_time_before(dl_se->deadline, rq_clock(rq)) || dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) { + + if (unlikely(!dl_is_implicit(dl_se) && + !dl_time_before(dl_se->deadline, rq_clock(rq)) && + !dl_se->dl_boosted)){ + update_dl_revised_wakeup(dl_se, rq); + return; + } + dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; dl_se->runtime = pi_se->dl_runtime; } @@ -991,11 +1070,6 @@ static void dequeue_dl_entity(struct sched_dl_entity *dl_se) __dequeue_dl_entity(dl_se); } -static inline bool dl_is_constrained(struct sched_dl_entity *dl_se) -{ - return dl_se->dl_deadline < dl_se->dl_period; -} - static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) { struct task_struct *pi_task = rt_mutex_get_top_task(p); @@ -1027,7 +1101,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) * If that is the case, the task will be throttled and * the replenishment timer will be set to the next period. */ - if (!p->dl.dl_throttled && dl_is_constrained(&p->dl)) + if (!p->dl.dl_throttled && !dl_is_implicit(&p->dl)) dl_check_constrained_dl(&p->dl); /* From e7514af60542830a37cd8f2fc0419fc5e320d70c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 16 Jan 2018 19:30:14 +0100 Subject: [PATCH 089/427] can: af_can: can_rcv(): replace WARN_ONCE by pr_warn_once commit 8cb68751c115d176ec851ca56ecfbb411568c9e8 upstream. If an invalid CAN frame is received, from a driver or from a tun interface, a Kernel warning is generated. This patch replaces the WARN_ONCE by a simple pr_warn_once, so that a kernel, bootet with panic_on_warn, does not panic. A printk seems to be more appropriate here. Reported-by: syzbot+4386709c0c1284dca827@syzkaller.appspotmail.com Suggested-by: Dmitry Vyukov Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Oliver Hartkopp Signed-off-by: Greg Kroah-Hartman --- net/can/af_can.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 928f58064098..924ad0513af9 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -722,13 +722,12 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, if (unlikely(!net_eq(dev_net(dev), &init_net))) goto drop; - if (WARN_ONCE(dev->type != ARPHRD_CAN || - skb->len != CAN_MTU || - cfd->len > CAN_MAX_DLEN, - "PF_CAN: dropped non conform CAN skbuf: " - "dev type %d, len %d, datalen %d\n", - dev->type, skb->len, cfd->len)) + if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU || + cfd->len > CAN_MAX_DLEN)) { + pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, datalen %d\n", + dev->type, skb->len, cfd->len); goto drop; + } can_receive(skb, dev); return NET_RX_SUCCESS; From 08f39b7bcccb532a6b96fdeaf91ed08e4af7dda4 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 16 Jan 2018 19:30:14 +0100 Subject: [PATCH 090/427] can: af_can: canfd_rcv(): replace WARN_ONCE by pr_warn_once commit d4689846881d160a4d12a514e991a740bcb5d65a upstream. If an invalid CANFD frame is received, from a driver or from a tun interface, a Kernel warning is generated. This patch replaces the WARN_ONCE by a simple pr_warn_once, so that a kernel, bootet with panic_on_warn, does not panic. A printk seems to be more appropriate here. Reported-by: syzbot+e3b775f40babeff6e68b@syzkaller.appspotmail.com Suggested-by: Dmitry Vyukov Acked-by: Oliver Hartkopp Cc: linux-stable Signed-off-by: Marc Kleine-Budde Signed-off-by: Oliver Hartkopp Signed-off-by: Greg Kroah-Hartman --- net/can/af_can.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 924ad0513af9..c866e761651a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -745,13 +745,12 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, if (unlikely(!net_eq(dev_net(dev), &init_net))) goto drop; - if (WARN_ONCE(dev->type != ARPHRD_CAN || - skb->len != CANFD_MTU || - cfd->len > CANFD_MAX_DLEN, - "PF_CAN: dropped non conform CAN FD skbuf: " - "dev type %d, len %d, datalen %d\n", - dev->type, skb->len, cfd->len)) + if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU || + cfd->len > CANFD_MAX_DLEN)) { + pr_warn_once("PF_CAN: dropped non conform CAN FD skbuf: dev type %d, len %d, datalen %d\n", + dev->type, skb->len, cfd->len); goto drop; + } can_receive(skb, dev); return NET_RX_SUCCESS; From 0cb5ae4db47abc3985016aac6326ef98c533fe4d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 24 Jan 2016 20:08:52 -0600 Subject: [PATCH 091/427] PM / sleep: declare __tracedata symbols as char[] rather than char commit f97238373b8662a6d580e204df2e7bcbfa43e27a upstream. Accessing more than one byte from a symbol declared simply 'char' is undefined behavior, as reported by UBSAN: UBSAN: Undefined behaviour in drivers/base/power/trace.c:178:18 load of address ffffffff8203fc78 with insufficient space for an object of type 'char' Avoid this by declaring the symbols as arrays. Signed-off-by: Eric Biggers Signed-off-by: Rafael J. Wysocki Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index a311cfa4c5bd..a6975795e7f3 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c @@ -166,14 +166,14 @@ void generate_pm_trace(const void *tracedata, unsigned int user) } EXPORT_SYMBOL(generate_pm_trace); -extern char __tracedata_start, __tracedata_end; +extern char __tracedata_start[], __tracedata_end[]; static int show_file_hash(unsigned int value) { int match; char *tracedata; match = 0; - for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; + for (tracedata = __tracedata_start ; tracedata < __tracedata_end ; tracedata += 2 + sizeof(unsigned long)) { unsigned short lineno = *(unsigned short *)tracedata; const char *file = *(const char **)(tracedata + 2); From 08b1cf4964d526cf3c2ea9e36ffd752752543ef3 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sat, 13 Aug 2016 01:37:04 +0200 Subject: [PATCH 092/427] time: Avoid undefined behaviour in ktime_add_safe() commit 979515c5645830465739254abc1b1648ada41518 upstream. I ran into this: ================================================================================ UBSAN: Undefined behaviour in kernel/time/hrtimer.c:310:16 signed integer overflow: 9223372036854775807 + 50000 cannot be represented in type 'long long int' CPU: 2 PID: 4798 Comm: trinity-c2 Not tainted 4.8.0-rc1+ #91 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014 0000000000000000 ffff88010ce6fb88 ffffffff82344740 0000000041b58ab3 ffffffff84f97a20 ffffffff82344694 ffff88010ce6fbb0 ffff88010ce6fb60 000000000000c350 ffff88010ce6f968 dffffc0000000000 ffffffff857bc320 Call Trace: [] dump_stack+0xac/0xfc [] ? _atomic_dec_and_lock+0xc4/0xc4 [] ubsan_epilogue+0xd/0x8a [] handle_overflow+0x202/0x23d [] ? val_to_string.constprop.6+0x11e/0x11e [] ? timerqueue_add+0x151/0x410 [] ? hrtimer_start_range_ns+0x3b8/0x1380 [] ? memset+0x31/0x40 [] __ubsan_handle_add_overflow+0xe/0x10 [] hrtimer_nanosleep+0x5d9/0x790 [] ? hrtimer_init_sleeper+0x80/0x80 [] ? __might_sleep+0x5b/0x260 [] common_nsleep+0x20/0x30 [] SyS_clock_nanosleep+0x197/0x210 [] ? SyS_clock_getres+0x150/0x150 [] ? __this_cpu_preempt_check+0x13/0x20 [] ? __context_tracking_exit.part.3+0x30/0x1b0 [] ? SyS_clock_getres+0x150/0x150 [] do_syscall_64+0x1b3/0x4b0 [] entry_SYSCALL64_slow_path+0x25/0x25 ================================================================================ Add a new ktime_add_unsafe() helper which doesn't check for overflow, but doesn't throw a UBSAN warning when it does overflow either. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Richard Cochran Cc: Prarit Bhargava Signed-off-by: Vegard Nossum Signed-off-by: John Stultz Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- include/linux/ktime.h | 7 +++++++ kernel/time/hrtimer.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 2b6a204bd8d4..3ffc69ebe967 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -63,6 +63,13 @@ static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs) #define ktime_add(lhs, rhs) \ ({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; }) +/* + * Same as ktime_add(), but avoids undefined behaviour on overflow; however, + * this means that you must check the result for overflow yourself. + */ +#define ktime_add_unsafe(lhs, rhs) \ + ({ (ktime_t){ .tv64 = (u64) (lhs).tv64 + (rhs).tv64 }; }) + /* * Add a ktime_t variable and a scalar nanosecond value. * res = kt + nsval: diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 17f7bcff1e02..1dc94768b5a3 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(__ktime_divns); */ ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs) { - ktime_t res = ktime_add(lhs, rhs); + ktime_t res = ktime_add_unsafe(lhs, rhs); /* * We use KTIME_SEC_MAX here, the maximum timeout which we can From 839003061aa9362f23866614862b49b57bfdd6ce Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 24 Oct 2016 11:41:56 +0200 Subject: [PATCH 093/427] timers: Plug locking race vs. timer migration commit b831275a3553c32091222ac619cfddd73a5553fb upstream. Linus noticed that lock_timer_base() lacks a READ_ONCE() for accessing the timer flags. As a consequence the compiler is allowed to reload the flags between the initial check for TIMER_MIGRATION and the following timer base computation and the spin lock of the base. While this has not been observed (yet), we need to make sure that it never happens. Fixes: 0eeda71bc30d ("timer: Replace timer base by a cpu index") Reported-by: Linus Torvalds Signed-off-by: Thomas Gleixner Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1610241711220.4983@nanos Cc: Andrew Morton Cc: Peter Zijlstra Signed-off-by: Mike Galbraith Signed-off-by: Greg Kroah-Hartman --- kernel/time/timer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 125407144c01..3d7588a2e97c 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -764,8 +764,15 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer, __acquires(timer->base->lock) { for (;;) { - u32 tf = timer->flags; struct tvec_base *base; + u32 tf; + + /* + * We need to use READ_ONCE() here, otherwise the compiler + * might re-read @tf between the check for TIMER_MIGRATING + * and spin_lock(). + */ + tf = READ_ONCE(timer->flags); if (!(tf & TIMER_MIGRATING)) { base = per_cpu_ptr(&tvec_bases, tf & TIMER_CPUMASK); From 29b73cace1b1cc2daf2556b3285d4e79f19bcb3b Mon Sep 17 00:00:00 2001 From: Janakarajan Natarajan Date: Tue, 25 Apr 2017 16:44:03 -0500 Subject: [PATCH 094/427] Prevent timer value 0 for MWAITX commit 88d879d29f9cc0de2d930b584285638cdada6625 upstream. Newer hardware has uncovered a bug in the software implementation of using MWAITX for the delay function. A value of 0 for the timer is meant to indicate that a timeout will not be used to exit MWAITX. On newer hardware this can result in MWAITX never returning, resulting in NMI soft lockup messages being printed. On older hardware, some of the other conditions under which MWAITX can exit masked this issue. The AMD APM does not currently document this and will be updated. Please refer to http://marc.info/?l=kvm&m=148950623231140 for information regarding NMI soft lockup messages on an AMD Ryzen 1800X. This has been root-caused as a 0 passed to MWAITX causing it to wait indefinitely. This change has the added benefit of avoiding the unnecessary setup of MONITORX/MWAITX when the delay value is zero. Signed-off-by: Janakarajan Natarajan Link: http://lkml.kernel.org/r/1493156643-29366-1-git-send-email-Janakarajan.Natarajan@amd.com Signed-off-by: Thomas Gleixner Signed-off-by: Davidlohr Bueso Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/delay.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index e912b2f6d36e..45772560aceb 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -93,6 +93,13 @@ static void delay_mwaitx(unsigned long __loops) { u64 start, end, delay, loops = __loops; + /* + * Timer value of 0 causes MWAITX to wait indefinitely, unless there + * is a store on the memory monitored by MONITORX. + */ + if (loops == 0) + return; + start = rdtsc_ordered(); for (;;) { From f31a8450c09327339939fe195707749c1d67016d Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 28 Oct 2016 09:45:28 +0100 Subject: [PATCH 095/427] drivers: base: cacheinfo: fix x86 with CONFIG_OF enabled commit fac51482577d5e05bbb0efa8d602a3c2111098bf upstream. With CONFIG_OF enabled on x86, we get the following error on boot: " Failed to find cpu0 device node Unable to detect cache hierarchy from DT for CPU 0 " and the cacheinfo fails to get populated in the corresponding sysfs entries. This is because cache_setup_of_node looks for of_node for setting up the shared cpu_map without checking that it's already populated in the architecture specific callback. In order to indicate that the shared cpu_map is already populated, this patch introduces a boolean `cpu_map_populated` in struct cpu_cacheinfo that can be used by the generic code to skip cache_shared_cpu_map_setup. This patch also sets that boolean for x86. Cc: Greg Kroah-Hartman Signed-off-by: Sudeep Holla Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 ++ drivers/base/cacheinfo.c | 3 +++ include/linux/cacheinfo.h | 1 + 3 files changed, 6 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index e38d338a6447..b4ca91cf55b0 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -934,6 +934,8 @@ static int __populate_cache_leaves(unsigned int cpu) ci_leaf_init(this_leaf++, &id4_regs); __cache_cpumap_setup(cpu, idx, &id4_regs); } + this_cpu_ci->cpu_map_populated = true; + return 0; } diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index e9fd32e91668..ecde8957835a 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -106,6 +106,9 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) unsigned int index; int ret; + if (this_cpu_ci->cpu_map_populated) + return 0; + ret = cache_setup_of_node(cpu); if (ret) return ret; diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 2189935075b4..a951fd10aaaa 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -71,6 +71,7 @@ struct cpu_cacheinfo { struct cacheinfo *info_list; unsigned int num_levels; unsigned int num_leaves; + bool cpu_map_populated; }; /* From a91cdfa754905b702a5841b8d2b895599d8fad72 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 28 Oct 2016 09:45:29 +0100 Subject: [PATCH 096/427] drivers: base: cacheinfo: fix boot error message when acpi is enabled commit 55877ef45fbd7f975d078426866b7d1a2435dcc3 upstream. ARM64 enables both CONFIG_OF and CONFIG_ACPI and the firmware can pass both ACPI tables and the device tree. Based on the kernel parameter, one of the two will be chosen. If acpi is enabled, then device tree is not unflattened. Currently ARM64 platforms report: " Failed to find cpu0 device node Unable to detect cache hierarchy from DT for CPU 0 " which is incorrect when booting with ACPI. Also latest ACPI v6.1 has no support for cache properties/hierarchy. This patch adds check for unflattened device tree and also returns as "not supported" if ACPI is runtime enabled. It also removes the reference to DT from the error message as the cache hierarchy can be detected from the firmware(OF/DT/ACPI) Cc: Greg Kroah-Hartman Signed-off-by: Sudeep Holla Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Greg Kroah-Hartman --- drivers/base/cacheinfo.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index ecde8957835a..70e13cf06ed0 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -104,12 +105,16 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf, *sib_leaf; unsigned int index; - int ret; + int ret = 0; if (this_cpu_ci->cpu_map_populated) return 0; - ret = cache_setup_of_node(cpu); + if (of_have_populated_dt()) + ret = cache_setup_of_node(cpu); + else if (!acpi_disabled) + /* No cache property/hierarchy support yet in ACPI */ + ret = -ENOTSUPP; if (ret) return ret; @@ -206,8 +211,7 @@ static int detect_cache_attributes(unsigned int cpu) */ ret = cache_shared_cpu_map_setup(cpu); if (ret) { - pr_warn("Unable to detect cache hierarchy from DT for CPU %d\n", - cpu); + pr_warn("Unable to detect cache hierarchy for CPU %d\n", cpu); goto free_ci; } return 0; From 12de6baf0637e2b0067bf5d71c3a7af1ec5b4ff1 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Wed, 27 Jan 2016 09:32:05 -0800 Subject: [PATCH 097/427] PCI: layerscape: Add "fsl,ls2085a-pcie" compatible ID commit dbae40b76abef2f8a7e7bf1701f77df9e73def48 upstream. The Layerscape PCI host driver must recognize ls2085a compatible when using firmware with ls2085a compatible property, otherwise the PCI bus won't be detected even though ls2085a compatible is included by the dts. Signed-off-by: Yang Shi Signed-off-by: Bjorn Helgaas Signed-off-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-layerscape.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index 3923bed93c7e..c40d8b2ce330 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c @@ -203,6 +203,7 @@ static const struct of_device_id ls_pcie_of_match[] = { { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, + { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata }, { }, }; MODULE_DEVICE_TABLE(of, ls_pcie_of_match); From 5ee8fef15d0affce9ff482dd99ff33a0578c2368 Mon Sep 17 00:00:00 2001 From: Minghuan Lian Date: Mon, 29 Feb 2016 17:24:15 -0600 Subject: [PATCH 098/427] PCI: layerscape: Fix MSG TLP drop setting commit 1195c103f6c98d9ff381cac3a8760d4f8a133627 upstream. Some kinds of Layerscape PCIe controllers will forward the received message TLPs to system application address space, which could corrupt system memory or lead to a system hang. Enable MSG_DROP to fix this issue. Signed-off-by: Minghuan Lian Signed-off-by: Bjorn Helgaas Signed-off-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-layerscape.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index c40d8b2ce330..a21e229d95e0 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c @@ -77,6 +77,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie) iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); } +/* Drop MSG TLP except for Vendor MSG */ +static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) +{ + u32 val; + + val = ioread32(pcie->dbi + PCIE_STRFMR1); + val &= 0xDFFFFFFF; + iowrite32(val, pcie->dbi + PCIE_STRFMR1); +} + static int ls1021_pcie_link_up(struct pcie_port *pp) { u32 state; @@ -97,7 +107,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp) static void ls1021_pcie_host_init(struct pcie_port *pp) { struct ls_pcie *pcie = to_ls_pcie(pp); - u32 val, index[2]; + u32 index[2]; pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, "fsl,pcie-scfg"); @@ -116,13 +126,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp) dw_pcie_setup_rc(pp); - /* - * LS1021A Workaround for internal TKT228622 - * to fix the INTx hang issue - */ - val = ioread32(pcie->dbi + PCIE_STRFMR1); - val &= 0xffff; - iowrite32(val, pcie->dbi + PCIE_STRFMR1); + ls_pcie_drop_msg_tlp(pcie); } static int ls_pcie_link_up(struct pcie_port *pp) @@ -147,6 +151,7 @@ static void ls_pcie_host_init(struct pcie_port *pp) iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN); ls_pcie_fix_class(pcie); ls_pcie_clear_multifunction(pcie); + ls_pcie_drop_msg_tlp(pcie); iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN); } From 0fd49331f9c1fee00ad9ef125faea9d14d7c6a59 Mon Sep 17 00:00:00 2001 From: yangbo lu Date: Wed, 25 Nov 2015 10:05:37 +0800 Subject: [PATCH 099/427] mmc: sdhci-of-esdhc: add/remove some quirks according to vendor version commit 1ef5e49e46b919052474d9b54a15debc79ff0133 upstream. A previous patch had removed esdhc_of_platform_init() by mistake. static void esdhc_of_platform_init(struct sdhci_host *host) { u32 vvn; vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; if (vvn == VENDOR_V_22) host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; if (vvn > VENDOR_V_22) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; } This patch is used to fix it by add/remove some quirks according to verdor version in probe. Signed-off-by: Yangbo Lu Fixes: f4932cfd22f1 ("mmc: sdhci-of-esdhc: support both BE and LE host controller") Signed-off-by: Ulf Hansson Signed-off-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-of-esdhc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 90e94a028a49..83b1226471c1 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -584,6 +584,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) { struct sdhci_host *host; struct device_node *np; + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_esdhc *esdhc; int ret; np = pdev->dev.of_node; @@ -600,6 +602,14 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + pltfm_host = sdhci_priv(host); + esdhc = pltfm_host->priv; + if (esdhc->vendor_ver == VENDOR_V_22) + host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; + + if (esdhc->vendor_ver > VENDOR_V_22) + host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; + if (of_device_is_compatible(np, "fsl,p5040-esdhc") || of_device_is_compatible(np, "fsl,p5020-esdhc") || of_device_is_compatible(np, "fsl,p4080-esdhc") || From 13757fc50433b6b6f68c21bd88a094d56514cb5b Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Tue, 11 Oct 2016 13:51:14 -0700 Subject: [PATCH 100/427] fs/select: add vmalloc fallback for select(2) commit 2d19309cf86883f634a4f8ec55a54bda87db19bf upstream. The select(2) syscall performs a kmalloc(size, GFP_KERNEL) where size grows with the number of fds passed. We had a customer report page allocation failures of order-4 for this allocation. This is a costly order, so it might easily fail, as the VM expects such allocation to have a lower-order fallback. Such trivial fallback is vmalloc(), as the memory doesn't have to be physically contiguous and the allocation is temporary for the duration of the syscall only. There were some concerns, whether this would have negative impact on the system by exposing vmalloc() to userspace. Although an excessive use of vmalloc can cause some system wide performance issues - TLB flushes etc. - a large order allocation is not for free either and an excessive reclaim/compaction can have a similar effect. Also note that the size is effectively limited by RLIMIT_NOFILE which defaults to 1024 on the systems I checked. That means the bitmaps will fit well within single page and thus the vmalloc() fallback could be only excercised for processes where root allows a higher limit. Note that the poll(2) syscall seems to use a linked list of order-0 pages, so it doesn't need this kind of fallback. [eric.dumazet@gmail.com: fix failure path logic] [akpm@linux-foundation.org: use proper type for size] Link: http://lkml.kernel.org/r/20160927084536.5923-1-vbabka@suse.cz Signed-off-by: Vlastimil Babka Acked-by: Michal Hocko Cc: Alexander Viro Cc: Eric Dumazet Cc: David Laight Cc: Hillf Danton Cc: Nicholas Piggin Cc: Jason Baron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/select.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/select.c b/fs/select.c index 015547330e88..f4dd55fc638c 100644 --- a/fs/select.c +++ b/fs/select.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -550,7 +551,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set_bits fds; void *bits; int ret, max_fds; - unsigned int size; + size_t size, alloc_size; struct fdtable *fdt; /* Allocate small arguments on the stack to save memory and be faster */ long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; @@ -577,7 +578,14 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, if (size > sizeof(stack_fds) / 6) { /* Not enough space in on-stack array; must use kmalloc */ ret = -ENOMEM; - bits = kmalloc(6 * size, GFP_KERNEL); + if (size > (SIZE_MAX / 6)) + goto out_nofds; + + alloc_size = 6 * size; + bits = kmalloc(alloc_size, GFP_KERNEL|__GFP_NOWARN); + if (!bits && alloc_size > PAGE_SIZE) + bits = vmalloc(alloc_size); + if (!bits) goto out_nofds; } @@ -614,7 +622,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, out: if (bits != stack_fds) - kfree(bits); + kvfree(bits); out_nofds: return ret; } From 7175e56fa7076ea176ffa6dd41ddad288294ddb5 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Mon, 10 Jul 2017 15:49:51 -0700 Subject: [PATCH 101/427] mm/mmap.c: do not blow on PROT_NONE MAP_FIXED holes in the stack commit 561b5e0709e4a248c67d024d4d94b6e31e3edf2f upstream. Commit 1be7107fbe18 ("mm: larger stack guard gap, between vmas") has introduced a regression in some rust and Java environments which are trying to implement their own stack guard page. They are punching a new MAP_FIXED mapping inside the existing stack Vma. This will confuse expand_{downwards,upwards} into thinking that the stack expansion would in fact get us too close to an existing non-stack vma which is a correct behavior wrt safety. It is a real regression on the other hand. Let's work around the problem by considering PROT_NONE mapping as a part of the stack. This is a gros hack but overflowing to such a mapping would trap anyway an we only can hope that usespace knows what it is doing and handle it propely. Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas") Link: http://lkml.kernel.org/r/20170705182849.GA18027@dhcp22.suse.cz Signed-off-by: Michal Hocko Debugged-by: Vlastimil Babka Cc: Ben Hutchings Cc: Willy Tarreau Cc: Oleg Nesterov Cc: Rik van Riel Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index eaa460ddcaf9..cc84b97ca250 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2188,7 +2188,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) gap_addr = TASK_SIZE; next = vma->vm_next; - if (next && next->vm_start < gap_addr) { + if (next && next->vm_start < gap_addr && + (next->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) { if (!(next->vm_flags & VM_GROWSUP)) return -ENOMEM; /* Check that both stack segments have the same anon_vma? */ @@ -2273,7 +2274,8 @@ int expand_downwards(struct vm_area_struct *vma, if (gap_addr > address) return -ENOMEM; prev = vma->vm_prev; - if (prev && prev->vm_end > gap_addr) { + if (prev && prev->vm_end > gap_addr && + (prev->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) { if (!(prev->vm_flags & VM_GROWSDOWN)) return -ENOMEM; /* Check that both stack segments have the same anon_vma? */ From 361376a53481a7e042a1dd320b6bdbde8dc1ba48 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 12 May 2017 15:46:26 -0700 Subject: [PATCH 102/427] hwpoison, memcg: forcibly uncharge LRU pages commit 18365225f0440d09708ad9daade2ec11275c3df9 upstream. Laurent Dufour has noticed that hwpoinsoned pages are kept charged. In his particular case he has hit a bad_page("page still charged to cgroup") when onlining a hwpoison page. While this looks like something that shouldn't happen in the first place because onlining hwpages and returning them to the page allocator makes only little sense it shows a real problem. hwpoison pages do not get freed usually so we do not uncharge them (at least not since commit 0a31bc97c80c ("mm: memcontrol: rewrite uncharge API")). Each charge pins memcg (since e8ea14cc6ead ("mm: memcontrol: take a css reference for each charged page")) as well and so the mem_cgroup and the associated state will never go away. Fix this leak by forcibly uncharging a LRU hwpoisoned page in delete_from_lru_cache(). We also have to tweak uncharge_list because it cannot rely on zero ref count for these pages. [akpm@linux-foundation.org: coding-style fixes] Fixes: 0a31bc97c80c ("mm: memcontrol: rewrite uncharge API") Link: http://lkml.kernel.org/r/20170502185507.GB19165@dhcp22.suse.cz Signed-off-by: Michal Hocko Reported-by: Laurent Dufour Tested-by: Laurent Dufour Reviewed-by: Balbir Singh Reviewed-by: Naoya Horiguchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memcontrol.c | 2 +- mm/memory-failure.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e25b93a4267d..55a9facb8e8d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5576,7 +5576,7 @@ static void uncharge_list(struct list_head *page_list) next = page->lru.next; VM_BUG_ON_PAGE(PageLRU(page), page); - VM_BUG_ON_PAGE(page_count(page), page); + VM_BUG_ON_PAGE(!PageHWPoison(page) && page_count(page), page); if (!page->mem_cgroup) continue; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 091fe9b06663..92a647957f91 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -539,6 +539,13 @@ static int delete_from_lru_cache(struct page *p) */ ClearPageActive(p); ClearPageUnevictable(p); + + /* + * Poisoned page might never drop its ref count to 0 so we have + * to uncharge it manually from its memcg. + */ + mem_cgroup_uncharge(p); + /* * drop the page count elevated by isolate_lru_page() */ From 1ab0bb9834766841e0119d472c78077c459654ac Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Mon, 10 Jul 2017 15:49:44 -0700 Subject: [PATCH 103/427] cma: fix calculation of aligned offset commit e048cb32f69038aa1c8f11e5c1b331be4181659d upstream. The align_offset parameter is used by bitmap_find_next_zero_area_off() to represent the offset of map's base from the previous alignment boundary; the function ensures that the returned index, plus the align_offset, honors the specified align_mask. The logic introduced by commit b5be83e308f7 ("mm: cma: align to physical address, not CMA region position") has the cma driver calculate the offset to the *next* alignment boundary. In most cases, the base alignment is greater than that specified when making allocations, resulting in a zero offset whether we align up or down. In the example given with the commit, the base alignment (8MB) was half the requested alignment (16MB) so the math also happened to work since the offset is 8MB in both directions. However, when requesting allocations with an alignment greater than twice that of the base, the returned index would not be correctly aligned. Also, the align_order arguments of cma_bitmap_aligned_mask() and cma_bitmap_aligned_offset() should not be negative so the argument type was made unsigned. Fixes: b5be83e308f7 ("mm: cma: align to physical address, not CMA region position") Link: http://lkml.kernel.org/r/20170628170742.2895-1-opendmb@gmail.com Signed-off-by: Angus Clark Signed-off-by: Doug Berger Acked-by: Gregory Fong Cc: Doug Berger Cc: Angus Clark Cc: Laura Abbott Cc: Vlastimil Babka Cc: Greg Kroah-Hartman Cc: Lucas Stach Cc: Catalin Marinas Cc: Shiraz Hashim Cc: Jaewon Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Vlastimil Babka Signed-off-by: Greg Kroah-Hartman --- mm/cma.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/mm/cma.c b/mm/cma.c index bd0e1412475e..43f4a122e969 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -54,7 +54,7 @@ unsigned long cma_get_size(const struct cma *cma) } static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, - int align_order) + unsigned int align_order) { if (align_order <= cma->order_per_bit) return 0; @@ -62,17 +62,14 @@ static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, } /* - * Find a PFN aligned to the specified order and return an offset represented in - * order_per_bits. + * Find the offset of the base PFN from the specified align_order. + * The value returned is represented in order_per_bits. */ static unsigned long cma_bitmap_aligned_offset(const struct cma *cma, - int align_order) + unsigned int align_order) { - if (align_order <= cma->order_per_bit) - return 0; - - return (ALIGN(cma->base_pfn, (1UL << align_order)) - - cma->base_pfn) >> cma->order_per_bit; + return (cma->base_pfn & ((1UL << align_order) - 1)) + >> cma->order_per_bit; } static unsigned long cma_bitmap_pages_to_bits(const struct cma *cma, From 90ca50c56bfba6c670c4b32cc062aa4c2b850938 Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Wed, 15 Nov 2017 17:38:30 -0800 Subject: [PATCH 104/427] mm, page_alloc: fix potential false positive in __zone_watermark_ok commit b050e3769c6b4013bb937e879fc43bf1847ee819 upstream. Since commit 97a16fc82a7c ("mm, page_alloc: only enforce watermarks for order-0 allocations"), __zone_watermark_ok() check for high-order allocations will shortcut per-migratetype free list checks for ALLOC_HARDER allocations, and return true as long as there's free page of any migratetype. The intention is that ALLOC_HARDER can allocate from MIGRATE_HIGHATOMIC free lists, while normal allocations can't. However, as a side effect, the watermark check will then also return true when there are pages only on the MIGRATE_ISOLATE list, or (prior to CMA conversion to ZONE_MOVABLE) on the MIGRATE_CMA list. Since the allocation cannot actually obtain isolated pages, and might not be able to obtain CMA pages, this can result in a false positive. The condition should be rare and perhaps the outcome is not a fatal one. Still, it's better if the watermark check is correct. There also shouldn't be a performance tradeoff here. Link: http://lkml.kernel.org/r/20171102125001.23708-1-vbabka@suse.cz Fixes: 97a16fc82a7c ("mm, page_alloc: only enforce watermarks for order-0 allocations") Signed-off-by: Vlastimil Babka Acked-by: Mel Gorman Cc: Joonsoo Kim Cc: Rik van Riel Cc: David Rientjes Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3c70f03d91ec..a4c9cd80c7b6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2468,9 +2468,6 @@ static bool __zone_watermark_ok(struct zone *z, unsigned int order, if (!area->nr_free) continue; - if (alloc_harder) - return true; - for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) { if (!list_empty(&area->free_list[mt])) return true; @@ -2482,6 +2479,9 @@ static bool __zone_watermark_ok(struct zone *z, unsigned int order, return true; } #endif + if (alloc_harder && + !list_empty(&area->free_list[MIGRATE_HIGHATOMIC])) + return true; } return false; } From bab93a6196224c862c679a1b1e97be8ceef926a5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 14 Dec 2016 15:06:07 -0800 Subject: [PATCH 105/427] ipc: msg, make msgrcv work with LONG_MIN commit 999898355e08ae3b92dfd0a08db706e0c6703d30 upstream. When LONG_MIN is passed to msgrcv, one would expect to recieve any message. But convert_mode does *msgtyp = -*msgtyp and -LONG_MIN is undefined. In particular, with my gcc -LONG_MIN produces -LONG_MIN again. So handle this case properly by assigning LONG_MAX to *msgtyp if LONG_MIN was specified as msgtyp to msgrcv. This code: long msg[] = { 100, 200 }; int m = msgget(IPC_PRIVATE, IPC_CREAT | 0644); msgsnd(m, &msg, sizeof(msg), 0); msgrcv(m, &msg, sizeof(msg), LONG_MIN, 0); produces currently nothing: msgget(IPC_PRIVATE, IPC_CREAT|0644) = 65538 msgsnd(65538, {100, "\310\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16, 0) = 0 msgrcv(65538, ... Except a UBSAN warning: UBSAN: Undefined behaviour in ipc/msg.c:745:13 negation of -9223372036854775808 cannot be represented in type 'long int': With the patch, I see what I expect: msgget(IPC_PRIVATE, IPC_CREAT|0644) = 0 msgsnd(0, {100, "\310\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16, 0) = 0 msgrcv(0, {100, "\310\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16, -9223372036854775808, 0) = 16 Link: http://lkml.kernel.org/r/20161024082633.10148-1-jslaby@suse.cz Signed-off-by: Jiri Slaby Cc: Davidlohr Bueso Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- ipc/msg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ipc/msg.c b/ipc/msg.c index c6521c205cb4..f993f441f852 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -742,7 +742,10 @@ static inline int convert_mode(long *msgtyp, int msgflg) if (*msgtyp == 0) return SEARCH_ANY; if (*msgtyp < 0) { - *msgtyp = -*msgtyp; + if (*msgtyp == LONG_MIN) /* -LONG_MIN is undefined */ + *msgtyp = LONG_MAX; + else + *msgtyp = -*msgtyp; return SEARCH_LESSEQUAL; } if (msgflg & MSG_EXCEPT) From 699a6cc7dd321113c99e06c6c997e8d15557439c Mon Sep 17 00:00:00 2001 From: Rui Wang Date: Wed, 8 Jun 2016 14:59:52 +0800 Subject: [PATCH 106/427] x86/ioapic: Fix incorrect pointers in ioapic_setup_resources() commit 9d98bcec731756b8688b59ec998707924d716d7b upstream. On a 4-socket Brickland system, hot-removing one ioapic is fine. Hot-removing the 2nd one causes panic in mp_unregister_ioapic() while calling release_resource(). It is because the iomem_res pointer has already been released when removing the first ioapic. To explain the use of &res[num] here: res is assigned to ioapic_resources, and later in ioapic_insert_resources() we do: struct resource *r = ioapic_resources; for_each_ioapic(i) { insert_resource(&iomem_resource, r); r++; } Here 'r' is treated as an arry of 'struct resource', and the r++ ensures that each element of the array is inserted separately. Thus we should call release_resouce() on each element at &res[num]. Fix it by assigning the correct pointers to ioapics[i].iomem_res in ioapic_setup_resources(). Signed-off-by: Rui Wang Signed-off-by: Thomas Gleixner Cc: tony.luck@intel.com Cc: linux-pci@vger.kernel.org Cc: rjw@rjwysocki.net Cc: linux-acpi@vger.kernel.org Cc: bhelgaas@google.com Link: http://lkml.kernel.org/r/1465369193-4816-3-git-send-email-rui.y.wang@intel.com Signed-off-by: Ingo Molnar Acked-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index fc91c98bee01..fd945099fc95 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2592,8 +2592,8 @@ static struct resource * __init ioapic_setup_resources(void) res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY; snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i); mem += IOAPIC_RESOURCE_NAME_SIZE; + ioapics[i].iomem_res = &res[num]; num++; - ioapics[i].iomem_res = res; } ioapic_resources = res; From 4d48ba75ec7877939e9f69ef66894f7f9ce4cf38 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 2 Jun 2016 01:57:50 +0200 Subject: [PATCH 107/427] ACPI / processor: Avoid reserving IO regions too early commit 86314751c7945fa0c67f459beeda2e7c610ca429 upstream. Roland Dreier reports that one of his systems cannot boot because of the changes made by commit ac212b6980d8 (ACPI / processor: Use common hotplug infrastructure). The problematic part of it is the request_region() call in acpi_processor_get_info() that used to run at module init time before the above commit and now it runs much earlier. Unfortunately, the region(s) reserved by it fall into a range the PCI subsystem attempts to reserve for AHCI IO BARs. As a result, the PCI reservation fails and AHCI doesn't work, while previously the PCI reservation would be made before acpi_processor_get_info() and it would succeed. That request_region() call, however, was overlooked by commit ac212b6980d8, as it is not necessary for the enumeration of the processors. It only is needed when the ACPI processor driver actually attempts to handle them which doesn't happen before loading the ACPI processor driver module. Therefore that call should have been moved from acpi_processor_get_info() into that module. Address the problem by moving the request_region() call in question out of acpi_processor_get_info() and use the observation that the region reserved by it is only needed if the FADT-based CPU throttling method is going to be used, which means that it should be sufficient to invoke it from acpi_processor_get_throttling_fadt(). Fixes: ac212b6980d8 (ACPI / processor: Use common hotplug infrastructure) Reported-by: Roland Dreier Tested-by: Roland Dreier Signed-off-by: Rafael J. Wysocki Acked-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpi_processor.c | 9 --------- drivers/acpi/processor_throttling.c | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 9f77943653fb..b63a173786d5 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -331,15 +331,6 @@ static int acpi_processor_get_info(struct acpi_device *device) pr->throttling.duty_width = acpi_gbl_FADT.duty_width; pr->pblk = object.processor.pblk_address; - - /* - * We don't care about error returns - we just try to mark - * these reserved so that nobody else is confused into thinking - * that this region might be unused.. - * - * (In particular, allocating the IO range for Cardbus) - */ - request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } /* diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index f170d746336d..c72e64893d03 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -676,6 +676,15 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) if (!pr->flags.throttling) return -ENODEV; + /* + * We don't care about error returns - we just try to mark + * these reserved so that nobody else is confused into thinking + * that this region might be unused.. + * + * (In particular, allocating the IO range for Cardbus) + */ + request_region(pr->throttling.address, 6, "ACPI CPU throttle"); + pr->throttling.state = 0; duty_mask = pr->throttling.state_count - 1; From 1fe277d48f998bd928f1b6ddcbe72f2a34b6f5ad Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 30 Dec 2016 02:27:31 +0100 Subject: [PATCH 108/427] ACPI / scan: Prefer devices without _HID/_CID for _ADR matching commit c2a6bbaf0c5f90463a7011a295bbdb7e33c80b51 upstream. The way acpi_find_child_device() works currently is that, if there are two (or more) devices with the same _ADR value in the same namespace scope (which is not specifically allowed by the spec and the OS behavior in that case is not defined), the first one of them found to be present (with the help of _STA) will be returned. This covers the majority of cases, but is not sufficient if some of the devices in question have a _HID (or _CID) returning some valid ACPI/PNP device IDs (which is disallowed by the spec) and the ASL writers' expectation appears to be that the OS will match devices without a valid ACPI/PNP device ID against a given bus address first. To cover this special case as well, modify find_child_checks() to prefer devices without ACPI/PNP device IDs over devices that have them. Suggested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki Tested-by: Hans de Goede Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/glue.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 73c9c7fa9001..f06317d6fc38 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -99,13 +99,13 @@ static int find_child_checks(struct acpi_device *adev, bool check_children) return -ENODEV; /* - * If the device has a _HID (or _CID) returning a valid ACPI/PNP - * device ID, it is better to make it look less attractive here, so that - * the other device with the same _ADR value (that may not have a valid - * device ID) can be matched going forward. [This means a second spec - * violation in a row, so whatever we do here is best effort anyway.] + * If the device has a _HID returning a valid ACPI/PNP device ID, it is + * better to make it look less attractive here, so that the other device + * with the same _ADR value (that may not have a valid device ID) can be + * matched going forward. [This means a second spec violation in a row, + * so whatever we do here is best effort anyway.] */ - return sta_present && list_empty(&adev->pnp.ids) ? + return sta_present && !adev->pnp.type.platform_id ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; } From 4c19b00e5588828f0d3198b926efade766dcf2c8 Mon Sep 17 00:00:00 2001 From: Seunghun Han Date: Wed, 26 Apr 2017 16:18:08 +0800 Subject: [PATCH 109/427] ACPICA: Namespace: fix operand cache leak commit 3b2d69114fefa474fca542e51119036dceb4aa6f upstream. ACPICA commit a23325b2e583556eae88ed3f764e457786bf4df6 I found some ACPI operand cache leaks in ACPI early abort cases. Boot log of ACPI operand cache leak is as follows: >[ 0.174332] ACPI: Added _OSI(Module Device) >[ 0.175504] ACPI: Added _OSI(Processor Device) >[ 0.176010] ACPI: Added _OSI(3.0 _SCP Extensions) >[ 0.177032] ACPI: Added _OSI(Processor Aggregator Device) >[ 0.178284] ACPI: SCI (IRQ16705) allocation failed >[ 0.179352] ACPI Exception: AE_NOT_ACQUIRED, Unable to install System Control Interrupt handler (20160930/evevent-131) >[ 0.180008] ACPI: Unable to start the ACPI Interpreter >[ 0.181125] ACPI Error: Could not remove SCI handler (20160930/evmisc-281) >[ 0.184068] kmem_cache_destroy Acpi-Operand: Slab cache still has objects >[ 0.185358] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.10.0-rc3 #2 >[ 0.186820] Hardware name: innotek gmb_h virtual_box/virtual_box, BIOS virtual_box 12/01/2006 >[ 0.188000] Call Trace: >[ 0.188000] ? dump_stack+0x5c/0x7d >[ 0.188000] ? kmem_cache_destroy+0x224/0x230 >[ 0.188000] ? acpi_sleep_proc_init+0x22/0x22 >[ 0.188000] ? acpi_os_delete_cache+0xa/0xd >[ 0.188000] ? acpi_ut_delete_caches+0x3f/0x7b >[ 0.188000] ? acpi_terminate+0x5/0xf >[ 0.188000] ? acpi_init+0x288/0x32e >[ 0.188000] ? __class_create+0x4c/0x80 >[ 0.188000] ? video_setup+0x7a/0x7a >[ 0.188000] ? do_one_initcall+0x4e/0x1b0 >[ 0.188000] ? kernel_init_freeable+0x194/0x21a >[ 0.188000] ? rest_init+0x80/0x80 >[ 0.188000] ? kernel_init+0xa/0x100 >[ 0.188000] ? ret_from_fork+0x25/0x30 When early abort is occurred due to invalid ACPI information, Linux kernel terminates ACPI by calling acpi_terminate() function. The function calls acpi_ns_terminate() function to delete namespace data and ACPI operand cache (acpi_gbl_module_code_list). But the deletion code in acpi_ns_terminate() function is wrapped in ACPI_EXEC_APP definition, therefore the code is only executed when the definition exists. If the define doesn't exist, ACPI operand cache (acpi_gbl_module_code_list) is leaked, and stack dump is shown in kernel log. This causes a security threat because the old kernel (<= 4.9) shows memory locations of kernel functions in stack dump, therefore kernel ASLR can be neutralized. To fix ACPI operand leak for enhancing security, I made a patch which removes the ACPI_EXEC_APP define in acpi_ns_terminate() function for executing the deletion code unconditionally. Link: https://github.com/acpica/acpica/commit/a23325b2 Signed-off-by: Seunghun Han Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Acked-by: Lee, Chun-Yi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/nsutils.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index de325ae04ce1..3b3c5b90bd20 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -593,25 +593,20 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) void acpi_ns_terminate(void) { acpi_status status; + union acpi_operand_object *prev; + union acpi_operand_object *next; ACPI_FUNCTION_TRACE(ns_terminate); -#ifdef ACPI_EXEC_APP - { - union acpi_operand_object *prev; - union acpi_operand_object *next; + /* Delete any module-level code blocks */ - /* Delete any module-level code blocks */ - - next = acpi_gbl_module_code_list; - while (next) { - prev = next; - next = next->method.mutex; - prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */ - acpi_ut_remove_reference(prev); - } + next = acpi_gbl_module_code_list; + while (next) { + prev = next; + next = next->method.mutex; + prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */ + acpi_ut_remove_reference(prev); } -#endif /* * Free the entire namespace -- all nodes and all objects From 45cf54e13c70ce0ec4875220103916978ce3ed07 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 14 Jul 2016 17:51:26 +0200 Subject: [PATCH 110/427] netfilter: x_tables: speed up jump target validation commit f4dc77713f8016d2e8a3295e1c9c53a21f296def upstream. The dummy ruleset I used to test the original validation change was broken, most rules were unreachable and were not tested by mark_source_chains(). In some cases rulesets that used to load in a few seconds now require several minutes. sample ruleset that shows the behaviour: echo "*filter" for i in $(seq 0 100000);do printf ":chain_%06x - [0:0]\n" $i done for i in $(seq 0 100000);do printf -- "-A INPUT -j chain_%06x\n" $i printf -- "-A INPUT -j chain_%06x\n" $i printf -- "-A INPUT -j chain_%06x\n" $i done echo COMMIT [ pipe result into iptables-restore ] This ruleset will be about 74mbyte in size, with ~500k searches though all 500k[1] rule entries. iptables-restore will take forever (gave up after 10 minutes) Instead of always searching the entire blob for a match, fill an array with the start offsets of every single ipt_entry struct, then do a binary search to check if the jump target is present or not. After this change ruleset restore times get again close to what one gets when reverting 36472341017529e (~3 seconds on my workstation). [1] every user-defined rule gets an implicit RETURN, so we get 300k jumps + 100k userchains + 100k returns -> 500k rule entries Fixes: 36472341017529e ("netfilter: x_tables: validate targets of jumps") Reported-by: Jeff Wu Tested-by: Jeff Wu Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- include/linux/netfilter/x_tables.h | 4 +++ net/ipv4/netfilter/arp_tables.c | 47 +++++++++++++++------------- net/ipv4/netfilter/ip_tables.c | 45 ++++++++++++++------------- net/ipv6/netfilter/ip6_tables.c | 45 ++++++++++++++------------- net/netfilter/x_tables.c | 50 ++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 04078e8a4803..26a41ddd3dec 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -243,6 +243,10 @@ int xt_check_entry_offsets(const void *base, const char *elems, unsigned int target_offset, unsigned int next_offset); +unsigned int *xt_alloc_entry_offsets(unsigned int size); +bool xt_find_jump_offset(const unsigned int *offsets, + unsigned int target, unsigned int size); + int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, bool inv_proto); int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 6e3e0e8b1ce3..d6531c544a82 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -367,23 +367,12 @@ static inline bool unconditional(const struct arpt_entry *e) memcmp(&e->arp, &uncond, sizeof(uncond)) == 0; } -static bool find_jump_target(const struct xt_table_info *t, - const struct arpt_entry *target) -{ - struct arpt_entry *iter; - - xt_entry_foreach(iter, t->entries, t->size) { - if (iter == target) - return true; - } - return false; -} - /* Figures out from what hook each rule can be called: returns 0 if * there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0) + unsigned int valid_hooks, void *entry0, + unsigned int *offsets) { unsigned int hook; @@ -472,10 +461,11 @@ static int mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + if (!xt_find_jump_offset(offsets, newpos, + newinfo->number)) + return 0; e = (struct arpt_entry *) (entry0 + newpos); - if (!find_jump_target(newinfo, e)) - return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; @@ -642,6 +632,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, const struct arpt_replace *repl) { struct arpt_entry *iter; + unsigned int *offsets; unsigned int i; int ret = 0; @@ -655,6 +646,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); + offsets = xt_alloc_entry_offsets(newinfo->number); + if (!offsets) + return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ @@ -665,7 +659,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, repl->underflow, repl->valid_hooks); if (ret != 0) - break; + goto out_free; + if (i < repl->num_entries) + offsets[i] = (void *)iter - entry0; ++i; if (strcmp(arpt_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) @@ -673,12 +669,13 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); if (ret != 0) - return ret; + goto out_free; + ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - return -EINVAL; + goto out_free; } /* Check hooks all assigned */ @@ -689,17 +686,20 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - return -EINVAL; + goto out_free; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - return -EINVAL; + goto out_free; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) - return -ELOOP; + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { + ret = -ELOOP; + goto out_free; + } + kvfree(offsets); /* Finally, each sanity check must pass */ i = 0; @@ -719,6 +719,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, return ret; } + return ret; + out_free: + kvfree(offsets); return ret; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index a399c5419622..2ba158f2cb72 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -443,23 +443,12 @@ ipt_do_table(struct sk_buff *skb, #endif } -static bool find_jump_target(const struct xt_table_info *t, - const struct ipt_entry *target) -{ - struct ipt_entry *iter; - - xt_entry_foreach(iter, t->entries, t->size) { - if (iter == target) - return true; - } - return false; -} - /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0) + unsigned int valid_hooks, void *entry0, + unsigned int *offsets) { unsigned int hook; @@ -552,10 +541,11 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + if (!xt_find_jump_offset(offsets, newpos, + newinfo->number)) + return 0; e = (struct ipt_entry *) (entry0 + newpos); - if (!find_jump_target(newinfo, e)) - return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; @@ -811,6 +801,7 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, const struct ipt_replace *repl) { struct ipt_entry *iter; + unsigned int *offsets; unsigned int i; int ret = 0; @@ -824,6 +815,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); + offsets = xt_alloc_entry_offsets(newinfo->number); + if (!offsets) + return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { @@ -833,17 +827,20 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, repl->underflow, repl->valid_hooks); if (ret != 0) - return ret; + goto out_free; + if (i < repl->num_entries) + offsets[i] = (void *)iter - entry0; ++i; if (strcmp(ipt_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) ++newinfo->stacksize; } + ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - return -EINVAL; + goto out_free; } /* Check hooks all assigned */ @@ -854,17 +851,20 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - return -EINVAL; + goto out_free; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - return -EINVAL; + goto out_free; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) - return -ELOOP; + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { + ret = -ELOOP; + goto out_free; + } + kvfree(offsets); /* Finally, each sanity check must pass */ i = 0; @@ -884,6 +884,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, return ret; } + return ret; + out_free: + kvfree(offsets); return ret; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 22f39e00bef3..c26bed92f523 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -455,23 +455,12 @@ ip6t_do_table(struct sk_buff *skb, #endif } -static bool find_jump_target(const struct xt_table_info *t, - const struct ip6t_entry *target) -{ - struct ip6t_entry *iter; - - xt_entry_foreach(iter, t->entries, t->size) { - if (iter == target) - return true; - } - return false; -} - /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0) + unsigned int valid_hooks, void *entry0, + unsigned int *offsets) { unsigned int hook; @@ -564,10 +553,11 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + if (!xt_find_jump_offset(offsets, newpos, + newinfo->number)) + return 0; e = (struct ip6t_entry *) (entry0 + newpos); - if (!find_jump_target(newinfo, e)) - return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; @@ -823,6 +813,7 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, const struct ip6t_replace *repl) { struct ip6t_entry *iter; + unsigned int *offsets; unsigned int i; int ret = 0; @@ -836,6 +827,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); + offsets = xt_alloc_entry_offsets(newinfo->number); + if (!offsets) + return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { @@ -845,17 +839,20 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, repl->underflow, repl->valid_hooks); if (ret != 0) - return ret; + goto out_free; + if (i < repl->num_entries) + offsets[i] = (void *)iter - entry0; ++i; if (strcmp(ip6t_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) ++newinfo->stacksize; } + ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - return -EINVAL; + goto out_free; } /* Check hooks all assigned */ @@ -866,17 +863,20 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - return -EINVAL; + goto out_free; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - return -EINVAL; + goto out_free; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) - return -ELOOP; + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { + ret = -ELOOP; + goto out_free; + } + kvfree(offsets); /* Finally, each sanity check must pass */ i = 0; @@ -896,6 +896,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, return ret; } + return ret; + out_free: + kvfree(offsets); return ret; } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 2fc6ca9d1286..7b42b0ad3f9b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -701,6 +701,56 @@ int xt_check_entry_offsets(const void *base, } EXPORT_SYMBOL(xt_check_entry_offsets); +/** + * xt_alloc_entry_offsets - allocate array to store rule head offsets + * + * @size: number of entries + * + * Return: NULL or kmalloc'd or vmalloc'd array + */ +unsigned int *xt_alloc_entry_offsets(unsigned int size) +{ + unsigned int *off; + + off = kcalloc(size, sizeof(unsigned int), GFP_KERNEL | __GFP_NOWARN); + + if (off) + return off; + + if (size < (SIZE_MAX / sizeof(unsigned int))) + off = vmalloc(size * sizeof(unsigned int)); + + return off; +} +EXPORT_SYMBOL(xt_alloc_entry_offsets); + +/** + * xt_find_jump_offset - check if target is a valid jump offset + * + * @offsets: array containing all valid rule start offsets of a rule blob + * @target: the jump target to search for + * @size: entries in @offset + */ +bool xt_find_jump_offset(const unsigned int *offsets, + unsigned int target, unsigned int size) +{ + int m, low = 0, hi = size; + + while (hi > low) { + m = (low + hi) / 2u; + + if (offsets[m] > target) + hi = m; + else if (offsets[m] < target) + low = m + 1; + else + return true; + } + + return false; +} +EXPORT_SYMBOL(xt_find_jump_offset); + int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { From a84338dad3c9501a5301db27ee665cda663219fc Mon Sep 17 00:00:00 2001 From: Hongxu Jia Date: Tue, 29 Nov 2016 21:56:26 -0500 Subject: [PATCH 111/427] netfilter: arp_tables: fix invoking 32bit "iptable -P INPUT ACCEPT" failed in 64bit kernel commit 17a49cd549d9dc8707dc9262210166455c612dde upstream. Since 09d9686047db ("netfilter: x_tables: do compat validation via translate_table"), it used compatr structure to assign newinfo structure. In translate_compat_table of ip_tables.c and ip6_tables.c, it used compatr->hook_entry to replace info->hook_entry and compatr->underflow to replace info->underflow, but not do the same replacement in arp_tables.c. It caused invoking 32-bit "arptbale -P INPUT ACCEPT" failed in 64bit kernel. -------------------------------------- root@qemux86-64:~# arptables -P INPUT ACCEPT root@qemux86-64:~# arptables -P INPUT ACCEPT ERROR: Policy for `INPUT' offset 448 != underflow 0 arptables: Incompatible with this kernel -------------------------------------- Fixes: 09d9686047db ("netfilter: x_tables: do compat validation via translate_table") Signed-off-by: Hongxu Jia Acked-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/arp_tables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index d6531c544a82..c75211528991 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1339,8 +1339,8 @@ static int translate_compat_table(struct xt_table_info **pinfo, newinfo->number = compatr->num_entries; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { - newinfo->hook_entry[i] = info->hook_entry[i]; - newinfo->underflow[i] = info->underflow[i]; + newinfo->hook_entry[i] = compatr->hook_entry[i]; + newinfo->underflow[i] = compatr->underflow[i]; } entry1 = newinfo->entries; pos = entry1; From da00455d38a73c9412dd3f99285b48753ff1b61a Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 26 May 2016 19:08:10 +0200 Subject: [PATCH 112/427] netfilter: nf_dup_ipv6: set again FLOWI_FLAG_KNOWN_NH at flowi6_flags commit 83170f3beccccd7ceb4f9a0ac0c4dc736afde90c upstream. With the commit 48e8aa6e3137 ("ipv6: Set FLOWI_FLAG_KNOWN_NH at flowi6_flags") ip6_pol_route() callers were asked to to set the FLOWI_FLAG_KNOWN_NH properly and xt_TEE was updated accordingly, but with the later refactor in commit bbde9fc1824a ("netfilter: factor out packet duplication for IPv4/IPv6") the flowi6_flags update was lost. This commit re-add it just before the routing decision. Fixes: bbde9fc1824a ("netfilter: factor out packet duplication for IPv4/IPv6") Signed-off-by: Paolo Abeni Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/ipv6/netfilter/nf_dup_ipv6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/netfilter/nf_dup_ipv6.c b/net/ipv6/netfilter/nf_dup_ipv6.c index 6989c70ae29f..4a84b5ad9ecb 100644 --- a/net/ipv6/netfilter/nf_dup_ipv6.c +++ b/net/ipv6/netfilter/nf_dup_ipv6.c @@ -33,6 +33,7 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb, fl6.daddr = *gw; fl6.flowlabel = (__force __be32)(((iph->flow_lbl[0] & 0xF) << 16) | (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]); + fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH; dst = ip6_route_output(net, NULL, &fl6); if (dst->error) { dst_release(dst); From d8f5cce0a8bce0decd125ef430ee6196692ff8da Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Mon, 8 Aug 2016 21:57:58 +0800 Subject: [PATCH 113/427] netfilter: nf_ct_expect: remove the redundant slash when policy name is empty commit b173a28f62cf929324a8a6adcc45adadce311d16 upstream. The 'name' filed in struct nf_conntrack_expect_policy{} is not a pointer, so check it is NULL or not will always return true. Even if the name is empty, slash will always be displayed like follows: # cat /proc/net/nf_conntrack_expect 297 l3proto = 2 proto=6 src=1.1.1.1 dst=2.2.2.2 sport=1 dport=1025 ftp/ ^ Fixes: 3a8fc53a45c4 ("netfilter: nf_ct_helper: allocate 16 bytes for the helper and policy names") Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_expect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 7f16d19d6198..a91f8bd51d05 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -560,7 +560,7 @@ static int exp_seq_show(struct seq_file *s, void *v) helper = rcu_dereference(nfct_help(expect->master)->helper); if (helper) { seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); - if (helper->expect_policy[expect->class].name) + if (helper->expect_policy[expect->class].name[0]) seq_printf(s, "/%s", helper->expect_policy[expect->class].name); } From 2adda392d28baa25ca7803002fdafcaa95b7b1fb Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Mon, 8 Aug 2016 22:07:27 +0800 Subject: [PATCH 114/427] netfilter: nfnetlink_queue: reject verdict request from different portid commit 00a3101f561816e58de054a470484996f78eb5eb upstream. Like NFQNL_MSG_VERDICT_BATCH do, we should also reject the verdict request when the portid is not same with the initial portid(maybe from another process). Fixes: 97d32cf9440d ("netfilter: nfnetlink_queue: batch verdict support") Signed-off-by: Liping Zhang Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nfnetlink_queue.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index f6837f9b6d6c..c14d2e8eaec3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -1053,10 +1053,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct net *net = sock_net(ctnl); struct nfnl_queue_net *q = nfnl_queue_pernet(net); - queue = instance_lookup(q, queue_num); - if (!queue) - queue = verdict_instance_lookup(q, queue_num, - NETLINK_CB(skb).portid); + queue = verdict_instance_lookup(q, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); From 2cf26badef7bde1f9ecb9fbdea2079ce366f3013 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 25 Aug 2016 15:33:29 +0200 Subject: [PATCH 115/427] netfilter: restart search if moved to other chain commit 95a8d19f28e6b29377a880c6264391a62e07fccc upstream. In case nf_conntrack_tuple_taken did not find a conflicting entry check that all entries in this hash slot were tested and restart in case an entry was moved to another chain. Reported-by: Eric Dumazet Fixes: ea781f197d6a ("netfilter: nf_conntrack: use SLAB_DESTROY_BY_RCU and get rid of call_rcu()") Signed-off-by: Florian Westphal Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 86a3c6f0c871..5f747089024f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -719,6 +719,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, * least once for the stats anyway. */ rcu_read_lock_bh(); + begin: hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (ct != ignored_conntrack && @@ -730,6 +731,12 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, } NF_CT_STAT_INC(net, searched); } + + if (get_nulls_value(n) != hash) { + NF_CT_STAT_INC(net, search_restart); + goto begin; + } + rcu_read_unlock_bh(); return 0; From 80291566d8f324563f2d889ef5a470e223d44f5c Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Mon, 24 Oct 2016 18:07:23 +0200 Subject: [PATCH 116/427] netfilter: nf_conntrack_sip: extend request line validation commit 444f901742d054a4cd5ff045871eac5131646cfb upstream. on SIP requests, so a fragmented TCP SIP packet from an allow header starting with INVITE,NOTIFY,OPTIONS,REFER,REGISTER,UPDATE,SUBSCRIBE Content-Length: 0 will not bet interpreted as an INVITE request. Also Request-URI must start with an alphabetic character. Confirm with RFC 3261 Request-Line = Method SP Request-URI SP SIP-Version CRLF Fixes: 30f33e6dee80 ("[NETFILTER]: nf_conntrack_sip: support method specific request/response handling") Signed-off-by: Ulrich Weber Acked-by: Marco Angaroni Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_sip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 885b4aba3695..1665c2159e4b 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1434,9 +1434,12 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff, handler = &sip_handlers[i]; if (handler->request == NULL) continue; - if (*datalen < handler->len || + if (*datalen < handler->len + 2 || strncasecmp(*dptr, handler->method, handler->len)) continue; + if ((*dptr)[handler->len] != ' ' || + !isalpha((*dptr)[handler->len+1])) + continue; if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, &matchoff, &matchlen) <= 0) { From f4ca7cba8ffa94c43913ed322c7d35ab3d6d1e38 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 6 Jan 2017 20:33:27 +0100 Subject: [PATCH 117/427] netfilter: use fwmark_reflect in nf_send_reset commit cc31d43b4154ad5a7d8aa5543255a93b7e89edc2 upstream. Otherwise, RST packets generated by ipt_REJECT always have mark 0 when the routing is checked later in the same code path. Fixes: e110861f8609 ("net: add a sysctl to reflect the fwmark on replies") Cc: Lorenzo Colitti Signed-off-by: Pau Espin Pedrol Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/nf_reject_ipv4.c | 2 ++ net/ipv6/netfilter/nf_reject_ipv6.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index c747b2d9eb77..d4acf38b60fd 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c @@ -124,6 +124,8 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) /* ip_route_me_harder expects skb->dst to be set */ skb_dst_set_noref(nskb, skb_dst(oldskb)); + nskb->mark = IP4_REPLY_MARK(net, oldskb->mark); + skb_reserve(nskb, LL_MAX_HEADER); niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, ip4_dst_hoplimit(skb_dst(nskb))); diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index e0f922b777e3..7117e5bef412 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -157,6 +157,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) fl6.daddr = oip6h->saddr; fl6.fl6_sport = otcph->dest; fl6.fl6_dport = otcph->source; + fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark); security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); dst = ip6_route_output(net, NULL, &fl6); if (dst == NULL || dst->error) { @@ -180,6 +181,8 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) skb_dst_set(nskb, dst); + nskb->mark = fl6.flowi6_mark; + skb_reserve(nskb, hh_len + dst->header_len); ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, ip6_dst_hoplimit(dst)); From 936b21419e7c5be2f81e6dea02fc3d8852f3fb83 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 29 Apr 2016 10:39:34 +0200 Subject: [PATCH 118/427] netfilter: fix IS_ERR_VALUE usage commit 92b4423e3a0bc5d43ecde4bcad871f8b5ba04efd upstream. This is a forward-port of the original patch from Andrzej Hajda, he said: "IS_ERR_VALUE should be used only with unsigned long type. Otherwise it can work incorrectly. To achieve this function xt_percpu_counter_alloc is modified to return unsigned long, and its result is assigned to temporary variable to perform error checking, before assigning to .pcnt field. The patch follows conclusion from discussion on LKML [1][2]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2120927 [2]: http://permalink.gmane.org/gmane.linux.kernel/2150581" Original patch from Andrzej is here: http://patchwork.ozlabs.org/patch/582970/ This patch has clashed with input validation fixes for x_tables. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman Acked-by: Michal Kubecek --- include/linux/netfilter/x_tables.h | 6 +++--- net/ipv4/netfilter/arp_tables.c | 6 ++++-- net/ipv4/netfilter/ip_tables.c | 6 ++++-- net/ipv6/netfilter/ip6_tables.c | 6 ++++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 26a41ddd3dec..d6c53fce006b 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -381,16 +381,16 @@ static inline unsigned long ifname_compare_aligned(const char *_a, * allows us to return 0 for single core systems without forcing * callers to deal with SMP vs. NONSMP issues. */ -static inline u64 xt_percpu_counter_alloc(void) +static inline unsigned long xt_percpu_counter_alloc(void) { if (nr_cpu_ids > 1) { void __percpu *res = __alloc_percpu(sizeof(struct xt_counters), sizeof(struct xt_counters)); if (res == NULL) - return (u64) -ENOMEM; + return -ENOMEM; - return (u64) (__force unsigned long) res; + return (__force unsigned long) res; } return 0; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index c75211528991..4cfcc22f7430 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -511,11 +511,13 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) { struct xt_entry_target *t; struct xt_target *target; + unsigned long pcnt; int ret; - e->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(e->counters.pcnt)) + pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(pcnt)) return -ENOMEM; + e->counters.pcnt = pcnt; t = arpt_get_target(e); target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2ba158f2cb72..a98173d1ea97 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -653,10 +653,12 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, unsigned int j; struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; + unsigned long pcnt; - e->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(e->counters.pcnt)) + pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(pcnt)) return -ENOMEM; + e->counters.pcnt = pcnt; j = 0; mtpar.net = net; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index c26bed92f523..bb1b5453a7a1 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -666,10 +666,12 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, unsigned int j; struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; + unsigned long pcnt; - e->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(e->counters.pcnt)) + pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(pcnt)) return -ENOMEM; + e->counters.pcnt = pcnt; j = 0; mtpar.net = net; From a359a437fbc6bb08aa9cc8e25ef4ac3b77ca727b Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sun, 3 Dec 2017 12:12:45 -0800 Subject: [PATCH 119/427] netfilter: nfnetlink_cthelper: Add missing permission checks commit 4b380c42f7d00a395feede754f0bc2292eebe6e5 upstream. The capability check in nfnetlink_rcv() verifies that the caller has CAP_NET_ADMIN in the namespace that "owns" the netlink socket. However, nfnl_cthelper_list is shared by all net namespaces on the system. An unprivileged user can create user and net namespaces in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable() check: $ nfct helper list nfct v1.4.4: netlink error: Operation not permitted $ vpnns -- nfct helper list { .name = ftp, .queuenum = 0, .l3protonum = 2, .l4protonum = 6, .priv_data_len = 24, .status = enabled, }; Add capable() checks in nfnetlink_cthelper, as this is cleaner than trying to generalize the solution. Signed-off-by: Kevin Cernekee Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nfnetlink_cthelper.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 8d34a488efc0..ac143ae4f7b6 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -392,6 +393,9 @@ nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb, struct nfnl_cthelper *nlcth; int ret = 0; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE]) return -EINVAL; @@ -595,6 +599,9 @@ nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb, struct nfnl_cthelper *nlcth; bool tuple_set = false; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = nfnl_cthelper_dump_table, @@ -661,6 +668,9 @@ nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb, struct nfnl_cthelper *nlcth, *n; int j = 0, ret; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (tb[NFCTH_NAME]) helper_name = nla_data(tb[NFCTH_NAME]); From d01ceb4722cd8d64176272434fe332b596750d9c Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 5 Dec 2017 15:42:41 -0800 Subject: [PATCH 120/427] netfilter: xt_osf: Add missing permission checks commit 916a27901de01446bcf57ecca4783f6cff493309 upstream. The capability check in nfnetlink_rcv() verifies that the caller has CAP_NET_ADMIN in the namespace that "owns" the netlink socket. However, xt_osf_fingers is shared by all net namespaces on the system. An unprivileged user can create user and net namespaces in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable() check: vpnns -- nfnl_osf -f /tmp/pf.os vpnns -- nfnl_osf -f /tmp/pf.os -d These non-root operations successfully modify the systemwide OS fingerprint list. Add new capable() checks so that they can't. Signed-off-by: Kevin Cernekee Signed-off-by: Pablo Neira Ayuso Acked-by: Michal Kubecek Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_osf.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index df8801e02a32..7eae0d0af89a 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -69,6 +70,9 @@ static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, struct xt_osf_finger *kf = NULL, *sf; int err = 0; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; @@ -112,6 +116,9 @@ static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb, struct xt_osf_finger *sf; int err = -ENOENT; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; From 8e8224de0e1848a5905ebda018969e2ce72258ca Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 21 Jun 2017 14:34:15 +0200 Subject: [PATCH 121/427] ext2: Don't clear SGID when inheriting ACLs commit a992f2d38e4ce17b8c7d1f7f67b2de0eebdea069 upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by creating __ext2_set_acl() function that does not call posix_acl_update_mode() and use it when inheriting ACLs. That prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: stable@vger.kernel.org CC: linux-ext4@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext2/acl.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index d6aeb84e90b6..d882d873c5a3 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -178,11 +178,8 @@ ext2_get_acl(struct inode *inode, int type) return acl; } -/* - * inode->i_mutex: down - */ -int -ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +static int +__ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int name_index; void *value = NULL; @@ -192,13 +189,6 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; - if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) - return error; - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - } break; case ACL_TYPE_DEFAULT: @@ -224,6 +214,24 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) return error; } +/* + * inode->i_mutex: down + */ +int +ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + int error; + + if (type == ACL_TYPE_ACCESS && acl) { + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) + return error; + inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); + } + return __ext2_set_acl(inode, acl, type); +} + /* * Initialize the ACLs of a new inode. Called from ext2_new_inode. * @@ -241,12 +249,12 @@ ext2_init_acl(struct inode *inode, struct inode *dir) return error; if (default_acl) { - error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + error = __ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } if (acl) { if (!error) - error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS); + error = __ext2_set_acl(inode, acl, ACL_TYPE_ACCESS); posix_acl_release(acl); } return error; From ac125d89f8e980f100f63634a81b84fed7e997cf Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 22 Jun 2017 16:47:34 -0400 Subject: [PATCH 122/427] reiserfs: fix race in prealloc discard commit 08db141b5313ac2f64b844fb5725b8d81744b417 upstream. The main loop in __discard_prealloc is protected by the reiserfs write lock which is dropped across schedules like the BKL it replaced. The problem is that it checks the value, calls a routine that schedules, and then adjusts the state. As a result, two threads that are calling reiserfs_prealloc_discard at the same time can race when one calls reiserfs_free_prealloc_block, the lock is dropped, and the other calls reiserfs_free_prealloc_block with the same block number. In the right circumstances, it can cause the prealloc count to go negative. Signed-off-by: Jeff Mahoney Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/bitmap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index dc198bc64c61..73705d4bb069 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -513,9 +513,17 @@ static void __discard_prealloc(struct reiserfs_transaction_handle *th, "inode has negative prealloc blocks count."); #endif while (ei->i_prealloc_count > 0) { - reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block); - ei->i_prealloc_block++; + b_blocknr_t block_to_free; + + /* + * reiserfs_free_prealloc_block can drop the write lock, + * which could allow another caller to free the same block. + * We can protect against it by modifying the prealloc + * state before calling it. + */ + block_to_free = ei->i_prealloc_block++; ei->i_prealloc_count--; + reiserfs_free_prealloc_block(th, inode, block_to_free); dirty = 1; } if (dirty) From 512e3b18531eb9526a1e695c19043f78e3a0abb1 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 22 Jun 2017 16:35:04 -0400 Subject: [PATCH 123/427] reiserfs: don't preallocate blocks for extended attributes commit 54930dfeb46e978b447af0fb8ab4e181c1bf9d7a upstream. Most extended attributes will fit in a single block. More importantly, we drop the reference to the inode while holding the transaction open so the preallocated blocks aren't released. As a result, the inode may be evicted before it's removed from the transaction's prealloc list which can cause memory corruption. Signed-off-by: Jeff Mahoney Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 73705d4bb069..edc8ef78b63f 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -1136,7 +1136,7 @@ static int determine_prealloc_size(reiserfs_blocknr_hint_t * hint) hint->prealloc_size = 0; if (!hint->formatted_node && hint->preallocate) { - if (S_ISREG(hint->inode->i_mode) + if (S_ISREG(hint->inode->i_mode) && !IS_PRIVATE(hint->inode) && hint->inode->i_size >= REISERFS_SB(hint->th->t_super)->s_alloc_options. preallocmin * hint->inode->i_sb->s_blocksize) From e22c8378505e1354b4346c7ecccb446b7c505deb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 22 Jun 2017 09:32:49 +0200 Subject: [PATCH 124/427] reiserfs: Don't clear SGID when inheriting ACLs commit 6883cd7f68245e43e91e5ee583b7550abf14523f upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by moving posix_acl_update_mode() out of __reiserfs_set_acl() into reiserfs_set_acl(). That way the function will not be called when inheriting ACLs which is what we want as it prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: reiserfs-devel@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/xattr_acl.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 9b1824f35501..91b036902a17 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -37,7 +37,14 @@ reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) error = journal_begin(&th, inode->i_sb, jcreate_blocks); reiserfs_write_unlock(inode->i_sb); if (error == 0) { + if (type == ACL_TYPE_ACCESS && acl) { + error = posix_acl_update_mode(inode, &inode->i_mode, + &acl); + if (error) + goto unlock; + } error = __reiserfs_set_acl(&th, inode, type, acl); +unlock: reiserfs_write_lock(inode->i_sb); error2 = journal_end(&th); reiserfs_write_unlock(inode->i_sb); @@ -245,11 +252,6 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) - return error; - } break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; From ad941c49a40237b77c543469e9e8daee0482a851 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 13 Jun 2017 13:35:51 +0200 Subject: [PATCH 125/427] fs/fcntl: f_setown, avoid undefined behaviour commit fc3dc67471461c0efcb1ed22fb7595121d65fad9 upstream. fcntl(0, F_SETOWN, 0x80000000) triggers: UBSAN: Undefined behaviour in fs/fcntl.c:118:7 negation of -2147483648 cannot be represented in type 'int': CPU: 1 PID: 18261 Comm: syz-executor Not tainted 4.8.1-0-syzkaller #1 ... Call Trace: ... [] ? f_setown+0x1d8/0x200 [] ? SyS_fcntl+0x999/0xf30 [] ? entry_SYSCALL_64_fastpath+0x23/0xc1 Fix that by checking the arg parameter properly (against INT_MAX) before "who = -who". And return immediatelly with -EINVAL in case it is wrong. Note that according to POSIX we can return EINVAL: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html [EINVAL] The cmd argument is F_SETOWN and the value of the argument is not valid as a process or process group identifier. [v2] returns an error, v1 used to fail silently [v3] implement proper check for the bad value INT_MIN Signed-off-by: Jiri Slaby Cc: Jeff Layton Cc: "J. Bruce Fields" Cc: Alexander Viro Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Jeff Layton Signed-off-by: Greg Kroah-Hartman --- fs/fcntl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index 62376451bbce..5df914943d96 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -113,6 +113,10 @@ void f_setown(struct file *filp, unsigned long arg, int force) int who = arg; type = PIDTYPE_PID; if (who < 0) { + /* avoid overflow below */ + if (who == INT_MIN) + return; + type = PIDTYPE_PGID; who = -who; } From 509ed20926aa67aa9933b13f96002dc86b71ca60 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 9 Oct 2017 13:33:19 +0200 Subject: [PATCH 126/427] scsi: libiscsi: fix shifting of DID_REQUEUE host byte commit eef9ffdf9cd39b2986367bc8395e2772bc1284ba upstream. The SCSI host byte should be shifted left by 16 in order to have scsi_decide_disposition() do the right thing (.i.e. requeue the command). Signed-off-by: Johannes Thumshirn Fixes: 661134ad3765 ("[SCSI] libiscsi, bnx2i: make bound ep check common") Cc: Lee Duncan Cc: Hannes Reinecke Cc: Bart Van Assche Cc: Chris Leech Acked-by: Lee Duncan Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libiscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c1ccf1ee99ea..efce04df2109 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1727,7 +1727,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { reason = FAILURE_SESSION_IN_RECOVERY; - sc->result = DID_REQUEUE; + sc->result = DID_REQUEUE << 16; goto fault; } From 5f1dc06152e1683a9277a2836517d6574757dd1f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jan 2018 15:28:17 +0100 Subject: [PATCH 127/427] Revert "module: Add retpoline tag to VERMAGIC" commit 5132ede0fe8092b043dae09a7cc32b8ae7272baa upstream. This reverts commit 6cfb521ac0d5b97470883ff9b7facae264b7ab12. Turns out distros do not want to make retpoline as part of their "ABI", so this patch should not have been merged. Sorry Andi, this was my fault, I suggested it when your original patch was the "correct" way of doing this instead. Reported-by: Jiri Kosina Fixes: 6cfb521ac0d5 ("module: Add retpoline tag to VERMAGIC") Acked-by: Andi Kleen Cc: Thomas Gleixner Cc: David Woodhouse Cc: rusty@rustcorp.com.au Cc: arjan.van.de.ven@intel.com Cc: jeyu@kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/vermagic.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h index a3d04934aa96..6f8fbcf10dfb 100644 --- a/include/linux/vermagic.h +++ b/include/linux/vermagic.h @@ -24,16 +24,10 @@ #ifndef MODULE_ARCH_VERMAGIC #define MODULE_ARCH_VERMAGIC "" #endif -#ifdef RETPOLINE -#define MODULE_VERMAGIC_RETPOLINE "retpoline " -#else -#define MODULE_VERMAGIC_RETPOLINE "" -#endif #define VERMAGIC_STRING \ UTS_RELEASE " " \ MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \ - MODULE_ARCH_VERMAGIC \ - MODULE_VERMAGIC_RETPOLINE + MODULE_ARCH_VERMAGIC From 9af75003499c7a441e5a483220f5d2cf65861e73 Mon Sep 17 00:00:00 2001 From: Aaron Ma Date: Fri, 19 Jan 2018 09:43:39 -0800 Subject: [PATCH 128/427] Input: trackpoint - force 3 buttons if 0 button is reported commit f5d07b9e98022d50720e38aa936fc11c67868ece upstream. Lenovo introduced trackpoint compatible sticks with minimum PS/2 commands. They supposed to reply with 0x02, 0x03, or 0x04 in response to the "Read Extended ID" command, so we would know not to try certain extended commands. Unfortunately even some trackpoints reporting the original IBM version (0x01 firmware 0x0e) now respond with incorrect data to the "Get Extended Buttons" command: thinkpad_acpi: ThinkPad BIOS R0DET87W (1.87 ), EC unknown thinkpad_acpi: Lenovo ThinkPad E470, model 20H1004SGE psmouse serio2: trackpoint: IBM TrackPoint firmware: 0x0e, buttons: 0/0 Since there are no trackpoints without buttons, let's assume the trackpoint has 3 buttons when we get 0 response to the extended buttons query. Signed-off-by: Aaron Ma Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=196253 Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/trackpoint.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 7e2dc5e56632..0b49f29bf0da 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -383,6 +383,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n"); button_info = 0x33; + } else if (!button_info) { + psmouse_warn(psmouse, "got 0 in extended button data, assuming 3 buttons\n"); + button_info = 0x33; } psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); From 18e905a839ed54b135b00e9d9c9dee2ed6908a08 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 2 Feb 2016 17:36:39 +0000 Subject: [PATCH 129/427] usb: usbip: Fix possible deadlocks reported by lockdep commit 21619792d1eca7e772ca190ba68588e57f29595b upstream. Change spin_lock calls to spin_lock_irqsave to prevent attmpted recursive lock taking in interrupt context. This patch fixes Bug 109351 https://bugzilla.kernel.org/show_bug.cgi?id=109351 Signed-off-by: Andrew Goodbody Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_event.c | 5 +- drivers/usb/usbip/vhci_hcd.c | 88 +++++++++++++++++++-------------- drivers/usb/usbip/vhci_rx.c | 30 ++++++----- drivers/usb/usbip/vhci_sysfs.c | 19 ++++--- drivers/usb/usbip/vhci_tx.c | 14 +++--- 5 files changed, 91 insertions(+), 65 deletions(-) diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 64933b993d7a..2580a32bcdff 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add); int usbip_event_happened(struct usbip_device *ud) { int happened = 0; + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); if (ud->event != 0) happened = 1; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); return happened; } diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index f9af04d7f02f..0aaa8e524afd 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status) void rh_port_connect(int rhport, enum usb_device_speed speed) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION); @@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) break; } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } static void rh_port_disconnect(int rhport) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } @@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) int retval; int rhport; int changed = 0; + unsigned long flags; retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8); memset(buf, 0, retval); vhci = hcd_to_vhci(hcd); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { usbip_dbg_vhci_rh("hw accessible flag not on?\n"); goto done; @@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) usb_hcd_resume_root_hub(hcd); done: - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return changed ? retval : 0; } @@ -236,6 +241,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, struct vhci_hcd *dum; int retval = 0; int rhport; + unsigned long flags; u32 prev_port_status[VHCI_NPORTS]; @@ -254,7 +260,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dum = hcd_to_vhci(hcd); - spin_lock(&dum->lock); + spin_lock_irqsave(&dum->lock, flags); /* store old status and compare now and old later */ if (usbip_dbg_flag_vhci_rh) { @@ -408,7 +414,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } usbip_dbg_vhci_rh(" bye\n"); - spin_unlock(&dum->lock); + spin_unlock_irqrestore(&dum->lock, flags); return retval; } @@ -431,6 +437,7 @@ static void vhci_tx_urb(struct urb *urb) { struct vhci_device *vdev = get_vdev(urb->dev); struct vhci_priv *priv; + unsigned long flags; if (!vdev) { pr_err("could not get virtual device"); @@ -443,7 +450,7 @@ static void vhci_tx_urb(struct urb *urb) return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); priv->seqnum = atomic_inc_return(&the_controller->seqnum); if (priv->seqnum == 0xffff) @@ -457,7 +464,7 @@ static void vhci_tx_urb(struct urb *urb) list_add_tail(&priv->list, &vdev->priv_tx); wake_up(&vdev->waitq_tx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); } static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, @@ -466,15 +473,16 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; struct vhci_device *vdev; + unsigned long flags; /* patch to usb_sg_init() is in 2.5.60 */ BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); if (urb->status != -EINPROGRESS) { dev_err(dev, "URB already unlinked!, status %d\n", urb->status); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return urb->status; } @@ -486,7 +494,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, vdev->ud.status == VDEV_ST_ERROR) { dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport); spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -ENODEV; } spin_unlock(&vdev->ud.lock); @@ -559,14 +567,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, out: vhci_tx_urb(urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return 0; no_need_xmit: usb_hcd_unlink_urb_from_ep(hcd, urb); no_need_unlink: - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (!ret) usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -623,14 +631,15 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { struct vhci_priv *priv; struct vhci_device *vdev; + unsigned long flags; - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); priv = urb->hcpriv; if (!priv) { /* URB was never linked! or will be soon given back by * vhci_rx. */ - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EIDRM; } @@ -639,7 +648,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ret = usb_hcd_check_unlink_urb(hcd, urb, status); if (ret) { - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return ret; } } @@ -664,10 +673,10 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) */ usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); } else { /* tcp connection is alive */ @@ -679,7 +688,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); if (!unlink) { spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); return -ENOMEM; } @@ -698,7 +707,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) spin_unlock(&vdev->priv_lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_dbg_vhci_hc("leave\n"); return 0; @@ -707,8 +716,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { @@ -742,19 +752,19 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) list_del(&unlink->list); spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); kfree(unlink); } spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); } /* @@ -821,8 +831,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud) { struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); vdev->speed = 0; vdev->devid = 0; @@ -836,14 +847,16 @@ static void vhci_device_reset(struct usbip_device *ud) } ud->status = VDEV_ST_NULL; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_unusable(struct usbip_device *ud) { - spin_lock(&ud->lock); + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); ud->status = VDEV_ST_ERROR; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_init(struct vhci_device *vdev) @@ -933,12 +946,13 @@ static int vhci_get_frame_number(struct usb_hcd *hcd) static int vhci_bus_suspend(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); hcd->state = HC_STATE_SUSPENDED; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return 0; } @@ -947,15 +961,16 @@ static int vhci_bus_resume(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); int rc = 0; + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) rc = -ESHUTDOWN; else hcd->state = HC_STATE_RUNNING; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return rc; } @@ -1053,17 +1068,18 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) int rhport = 0; int connected = 0; int ret = 0; + unsigned long flags; hcd = platform_get_drvdata(pdev); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); for (rhport = 0; rhport < VHCI_NPORTS; rhport++) if (the_controller->port_status[rhport] & USB_PORT_STAT_CONNECTION) connected += 1; - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (connected > 0) { dev_info(&pdev->dev, diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c index bc4eb0855314..323aa7789989 100644 --- a/drivers/usb/usbip/vhci_rx.c +++ b/drivers/usb/usbip/vhci_rx.c @@ -71,10 +71,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { pr_err("cannot find a urb of seqnum %u max seqnum %d\n", @@ -103,9 +104,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -116,8 +117,9 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, struct usbip_header *pdu) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { pr_info("unlink->seqnum %lu\n", unlink->seqnum); @@ -126,12 +128,12 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, unlink->seqnum); list_del(&unlink->list); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -141,6 +143,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -151,9 +154,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { /* @@ -170,9 +173,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -184,10 +187,11 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, static int vhci_priv_tx_empty(struct vhci_device *vdev) { int empty = 0; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); empty = list_empty(&vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return empty; } diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 84c21c4ccf46..1c7f41a65565 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -32,10 +32,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, { char *s = out; int i = 0; + unsigned long flags; BUG_ON(!the_controller || !out); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); /* * output example: @@ -74,7 +75,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, spin_unlock(&vdev->ud.lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return out - s; } @@ -84,11 +85,12 @@ static DEVICE_ATTR_RO(status); static int vhci_port_disconnect(__u32 rhport) { struct vhci_device *vdev; + unsigned long flags; usbip_dbg_vhci_sysfs("enter\n"); /* lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); @@ -98,14 +100,14 @@ static int vhci_port_disconnect(__u32 rhport) /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EINVAL; } /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); @@ -181,6 +183,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, int sockfd = 0; __u32 rhport = 0, devid = 0, speed = 0; int err; + unsigned long flags; /* * @rhport: port number of vhci_hcd @@ -206,14 +209,14 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, /* now need lock until setting vdev status as used */ /* begin a lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); spin_lock(&vdev->ud.lock); if (vdev->ud.status != VDEV_ST_NULL) { /* end of the lock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); sockfd_put(socket); @@ -232,7 +235,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, vdev->ud.status = VDEV_ST_NOTASSIGNED; spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); /* end the lock */ vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c index 3c5796c8633a..a9a663a578b6 100644 --- a/drivers/usb/usbip/vhci_tx.c +++ b/drivers/usb/usbip/vhci_tx.c @@ -47,16 +47,17 @@ static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) { struct vhci_priv *priv, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return priv; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -137,16 +138,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } From 80e733a9b37fb6b40351bf1924d5a90d89c375ae Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 7 Dec 2017 14:16:47 -0700 Subject: [PATCH 130/427] usbip: fix stub_rx: get_pipe() to validate endpoint number commit 635f545a7e8be7596b9b2b6a43cab6bbd5a88e43 upstream. get_pipe() routine doesn't validate the input endpoint number and uses to reference ep_in and ep_out arrays. Invalid endpoint number can trigger BUG(). Range check the epnum and returning error instead of calling BUG(). Change caller stub_recv_cmd_submit() to handle the get_pipe() error return. Reported-by: Secunia Research Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_rx.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c index 7de54a66044f..e617c90661b4 100644 --- a/drivers/usb/usbip/stub_rx.c +++ b/drivers/usb/usbip/stub_rx.c @@ -344,15 +344,15 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; + if (epnum < 0 || epnum > 15) + goto err_ret; + if (dir == USBIP_DIR_IN) ep = udev->ep_in[epnum & 0x7f]; else ep = udev->ep_out[epnum & 0x7f]; - if (!ep) { - dev_err(&sdev->interface->dev, "no such endpoint?, %d\n", - epnum); - BUG(); - } + if (!ep) + goto err_ret; epd = &ep->desc; if (usb_endpoint_xfer_control(epd)) { @@ -383,9 +383,10 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) return usb_rcvisocpipe(udev, epnum); } +err_ret: /* NOT REACHED */ - dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum); - return 0; + dev_err(&sdev->udev->dev, "get pipe() invalid epnum %d\n", epnum); + return -1; } static void masking_bogus_flags(struct urb *urb) @@ -451,6 +452,9 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, struct usb_device *udev = sdev->udev; int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); + if (pipe == -1) + return; + priv = stub_priv_alloc(sdev, pdu); if (!priv) return; From b6f826ba10dce86f74efd3c0953cb9982a3c51e2 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 7 Dec 2017 14:16:48 -0700 Subject: [PATCH 131/427] usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input commit c6688ef9f29762e65bce325ef4acd6c675806366 upstream. Harden CMD_SUBMIT path to handle malicious input that could trigger large memory allocations. Add checks to validate transfer_buffer_length and number_of_packets to protect against bad input requesting for unbounded memory allocations. Validate early in get_pipe() and return failure. Reported-by: Secunia Research Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_rx.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c index e617c90661b4..56cacb68040c 100644 --- a/drivers/usb/usbip/stub_rx.c +++ b/drivers/usb/usbip/stub_rx.c @@ -338,11 +338,13 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, return priv; } -static int get_pipe(struct stub_device *sdev, int epnum, int dir) +static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu) { struct usb_device *udev = sdev->udev; struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; + int epnum = pdu->base.ep; + int dir = pdu->base.direction; if (epnum < 0 || epnum > 15) goto err_ret; @@ -355,6 +357,7 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) goto err_ret; epd = &ep->desc; + if (usb_endpoint_xfer_control(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, epnum); @@ -377,6 +380,27 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) } if (usb_endpoint_xfer_isoc(epd)) { + /* validate packet size and number of packets */ + unsigned int maxp, packets, bytes; + +#define USB_EP_MAXP_MULT_SHIFT 11 +#define USB_EP_MAXP_MULT_MASK (3 << USB_EP_MAXP_MULT_SHIFT) +#define USB_EP_MAXP_MULT(m) \ + (((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT) + + maxp = usb_endpoint_maxp(epd); + maxp *= (USB_EP_MAXP_MULT( + __le16_to_cpu(epd->wMaxPacketSize)) + 1); + bytes = pdu->u.cmd_submit.transfer_buffer_length; + packets = DIV_ROUND_UP(bytes, maxp); + + if (pdu->u.cmd_submit.number_of_packets < 0 || + pdu->u.cmd_submit.number_of_packets > packets) { + dev_err(&sdev->udev->dev, + "CMD_SUBMIT: isoc invalid num packets %d\n", + pdu->u.cmd_submit.number_of_packets); + return -1; + } if (dir == USBIP_DIR_OUT) return usb_sndisocpipe(udev, epnum); else @@ -385,7 +409,7 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) err_ret: /* NOT REACHED */ - dev_err(&sdev->udev->dev, "get pipe() invalid epnum %d\n", epnum); + dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum); return -1; } @@ -450,7 +474,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, struct stub_priv *priv; struct usbip_device *ud = &sdev->ud; struct usb_device *udev = sdev->udev; - int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); + int pipe = get_pipe(sdev, pdu); if (pipe == -1) return; From 04e7c734e33c53ca2f2b8d027d9f7251f12bb206 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 15 Dec 2017 10:50:09 -0700 Subject: [PATCH 132/427] usbip: prevent leaking socket pointer address in messages commit 90120d15f4c397272aaf41077960a157fc4212bf upstream. usbip driver is leaking socket pointer address in messages. Remove the messages that aren't useful and print sockfd in the ones that are useful for debugging. Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_dev.c | 3 +-- drivers/usb/usbip/usbip_common.c | 15 ++++----------- drivers/usb/usbip/vhci_hcd.c | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index a3ec49bdc1e6..ec38370ffcab 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -163,8 +163,7 @@ static void stub_shutdown_connection(struct usbip_device *ud) * step 1? */ if (ud->tcp_socket) { - dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n", - ud->tcp_socket); + dev_dbg(&sdev->udev->dev, "shutdown sockfd %d\n", ud->sockfd); kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); } diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c index 9752b93f754e..1838f1b2c2fa 100644 --- a/drivers/usb/usbip/usbip_common.c +++ b/drivers/usb/usbip/usbip_common.c @@ -317,18 +317,14 @@ int usbip_recv(struct socket *sock, void *buf, int size) struct msghdr msg; struct kvec iov; int total = 0; - /* for blocks of if (usbip_dbg_flag_xmit) */ char *bp = buf; int osize = size; - usbip_dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf, - size); + if (!sock || !buf || !size) return -EINVAL; - } + + usbip_dbg_xmit("enter\n"); do { sock->sk->sk_allocation = GFP_NOIO; @@ -341,11 +337,8 @@ int usbip_recv(struct socket *sock, void *buf, int size) msg.msg_flags = MSG_NOSIGNAL; result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - if (result <= 0) { - pr_debug("receive sock %p buf %p size %u ret %d total %d\n", - sock, buf, size, result, total); + if (result <= 0) goto err; - } size -= result; buf += result; diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 0aaa8e524afd..00d68945548e 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -778,7 +778,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud) /* need this? see stub_dev.c */ if (ud->tcp_socket) { - pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket); + pr_debug("shutdown sockfd %d\n", ud->sockfd); kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); } From e1e457a49544718928282c56b69af082e1ebe405 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sun, 20 Aug 2017 13:26:04 +0200 Subject: [PATCH 133/427] um: link vmlinux with -no-pie commit 883354afbc109c57f925ccc19840055193da0cc0 upstream. Debian's gcc defaults to pie. The global Makefile already defines the -fno-pie option. Link UML dynamic kernel image also with -no-pie to fix the build. Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger Cc: Bernie Innocenti Signed-off-by: Greg Kroah-Hartman --- arch/um/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index e3abe6f3156d..9ccf462131c4 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -117,7 +117,7 @@ archheaders: archprepare: include/generated/user_constants.h LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static -LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib +LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib $(call cc-option, -no-pie) CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \ $(call cc-option, -fno-stack-protector,) \ From ed73df0b7f23c95b3243a0f4bfc40f962e61d349 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 26 Jan 2018 16:23:02 +0000 Subject: [PATCH 134/427] vsyscall: Fix permissions for emulate mode with KAISER/PTI The backport of KAISER to 4.4 turned vsyscall emulate mode into native mode. Add a vsyscall_pgprot variable to hold the correct page protections, like Borislav and Hugh did for 3.2 and 3.18. Cc: Borislav Petkov Cc: Hugh Dickins Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/vsyscall/vsyscall_64.c | 7 ++++--- arch/x86/include/asm/vsyscall.h | 1 + arch/x86/mm/kaiser.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index 112178b401a1..2d359991a273 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -46,6 +46,7 @@ static enum { EMULATE, NATIVE, NONE } vsyscall_mode = #else EMULATE; #endif +unsigned long vsyscall_pgprot = __PAGE_KERNEL_VSYSCALL; static int __init vsyscall_setup(char *str) { @@ -336,11 +337,11 @@ void __init map_vsyscall(void) extern char __vsyscall_page; unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page); + if (vsyscall_mode != NATIVE) + vsyscall_pgprot = __PAGE_KERNEL_VVAR; if (vsyscall_mode != NONE) __set_fixmap(VSYSCALL_PAGE, physaddr_vsyscall, - vsyscall_mode == NATIVE - ? PAGE_KERNEL_VSYSCALL - : PAGE_KERNEL_VVAR); + __pgprot(vsyscall_pgprot)); BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) != (unsigned long)VSYSCALL_ADDR); diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h index 4865e10dbb55..9ee85066f407 100644 --- a/arch/x86/include/asm/vsyscall.h +++ b/arch/x86/include/asm/vsyscall.h @@ -13,6 +13,7 @@ extern void map_vsyscall(void); */ extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address); extern bool vsyscall_enabled(void); +extern unsigned long vsyscall_pgprot; #else static inline void map_vsyscall(void) {} static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) diff --git a/arch/x86/mm/kaiser.c b/arch/x86/mm/kaiser.c index 8af98513d36c..2298434f7bdb 100644 --- a/arch/x86/mm/kaiser.c +++ b/arch/x86/mm/kaiser.c @@ -345,7 +345,7 @@ void __init kaiser_init(void) if (vsyscall_enabled()) kaiser_add_user_map_early((void *)VSYSCALL_ADDR, PAGE_SIZE, - __PAGE_KERNEL_VSYSCALL); + vsyscall_pgprot); for_each_possible_cpu(cpu) { void *percpu_vaddr = __per_cpu_user_mapped_start + From 506ff217e470bdaa78477406a051c0570403307d Mon Sep 17 00:00:00 2001 From: Greg KH Date: Wed, 8 Mar 2017 19:03:44 +0100 Subject: [PATCH 135/427] eventpoll.h: add missing epoll event masks commit 7e040726850a106587485c21bdacc0bfc8a0cbed upstream. [resend due to me forgetting to cc: linux-api the first time around I posted these back on Feb 23] From: Greg Kroah-Hartman For some reason these values are not in the uapi header file, so any libc has to define it themselves. To prevent them from needing to do this, just have the kernel provide the correct values. Reported-by: Elliott Hughes Signed-off-by: Greg Hackmann Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/eventpoll.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h index bc81fb2e1f0e..6f04cb419115 100644 --- a/include/uapi/linux/eventpoll.h +++ b/include/uapi/linux/eventpoll.h @@ -26,6 +26,19 @@ #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 +/* Epoll event masks */ +#define EPOLLIN 0x00000001 +#define EPOLLPRI 0x00000002 +#define EPOLLOUT 0x00000004 +#define EPOLLERR 0x00000008 +#define EPOLLHUP 0x00000010 +#define EPOLLRDNORM 0x00000040 +#define EPOLLRDBAND 0x00000080 +#define EPOLLWRNORM 0x00000100 +#define EPOLLWRBAND 0x00000200 +#define EPOLLMSG 0x00000400 +#define EPOLLRDHUP 0x00002000 + /* * Request the handling of system wakeup events so as to prevent system suspends * from happening while those events are being processed. From 20c0a04284496b262b172707b7dd122cdd8fe9a1 Mon Sep 17 00:00:00 2001 From: Jia Zhang Date: Tue, 23 Jan 2018 11:41:32 +0100 Subject: [PATCH 136/427] x86/microcode/intel: Extend BDW late-loading further with LLC size check commit 7e702d17ed138cf4ae7c00e8c00681ed464587c7 upstream. Commit b94b73733171 ("x86/microcode/intel: Extend BDW late-loading with a revision check") reduced the impact of erratum BDF90 for Broadwell model 79. The impact can be reduced further by checking the size of the last level cache portion per core. Tony: "The erratum says the problem only occurs on the large-cache SKUs. So we only need to avoid the update if we are on a big cache SKU that is also running old microcode." For more details, see erratum BDF90 in document #334165 (Intel Xeon Processor E7-8800/4800 v4 Product Family Specification Update) from September 2017. Fixes: b94b73733171 ("x86/microcode/intel: Extend BDW late-loading with a revision check") Signed-off-by: Jia Zhang Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Acked-by: Tony Luck Link: https://lkml.kernel.org/r/1516321542-31161-1-git-send-email-zhang.jia@linux.alibaba.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/microcode/intel.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index ee011bd7934d..2c76a1801393 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -39,6 +39,9 @@ #include #include +/* last level cache size per core */ +static int llc_size_per_core; + static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; static struct mc_saved_data { unsigned int mc_saved_count; @@ -996,12 +999,14 @@ static bool is_blacklisted(unsigned int cpu) /* * Late loading on model 79 with microcode revision less than 0x0b000021 - * may result in a system hang. This behavior is documented in item - * BDF90, #334165 (Intel Xeon Processor E7-8800/4800 v4 Product Family). + * and LLC size per core bigger than 2.5MB may result in a system hang. + * This behavior is documented in item BDF90, #334165 (Intel Xeon + * Processor E7-8800/4800 v4 Product Family). */ if (c->x86 == 6 && c->x86_model == 79 && c->x86_mask == 0x01 && + llc_size_per_core > 2621440 && c->microcode < 0x0b000021) { pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); @@ -1068,6 +1073,15 @@ static struct microcode_ops microcode_intel_ops = { .microcode_fini_cpu = microcode_fini_cpu, }; +static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c) +{ + u64 llc_size = c->x86_cache_size * 1024; + + do_div(llc_size, c->x86_max_cores); + + return (int)llc_size; +} + struct microcode_ops * __init init_intel_microcode(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -1078,6 +1092,8 @@ struct microcode_ops * __init init_intel_microcode(void) return NULL; } + llc_size_per_core = calc_llc_size_per_core(c); + return µcode_intel_ops; } From 360496cab53af2f1dd77dbe353b7b665bcfdc1e3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jan 2018 14:54:32 +0100 Subject: [PATCH 137/427] hrtimer: Reset hrtimer cpu base proper on CPU hotplug commit d5421ea43d30701e03cadc56a38854c36a8b4433 upstream. The hrtimer interrupt code contains a hang detection and mitigation mechanism, which prevents that a long delayed hrtimer interrupt causes a continous retriggering of interrupts which prevent the system from making progress. If a hang is detected then the timer hardware is programmed with a certain delay into the future and a flag is set in the hrtimer cpu base which prevents newly enqueued timers from reprogramming the timer hardware prior to the chosen delay. The subsequent hrtimer interrupt after the delay clears the flag and resumes normal operation. If such a hang happens in the last hrtimer interrupt before a CPU is unplugged then the hang_detected flag is set and stays that way when the CPU is plugged in again. At that point the timer hardware is not armed and it cannot be armed because the hang_detected flag is still active, so nothing clears that flag. As a consequence the CPU does not receive hrtimer interrupts and no timers expire on that CPU which results in RCU stalls and other malfunctions. Clear the flag along with some other less critical members of the hrtimer cpu base to ensure starting from a clean state when a CPU is plugged in. Thanks to Paul, Sebastian and Anna-Maria for their help to get down to the root cause of that hard to reproduce heisenbug. Once understood it's trivial and certainly justifies a brown paperbag. Fixes: 41d2e4949377 ("hrtimer: Tune hrtimer_interrupt hang logic") Reported-by: Paul E. McKenney Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Sebastian Sewior Cc: Anna-Maria Gleixner Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1801261447590.2067@nanos Signed-off-by: Greg Kroah-Hartman --- kernel/time/hrtimer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 1dc94768b5a3..323282e63865 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -669,7 +669,9 @@ static void hrtimer_reprogram(struct hrtimer *timer, static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { base->expires_next.tv64 = KTIME_MAX; + base->hang_detected = 0; base->hres_active = 0; + base->next_timer = NULL; } /* @@ -1615,6 +1617,7 @@ static void init_hrtimers_cpu(int cpu) timerqueue_init_head(&cpu_base->clock_base[i].active); } + cpu_base->active_bases = 0; cpu_base->cpu = cpu; hrtimer_init_hres(cpu_base); } From e91e5b700fb6f887d4df4a18de0d8865df43d77d Mon Sep 17 00:00:00 2001 From: Alexey Kodanev Date: Fri, 26 Jan 2018 15:14:16 +0300 Subject: [PATCH 138/427] dccp: don't restart ccid2_hc_tx_rto_expire() if sk in closed state [ Upstream commit dd5684ecae3bd8e44b644f50e2c12c7e57fdfef5 ] ccid2_hc_tx_rto_expire() timer callback always restarts the timer again and can run indefinitely (unless it is stopped outside), and after commit 120e9dabaf55 ("dccp: defer ccid_hc_tx_delete() at dismantle time"), which moved ccid_hc_tx_delete() (also includes sk_stop_timer()) from dccp_destroy_sock() to sk_destruct(), this started to happen quite often. The timer prevents releasing the socket, as a result, sk_destruct() won't be called. Found with LTP/dccp_ipsec tests running on the bonding device, which later couldn't be unloaded after the tests were completed: unregister_netdevice: waiting for bond0 to become free. Usage count = 148 Fixes: 2a91aa396739 ("[DCCP] CCID2: Initial CCID2 (TCP-Like) implementation") Signed-off-by: Alexey Kodanev Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/dccp/ccids/ccid2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 5e3a7302f774..7753681195c1 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -140,6 +140,9 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) ccid2_pr_debug("RTO_EXPIRE\n"); + if (sk->sk_state == DCCP_CLOSED) + goto out; + /* back-off timer */ hc->tx_rto <<= 1; if (hc->tx_rto > DCCP_RTO_MAX) From c5371a321a4a3c1f181f4482b3b3ceae06b72879 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 22 Jan 2018 20:06:42 +0000 Subject: [PATCH 139/427] ipv6: Fix getsockopt() for sockets with default IPV6_AUTOFLOWLABEL [ Upstream commit e9191ffb65d8e159680ce0ad2224e1acbde6985c ] Commit 513674b5a2c9 ("net: reevalulate autoflowlabel setting after sysctl setting") removed the initialisation of ipv6_pinfo::autoflowlabel and added a second flag to indicate whether this field or the net namespace default should be used. The getsockopt() handling for this case was not updated, so it currently returns 0 for all sockets for which IPV6_AUTOFLOWLABEL is not explicitly enabled. Fix it to return the effective value, whether that has been set at the socket or net namespace level. Fixes: 513674b5a2c9 ("net: reevalulate autoflowlabel setting after sysctl ...") Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ipv6.h | 1 + net/ipv6/ip6_output.c | 2 +- net/ipv6/ipv6_sockglue.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 7a8066b90289..84f0d0602433 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -281,6 +281,7 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, int flags); int ip6_flowlabel_init(void); void ip6_flowlabel_cleanup(void); +bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np); static inline void fl6_sock_release(struct ip6_flowlabel *fl) { diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index b809958f7388..d82b814e6c27 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -148,7 +148,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) !(IP6CB(skb)->flags & IP6SKB_REROUTED)); } -static bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np) +bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np) { if (!np->autoflowlabel_set) return ip6_default_np_autolabel(net); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 435e26210587..9011176c8387 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -1313,7 +1313,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, break; case IPV6_AUTOFLOWLABEL: - val = np->autoflowlabel; + val = ip6_autoflowlabel(sock_net(sk), np); break; default: From c867a05df5d1baefbb2040474356b5e02ca5fcaf Mon Sep 17 00:00:00 2001 From: Mike Maloney Date: Wed, 10 Jan 2018 12:45:10 -0500 Subject: [PATCH 140/427] ipv6: fix udpv6 sendmsg crash caused by too small MTU [ Upstream commit 749439bfac6e1a2932c582e2699f91d329658196 ] The logic in __ip6_append_data() assumes that the MTU is at least large enough for the headers. A device's MTU may be adjusted after being added while sendmsg() is processing data, resulting in __ip6_append_data() seeing any MTU. For an mtu smaller than the size of the fragmentation header, the math results in a negative 'maxfraglen', which causes problems when refragmenting any previous skb in the skb_write_queue, leaving it possibly malformed. Instead sendmsg returns EINVAL when the mtu is calculated to be less than IPV6_MIN_MTU. Found by syzkaller: kernel BUG at ./include/linux/skbuff.h:2064! invalid opcode: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 1 PID: 14216 Comm: syz-executor5 Not tainted 4.13.0-rc4+ #2 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 task: ffff8801d0b68580 task.stack: ffff8801ac6b8000 RIP: 0010:__skb_pull include/linux/skbuff.h:2064 [inline] RIP: 0010:__ip6_make_skb+0x18cf/0x1f70 net/ipv6/ip6_output.c:1617 RSP: 0018:ffff8801ac6bf570 EFLAGS: 00010216 RAX: 0000000000010000 RBX: 0000000000000028 RCX: ffffc90003cce000 RDX: 00000000000001b8 RSI: ffffffff839df06f RDI: ffff8801d9478ca0 RBP: ffff8801ac6bf780 R08: ffff8801cc3f1dbc R09: 0000000000000000 R10: ffff8801ac6bf7a0 R11: 43cb4b7b1948a9e7 R12: ffff8801cc3f1dc8 R13: ffff8801cc3f1d40 R14: 0000000000001036 R15: dffffc0000000000 FS: 00007f43d740c700(0000) GS:ffff8801dc100000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f7834984000 CR3: 00000001d79b9000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ip6_finish_skb include/net/ipv6.h:911 [inline] udp_v6_push_pending_frames+0x255/0x390 net/ipv6/udp.c:1093 udpv6_sendmsg+0x280d/0x31a0 net/ipv6/udp.c:1363 inet_sendmsg+0x11f/0x5e0 net/ipv4/af_inet.c:762 sock_sendmsg_nosec net/socket.c:633 [inline] sock_sendmsg+0xca/0x110 net/socket.c:643 SYSC_sendto+0x352/0x5a0 net/socket.c:1750 SyS_sendto+0x40/0x50 net/socket.c:1718 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x4512e9 RSP: 002b:00007f43d740bc08 EFLAGS: 00000216 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 00000000007180a8 RCX: 00000000004512e9 RDX: 000000000000002e RSI: 0000000020d08000 RDI: 0000000000000005 RBP: 0000000000000086 R08: 00000000209c1000 R09: 000000000000001c R10: 0000000000040800 R11: 0000000000000216 R12: 00000000004b9c69 R13: 00000000ffffffff R14: 0000000000000005 R15: 00000000202c2000 Code: 9e 01 fe e9 c5 e8 ff ff e8 7f 9e 01 fe e9 4a ea ff ff 48 89 f7 e8 52 9e 01 fe e9 aa eb ff ff e8 a8 b6 cf fd 0f 0b e8 a1 b6 cf fd <0f> 0b 49 8d 45 78 4d 8d 45 7c 48 89 85 78 fe ff ff 49 8d 85 ba RIP: __skb_pull include/linux/skbuff.h:2064 [inline] RSP: ffff8801ac6bf570 RIP: __ip6_make_skb+0x18cf/0x1f70 net/ipv6/ip6_output.c:1617 RSP: ffff8801ac6bf570 Reported-by: syzbot Signed-off-by: Mike Maloney Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d82b814e6c27..dfd4a9a02dc3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1246,14 +1246,16 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, v6_cork->tclass = tclass; if (rt->dst.flags & DST_XFRM_TUNNEL) mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(&rt->dst); + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); else mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(rt->dst.path); + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(rt->dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; } + if (mtu < IPV6_MIN_MTU) + return -EINVAL; cork->base.fragsize = mtu; if (dst_allfrag(rt->dst.path)) cork->base.flags |= IPCORK_ALLFRAG; From f64568e420e6b9b523611ef564941b83c7527614 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 11 Jan 2018 22:31:18 -0800 Subject: [PATCH 141/427] ipv6: ip6_make_skb() needs to clear cork.base.dst [ Upstream commit 95ef498d977bf44ac094778fd448b98af158a3e6 ] In my last patch, I missed fact that cork.base.dst was not initialized in ip6_make_skb() : If ip6_setup_cork() returns an error, we might attempt a dst_release() on some random pointer. Fixes: 862c03ee1deb ("ipv6: fix possible mem leaks in ipv6_make_skb()") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index dfd4a9a02dc3..3ef81c387923 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1785,6 +1785,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk, cork.base.flags = 0; cork.base.addr = 0; cork.base.opt = NULL; + cork.base.dst = NULL; v6_cork.opt = NULL; err = ip6_setup_cork(sk, &cork, &v6_cork, hlimit, tclass, opt, rt, fl6); if (err) { From 1202fc020465b67297f84dfc7127b83805082c69 Mon Sep 17 00:00:00 2001 From: Yuiko Oshino Date: Mon, 15 Jan 2018 13:24:28 -0500 Subject: [PATCH 142/427] lan78xx: Fix failure in USB Full Speed [ Upstream commit a5b1379afbfabf91e3a689e82ac619a7157336b3 ] Fix initialize the uninitialized tx_qlen to an appropriate value when USB Full Speed is used. Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") Signed-off-by: Yuiko Oshino Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/lan78xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 41e9ebd7d0a6..ebdee8f01f65 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1859,6 +1859,7 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf = DEFAULT_BURST_CAP_SIZE / FS_USB_PKT_SIZE; dev->rx_urb_size = DEFAULT_BURST_CAP_SIZE; dev->rx_qlen = 4; + dev->tx_qlen = 4; } ret = lan78xx_write_reg(dev, BURST_CAP, buf); From 6c489ab43ccacb9f26620ded90374c582c466344 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 19 Jan 2018 11:50:46 +0100 Subject: [PATCH 143/427] net: igmp: fix source address check for IGMPv3 reports [ Upstream commit ad23b750933ea7bf962678972a286c78a8fa36aa ] Commit "net: igmp: Use correct source address on IGMPv3 reports" introduced a check to validate the source address of locally generated IGMPv3 packets. Instead of checking the local interface address directly, it uses inet_ifa_match(fl4->saddr, ifa), which checks if the address is on the local subnet (or equal to the point-to-point address if used). This breaks for point-to-point interfaces, so check against ifa->ifa_local directly. Cc: Kevin Cernekee Fixes: a46182b00290 ("net: igmp: Use correct source address on IGMPv3 reports") Reported-by: Sebastian Gottschall Signed-off-by: Felix Fietkau Signed-off-by: David S. Miller Tested-by: Florian Wolters Signed-off-by: Greg Kroah-Hartman --- net/ipv4/igmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index b60106d34346..8212ed80da48 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -338,7 +338,7 @@ static __be32 igmpv3_get_srcaddr(struct net_device *dev, return htonl(INADDR_ANY); for_ifa(in_dev) { - if (inet_ifa_match(fl4->saddr, ifa)) + if (fl4->saddr == ifa->ifa_local) return fl4->saddr; } endfor_ifa(in_dev); From bed42ef5ebbfc046e0440f7e0f941cc07f8ca1e8 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:37 -0500 Subject: [PATCH 144/427] tcp: __tcp_hdrlen() helper commit d9b3fca27385eafe61c3ca6feab6cb1e7dc77482 upstream. tcp_hdrlen is wasteful if you already have a pointer to struct tcphdr. This splits the size calculation into a helper function that can be used if a struct tcphdr is already available. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/tcp.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 318c24612458..2260f92f1492 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -29,9 +29,14 @@ static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) return (struct tcphdr *)skb_transport_header(skb); } +static inline unsigned int __tcp_hdrlen(const struct tcphdr *th) +{ + return th->doff * 4; +} + static inline unsigned int tcp_hdrlen(const struct sk_buff *skb) { - return tcp_hdr(skb)->doff * 4; + return __tcp_hdrlen(tcp_hdr(skb)); } static inline struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb) From f50fc5f4f3e5f0d2b55cd09c01f3a09d0ddeb9dc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Jan 2018 19:59:19 -0800 Subject: [PATCH 145/427] net: qdisc_pkt_len_init() should be more robust [ Upstream commit 7c68d1a6b4db9012790af7ac0f0fdc0d2083422a ] Without proper validation of DODGY packets, we might very well feed qdisc_pkt_len_init() with invalid GSO packets. tcp_hdrlen() might access out-of-bound data, so let's use skb_header_pointer() and proper checks. Whole story is described in commit d0c081b49137 ("flow_dissector: properly cap thoff field") We have the goal of validating DODGY packets earlier in the stack, so we might very well revert this fix in the future. Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Jason Wang Reported-by: syzbot+9da69ebac7dddd804552@syzkaller.appspotmail.com Acked-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 3b67c1e5756f..cb58ba15d51e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2889,10 +2889,21 @@ static void qdisc_pkt_len_init(struct sk_buff *skb) hdr_len = skb_transport_header(skb) - skb_mac_header(skb); /* + transport layer */ - if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) - hdr_len += tcp_hdrlen(skb); - else - hdr_len += sizeof(struct udphdr); + if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { + const struct tcphdr *th; + struct tcphdr _tcphdr; + + th = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_tcphdr), &_tcphdr); + if (likely(th)) + hdr_len += __tcp_hdrlen(th); + } else { + struct udphdr _udphdr; + + if (skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_udphdr), &_udphdr)) + hdr_len += sizeof(struct udphdr); + } if (shinfo->gso_type & SKB_GSO_DODGY) gso_segs = DIV_ROUND_UP(skb->len - hdr_len, From a49558ebc2c4ce129a381d7cf39c4f01ea02c78b Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Mon, 22 Jan 2018 18:06:37 +0100 Subject: [PATCH 146/427] pppoe: take ->needed_headroom of lower device into account on xmit [ Upstream commit 02612bb05e51df8489db5e94d0cf8d1c81f87b0c ] In pppoe_sendmsg(), reserving dev->hard_header_len bytes of headroom was probably fine before the introduction of ->needed_headroom in commit f5184d267c1a ("net: Allow netdevices to specify needed head/tailroom"). But now, virtual devices typically advertise the size of their overhead in dev->needed_headroom, so we must also take it into account in skb_reserve(). Allocation size of skb is also updated to take dev->needed_tailroom into account and replace the arbitrary 32 bytes with the real size of a PPPoE header. This issue was discovered by syzbot, who connected a pppoe socket to a gre device which had dev->header_ops->create == ipgre_header and dev->hard_header_len == 0. Therefore, PPPoE didn't reserve any headroom, and dev_hard_header() crashed when ipgre_header() tried to prepend its header to skb->data. skbuff: skb_under_panic: text:000000001d390b3a len:31 put:24 head:00000000d8ed776f data:000000008150e823 tail:0x7 end:0xc0 dev:gre0 ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:104! invalid opcode: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 1 PID: 3670 Comm: syzkaller801466 Not tainted 4.15.0-rc7-next-20180115+ #97 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:skb_panic+0x162/0x1f0 net/core/skbuff.c:100 RSP: 0018:ffff8801d9bd7840 EFLAGS: 00010282 RAX: 0000000000000083 RBX: ffff8801d4f083c0 RCX: 0000000000000000 RDX: 0000000000000083 RSI: 1ffff1003b37ae92 RDI: ffffed003b37aefc RBP: ffff8801d9bd78a8 R08: 1ffff1003b37ae8a R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: ffffffff86200de0 R13: ffffffff84a981ad R14: 0000000000000018 R15: ffff8801d2d34180 FS: 00000000019c4880(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000208bc000 CR3: 00000001d9111001 CR4: 00000000001606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: skb_under_panic net/core/skbuff.c:114 [inline] skb_push+0xce/0xf0 net/core/skbuff.c:1714 ipgre_header+0x6d/0x4e0 net/ipv4/ip_gre.c:879 dev_hard_header include/linux/netdevice.h:2723 [inline] pppoe_sendmsg+0x58e/0x8b0 drivers/net/ppp/pppoe.c:890 sock_sendmsg_nosec net/socket.c:630 [inline] sock_sendmsg+0xca/0x110 net/socket.c:640 sock_write_iter+0x31a/0x5d0 net/socket.c:909 call_write_iter include/linux/fs.h:1775 [inline] do_iter_readv_writev+0x525/0x7f0 fs/read_write.c:653 do_iter_write+0x154/0x540 fs/read_write.c:932 vfs_writev+0x18a/0x340 fs/read_write.c:977 do_writev+0xfc/0x2a0 fs/read_write.c:1012 SYSC_writev fs/read_write.c:1085 [inline] SyS_writev+0x27/0x30 fs/read_write.c:1082 entry_SYSCALL_64_fastpath+0x29/0xa0 Admittedly PPPoE shouldn't be allowed to run on non Ethernet-like interfaces, but reserving space for ->needed_headroom is a more fundamental issue that needs to be addressed first. Same problem exists for __pppoe_xmit(), which also needs to take dev->needed_headroom into account in skb_cow_head(). Fixes: f5184d267c1a ("net: Allow netdevices to specify needed head/tailroom") Reported-by: syzbot+ed0838d0fa4c4f2b528e20286e6dc63effc7c14d@syzkaller.appspotmail.com Signed-off-by: Guillaume Nault Reviewed-by: Xin Long Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ppp/pppoe.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 4e0068e775f9..b7b859c3a0c7 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -860,6 +860,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m, struct pppoe_hdr *ph; struct net_device *dev; char *start; + int hlen; lock_sock(sk); if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) { @@ -878,16 +879,16 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m, if (total_len > (dev->mtu + dev->hard_header_len)) goto end; - - skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, - 0, GFP_KERNEL); + hlen = LL_RESERVED_SPACE(dev); + skb = sock_wmalloc(sk, hlen + sizeof(*ph) + total_len + + dev->needed_tailroom, 0, GFP_KERNEL); if (!skb) { error = -ENOMEM; goto end; } /* Reserve space for headers. */ - skb_reserve(skb, dev->hard_header_len); + skb_reserve(skb, hlen); skb_reset_network_header(skb); skb->dev = dev; @@ -948,7 +949,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) /* Copy the data if there is no space for the header or if it's * read-only. */ - if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) + if (skb_cow_head(skb, LL_RESERVED_SPACE(dev) + sizeof(*ph))) goto abort; __skb_push(skb, sizeof(*ph)); From d6611191f5a18d03314ab4a1b621d1892116af79 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 26 Jan 2018 01:53:26 +0100 Subject: [PATCH 147/427] r8169: fix memory corruption on retrieval of hardware statistics. [ Upstream commit a78e93661c5fd30b9e1dee464b2f62f966883ef7 ] Hardware statistics retrieval hurts in tight invocation loops. Avoid extraneous write and enforce strict ordering of writes targeted to the tally counters dump area address registers. Signed-off-by: Francois Romieu Tested-by: Oliver Freyermuth Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index c5ea1018cb47..24155380e43c 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -2205,19 +2205,14 @@ static bool rtl8169_do_counters(struct net_device *dev, u32 counter_cmd) void __iomem *ioaddr = tp->mmio_addr; dma_addr_t paddr = tp->counters_phys_addr; u32 cmd; - bool ret; RTL_W32(CounterAddrHigh, (u64)paddr >> 32); + RTL_R32(CounterAddrHigh); cmd = (u64)paddr & DMA_BIT_MASK(32); RTL_W32(CounterAddrLow, cmd); RTL_W32(CounterAddrLow, cmd | counter_cmd); - ret = rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - return ret; + return rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); } static bool rtl8169_reset_counters(struct net_device *dev) From 23f521bc70b935156e13897db2873312b18b0437 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Mon, 15 Jan 2018 17:02:00 +0800 Subject: [PATCH 148/427] sctp: do not allow the v4 socket to bind a v4mapped v6 address [ Upstream commit c5006b8aa74599ce19104b31d322d2ea9ff887cc ] The check in sctp_sockaddr_af is not robust enough to forbid binding a v4mapped v6 addr on a v4 socket. The worse thing is that v4 socket's bind_verify would not convert this v4mapped v6 addr to a v4 addr. syzbot even reported a crash as the v4 socket bound a v6 addr. This patch is to fix it by doing the common sa.sa_family check first, then AF_INET check for v4mapped v6 addrs. Fixes: 7dab83de50c7 ("sctp: Support ipv6only AF_INET6 sockets.") Reported-by: syzbot+7b7b518b1228d2743963@syzkaller.appspotmail.com Acked-by: Neil Horman Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/socket.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a870d27ca778..acf487283e9f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -332,16 +332,14 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, if (len < sizeof (struct sockaddr)) return NULL; + if (!opt->pf->af_supported(addr->sa.sa_family, opt)) + return NULL; + /* V4 mapped address are really of AF_INET family */ if (addr->sa.sa_family == AF_INET6 && - ipv6_addr_v4mapped(&addr->v6.sin6_addr)) { - if (!opt->pf->af_supported(AF_INET, opt)) - return NULL; - } else { - /* Does this PF support this AF? */ - if (!opt->pf->af_supported(addr->sa.sa_family, opt)) - return NULL; - } + ipv6_addr_v4mapped(&addr->v6.sin6_addr) && + !opt->pf->af_supported(AF_INET, opt)) + return NULL; /* If we get this far, af is valid. */ af = sctp_get_af_specific(addr->sa.sa_family); From 50194c3f48de2c2374731d4b6b7f3fbb89250094 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Mon, 15 Jan 2018 17:01:36 +0800 Subject: [PATCH 149/427] sctp: return error if the asoc has been peeled off in sctp_wait_for_sndbuf [ Upstream commit a0ff660058b88d12625a783ce9e5c1371c87951f ] After commit cea0cc80a677 ("sctp: use the right sk after waking up from wait_buf sleep"), it may change to lock another sk if the asoc has been peeled off in sctp_wait_for_sndbuf. However, the asoc's new sk could be already closed elsewhere, as it's in the sendmsg context of the old sk that can't avoid the new sk's closing. If the sk's last one refcnt is held by this asoc, later on after putting this asoc, the new sk will be freed, while under it's own lock. This patch is to revert that commit, but fix the old issue by returning error under the old sk's lock. Fixes: cea0cc80a677 ("sctp: use the right sk after waking up from wait_buf sleep") Reported-by: syzbot+ac6ea7baa4432811eb50@syzkaller.appspotmail.com Signed-off-by: Xin Long Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/socket.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index acf487283e9f..e9851198a850 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -83,7 +83,7 @@ static int sctp_writeable(struct sock *sk); static void sctp_wfree(struct sk_buff *skb); static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len, struct sock **orig_sk); + size_t msg_len); static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); @@ -1952,7 +1952,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); if (!sctp_wspace(asoc)) { /* sk can be changed by peel off when waiting for buf. */ - err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len, &sk); + err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); if (err) { if (err == -ESRCH) { /* asoc is already dead. */ @@ -6974,12 +6974,12 @@ void sctp_sock_rfree(struct sk_buff *skb) /* Helper function to wait for space in the sndbuf. */ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len, struct sock **orig_sk) + size_t msg_len) { struct sock *sk = asoc->base.sk; - int err = 0; long current_timeo = *timeo_p; DEFINE_WAIT(wait); + int err = 0; pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc, *timeo_p, msg_len); @@ -7008,17 +7008,13 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, release_sock(sk); current_timeo = schedule_timeout(current_timeo); lock_sock(sk); - if (sk != asoc->base.sk) { - release_sock(sk); - sk = asoc->base.sk; - lock_sock(sk); - } + if (sk != asoc->base.sk) + goto do_error; *timeo_p = current_timeo; } out: - *orig_sk = sk; finish_wait(&asoc->wait, &wait); /* Release the association's refcnt. */ From 0d9bcadb2226150776c5bf84ef6eb5df03e32b03 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 22 Jan 2018 16:06:37 -0500 Subject: [PATCH 150/427] vmxnet3: repair memory leak [ Upstream commit 848b159835ddef99cc4193083f7e786c3992f580 ] with the introduction of commit b0eb57cb97e7837ebb746404c2c58c6f536f23fa, it appears that rq->buf_info is improperly handled. While it is heap allocated when an rx queue is setup, and freed when torn down, an old line of code in vmxnet3_rq_destroy was not properly removed, leading to rq->buf_info[0] being set to NULL prior to its being freed, causing a memory leak, which eventually exhausts the system on repeated create/destroy operations (for example, when the mtu of a vmxnet3 interface is changed frequently. Fix is pretty straight forward, just move the NULL set to after the free. Tested by myself with successful results Applies to net, and should likely be queued for stable, please Signed-off-by: Neil Horman Reported-By: boyang@redhat.com CC: boyang@redhat.com CC: Shrikrishna Khare CC: "VMware, Inc." CC: David S. Miller Acked-by: Shrikrishna Khare Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 0cbf520cea77..82bf85ae5d08 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1563,7 +1563,6 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, rq->rx_ring[i].basePA); rq->rx_ring[i].base = NULL; } - rq->buf_info[i] = NULL; } if (rq->comp_ring.base) { @@ -1578,6 +1577,7 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, (rq->rx_ring[0].size + rq->rx_ring[1].size); dma_free_coherent(&adapter->pdev->dev, sz, rq->buf_info[0], rq->buf_info_pa); + rq->buf_info[0] = rq->buf_info[1] = NULL; } } From 29837a4a8764c1b73674eb78c99717cbc73aa9f3 Mon Sep 17 00:00:00 2001 From: Jim Westfall Date: Sun, 14 Jan 2018 04:18:50 -0800 Subject: [PATCH 151/427] net: Allow neigh contructor functions ability to modify the primary_key [ Upstream commit 096b9854c04df86f03b38a97d40b6506e5730919 ] Use n->primary_key instead of pkey to account for the possibility that a neigh constructor function may have modified the primary_key value. Signed-off-by: Jim Westfall Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/neighbour.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index ae92131c4f89..253c86b78ff0 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -496,7 +496,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, if (atomic_read(&tbl->entries) > (1 << nht->hash_shift)) nht = neigh_hash_grow(tbl, nht->hash_shift + 1); - hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); + hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift); if (n->parms->dead) { rc = ERR_PTR(-EINVAL); @@ -508,7 +508,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, n1 != NULL; n1 = rcu_dereference_protected(n1->next, lockdep_is_held(&tbl->lock))) { - if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) { + if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) { if (want_ref) neigh_hold(n1); rc = n1; From cab8451486a6fd9ba4ce798d41352f45abb44fae Mon Sep 17 00:00:00 2001 From: Jim Westfall Date: Sun, 14 Jan 2018 04:18:51 -0800 Subject: [PATCH 152/427] ipv4: Make neigh lookup keys for loopback/point-to-point devices be INADDR_ANY [ Upstream commit cd9ff4de0107c65d69d02253bb25d6db93c3dbc1 ] Map all lookup neigh keys to INADDR_ANY for loopback/point-to-point devices to avoid making an entry for every remote ip the device needs to talk to. This used the be the old behavior but became broken in a263b3093641f (ipv4: Make neigh lookups directly in output packet path) and later removed in 0bb4087cbec0 (ipv4: Fix neigh lookup keying over loopback/point-to-point devices) because it was broken. Signed-off-by: Jim Westfall Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/arp.h | 3 +++ net/ipv4/arp.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/net/arp.h b/include/net/arp.h index 5e0f891d476c..1b3f86981757 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -19,6 +19,9 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32 static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) { + if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) + key = INADDR_ANY; + return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev); } diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 711b4dfa17c3..cb5eb649ad5f 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -223,11 +223,16 @@ static bool arp_key_eq(const struct neighbour *neigh, const void *pkey) static int arp_constructor(struct neighbour *neigh) { - __be32 addr = *(__be32 *)neigh->primary_key; + __be32 addr; struct net_device *dev = neigh->dev; struct in_device *in_dev; struct neigh_parms *parms; + u32 inaddr_any = INADDR_ANY; + if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) + memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len); + + addr = *(__be32 *)neigh->primary_key; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { From d35cd5e279881ec36ff8cd82a2d9caebc0cce3fc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 17 Jan 2018 14:21:13 -0800 Subject: [PATCH 153/427] flow_dissector: properly cap thoff field [ Upstream commit d0c081b49137cd3200f2023c0875723be66e7ce5 ] syzbot reported yet another crash [1] that is caused by insufficient validation of DODGY packets. Two bugs are happening here to trigger the crash. 1) Flow dissection leaves with incorrect thoff field. 2) skb_probe_transport_header() sets transport header to this invalid thoff, even if pointing after skb valid data. 3) qdisc_pkt_len_init() reads out-of-bound data because it trusts tcp_hdrlen(skb) Possible fixes : - Full flow dissector validation before injecting bad DODGY packets in the stack. This approach was attempted here : https://patchwork.ozlabs.org/patch/ 861874/ - Have more robust functions in the core. This might be needed anyway for stable versions. This patch fixes the flow dissection issue. [1] CPU: 1 PID: 3144 Comm: syzkaller271204 Not tainted 4.15.0-rc4-mm1+ #49 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0x194/0x257 lib/dump_stack.c:53 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:355 [inline] kasan_report+0x23b/0x360 mm/kasan/report.c:413 __asan_report_load2_noabort+0x14/0x20 mm/kasan/report.c:432 __tcp_hdrlen include/linux/tcp.h:35 [inline] tcp_hdrlen include/linux/tcp.h:40 [inline] qdisc_pkt_len_init net/core/dev.c:3160 [inline] __dev_queue_xmit+0x20d3/0x2200 net/core/dev.c:3465 dev_queue_xmit+0x17/0x20 net/core/dev.c:3554 packet_snd net/packet/af_packet.c:2943 [inline] packet_sendmsg+0x3ad5/0x60a0 net/packet/af_packet.c:2968 sock_sendmsg_nosec net/socket.c:628 [inline] sock_sendmsg+0xca/0x110 net/socket.c:638 sock_write_iter+0x31a/0x5d0 net/socket.c:907 call_write_iter include/linux/fs.h:1776 [inline] new_sync_write fs/read_write.c:469 [inline] __vfs_write+0x684/0x970 fs/read_write.c:482 vfs_write+0x189/0x510 fs/read_write.c:544 SYSC_write fs/read_write.c:589 [inline] SyS_write+0xef/0x220 fs/read_write.c:581 entry_SYSCALL_64_fastpath+0x1f/0x96 Fixes: 34fad54c2537 ("net: __skb_flow_dissect() must cap its return value") Fixes: a6e544b0a88b ("flow_dissector: Jump to exit code in __skb_flow_dissect") Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Reported-by: syzbot Acked-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/flow_dissector.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index ee9082792530..4d14908afaec 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -492,8 +492,8 @@ ip_proto_again: out_good: ret = true; - key_control->thoff = (u16)nhoff; out: + key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen); key_basic->n_proto = proto; key_basic->ip_proto = ip_proto; @@ -501,7 +501,6 @@ out: out_bad: ret = false; - key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen); goto out; } EXPORT_SYMBOL(__skb_flow_dissect); From edaafa805e0f9d09560a4892790b8e19cab8bf09 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Thu, 18 Jan 2018 16:14:26 -0500 Subject: [PATCH 154/427] net: tcp: close sock if net namespace is exiting [ Upstream commit 4ee806d51176ba7b8ff1efd81f271d7252e03a1d ] When a tcp socket is closed, if it detects that its net namespace is exiting, close immediately and do not wait for FIN sequence. For normal sockets, a reference is taken to their net namespace, so it will never exit while the socket is open. However, kernel sockets do not take a reference to their net namespace, so it may begin exiting while the kernel socket is still open. In this case if the kernel socket is a tcp socket, it will stay open trying to complete its close sequence. The sock's dst(s) hold a reference to their interface, which are all transferred to the namespace's loopback interface when the real interfaces are taken down. When the namespace tries to take down its loopback interface, it hangs waiting for all references to the loopback interface to release, which results in messages like: unregister_netdevice: waiting for lo to become free. Usage count = 1 These messages continue until the socket finally times out and closes. Since the net namespace cleanup holds the net_mutex while calling its registered pernet callbacks, any new net namespace initialization is blocked until the current net namespace finishes exiting. After this change, the tcp socket notices the exiting net namespace, and closes immediately, releasing its dst(s) and their reference to the loopback interface, which lets the net namespace continue exiting. Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1711407 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=97811 Signed-off-by: Dan Streetman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/net_namespace.h | 10 ++++++++++ net/ipv4/tcp.c | 3 +++ net/ipv4/tcp_timer.c | 15 +++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 2dcea635ecce..93328c61934a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -209,6 +209,11 @@ int net_eq(const struct net *net1, const struct net *net2) return net1 == net2; } +static inline int check_net(const struct net *net) +{ + return atomic_read(&net->count) != 0; +} + void net_drop_ns(void *); #else @@ -233,6 +238,11 @@ int net_eq(const struct net *net1, const struct net *net2) return 1; } +static inline int check_net(const struct net *net) +{ + return 1; +} + #define net_drop_ns NULL #endif diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5597120c8ffd..37e8966a457b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2176,6 +2176,9 @@ adjudge_to_death: tcp_send_active_reset(sk, GFP_ATOMIC); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); + } else if (!check_net(sock_net(sk))) { + /* Not possible to send reset; just close */ + tcp_set_state(sk, TCP_CLOSE); } } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 1ec12a4f327e..35f638cfc675 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -46,11 +46,19 @@ static void tcp_write_err(struct sock *sk) * to prevent DoS attacks. It is called when a retransmission timeout * or zero probe timeout occurs on orphaned socket. * + * Also close if our net namespace is exiting; in that case there is no + * hope of ever communicating again since all netns interfaces are already + * down (or about to be down), and we need to release our dst references, + * which have been moved to the netns loopback interface, so the namespace + * can finish exiting. This condition is only possible if we are a kernel + * socket, as those do not hold references to the namespace. + * * Criteria is still not confirmed experimentally and may change. * We kill the socket, if: * 1. If number of orphaned sockets exceeds an administratively configured * limit. * 2. If we have strong memory pressure. + * 3. If our net namespace is exiting. */ static int tcp_out_of_resources(struct sock *sk, bool do_reset) { @@ -79,6 +87,13 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); return 1; } + + if (!check_net(sock_net(sk))) { + /* Not possible to send reset; just close */ + tcp_done(sk); + return 1; + } + return 0; } From 3f84339bd344b2cf0afe64b78d3964bb6422d0f3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 22 Jan 2018 20:11:06 +0000 Subject: [PATCH 155/427] nfsd: auth: Fix gid sorting when rootsquash enabled commit 1995266727fa8143897e89b55f5d3c79aa828420 upstream. Commit bdcf0a423ea1 ("kernel: make groups_sort calling a responsibility group_info allocators") appears to break nfsd rootsquash in a pretty major way. It adds a call to groups_sort() inside the loop that copies/squashes gids, which means the valid gids are sorted along with the following garbage. The net result is that the highest numbered valid gids are replaced with any lower-valued garbage gids, possibly including 0. We should sort only once, after filling in all the gids. Fixes: bdcf0a423ea1 ("kernel: make groups_sort calling a responsibility ...") Signed-off-by: Ben Hutchings Acked-by: J. Bruce Fields Signed-off-by: Linus Torvalds Cc: Wolfgang Walter Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/auth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index a260060042ad..67eb154af881 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c @@ -60,9 +60,10 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) else GROUP_AT(gi, i) = GROUP_AT(rqgi, i); - /* Each thread allocates its own gi, no race */ - groups_sort(gi); } + + /* Each thread allocates its own gi, no race */ + groups_sort(gi); } else { gi = get_group_info(rqgi); } From 49fe90b853dfb1087d0a734cd7f4af1aa00c8e53 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jan 2018 12:06:14 +0100 Subject: [PATCH 156/427] Linux 4.4.114 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 39019c9d205c..153440b1bbb0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 113 +SUBLEVEL = 114 EXTRAVERSION = NAME = Blurry Fish Butt From 41decf17a9eb33c7de9a4e7b7c56ada79ebedfe6 Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Wed, 31 Jan 2018 17:27:09 +0800 Subject: [PATCH 157/427] soc: rockchip: pm_test: fix memleak bug Change-Id: If484e4e8d18b860c32fbd2389c59db971b212d80 Signed-off-by: Rocky Hao --- drivers/soc/rockchip/pm_test.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/pm_test.c b/drivers/soc/rockchip/pm_test.c index 4e268659ff94..db839d16f0ba 100644 --- a/drivers/soc/rockchip/pm_test.c +++ b/drivers/soc/rockchip/pm_test.c @@ -75,6 +75,9 @@ static struct clk *clk_get_by_name(const char *clk_name) int i; np = of_find_node_by_name(NULL, "clock-controller"); + if (!np) + return ERR_PTR(-ENODEV); + clkspec.np = np; clkspec.args_count = 1; for (i = 1; i < CLK_NR_CLKS; i++) { @@ -83,12 +86,18 @@ static struct clk *clk_get_by_name(const char *clk_name) if (IS_ERR_OR_NULL(clk)) continue; name = __clk_get_name(clk); - if (strlen(name) != strlen(clk_name)) + if (strlen(name) != strlen(clk_name)) { + clk_put(clk); continue; + } if (!strncmp(name, clk_name, strlen(clk_name))) break; + + clk_put(clk); } + of_node_put(np); + if (i == CLK_NR_CLKS) clk = NULL; @@ -141,6 +150,7 @@ static int clk_rate_rawset(const char *buf) ret = clk_set_rate(clk, rate); if (ret) { pr_err("set %s rate %d error\n", clk_name, ret); + clk_put(clk); return ret; } From 62bf938f08e673abe307ca1ddd8b4bda723378aa Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 31 Jan 2018 18:38:14 +0800 Subject: [PATCH 158/427] drivers/base: remove unused devices_filter.h Change-Id: I50622b8c2d59addd303d897b57ee48b691e59b33 Signed-off-by: Tao Huang --- drivers/base/devices_filter.h | 182 ---------------------------------- 1 file changed, 182 deletions(-) delete mode 100644 drivers/base/devices_filter.h diff --git a/drivers/base/devices_filter.h b/drivers/base/devices_filter.h deleted file mode 100644 index d0a6099f46c7..000000000000 --- a/drivers/base/devices_filter.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef __DEVICES_FILTER_H -#define __DEVICES_FILTER_H -//lt 2010-12-03... - -#define USB_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - -typedef struct { - int vid; - int pid; - const char *manufacturer; - const char *product; - void *data; -}usb_parameter; - -static usb_parameter not_skip_device_list[] = { - {0x12D1, 0x1001, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", "HUAWEI Mobile",NULL}, -// {0x12D1, 0x1411, "HUAWEI Technology", "HUAWEI Mobile",NULL}, -}; - -static usb_parameter skip_device_list[] = { - {0x12D1, 0x1DA1, NULL, NULL, NULL}, - {0x12D1, 0x1D09, NULL, NULL, NULL}, - {0x12D1, 0x1520, NULL, NULL, NULL}, - {0x12D1, 0x14AC, NULL, NULL, NULL}, - {0x12D1, 0x1465, NULL, NULL, NULL}, - {0x12D1, 0x1446, NULL, NULL, NULL}, - {0x12D1, 0x1414, NULL, NULL, NULL}, - {0x12D1, 0x140C, NULL, NULL, NULL}, - {0x12D1, 0x1003, NULL, NULL, NULL}, - {0x12D1, 0x1001, NULL, NULL, NULL}, - {0x12D1, 0x1505, NULL, NULL, NULL}, - {0x12D1, 0x14FE, NULL, NULL, NULL}, - {0x12D1, 0x1506, NULL, NULL, NULL}, - {0x19D2, 0xFFF5, NULL, NULL, NULL}, - {0x19D2, 0xFFF1, NULL, NULL, NULL}, - {0x19D2, 0x2000, NULL, NULL, NULL}, - {0x19D2, 0x0120, NULL, NULL, NULL}, - {0x19D2, 0x0094, NULL, NULL, NULL}, - {0x19D2, 0x0079, NULL, NULL, NULL}, - {0x19D2, 0x0073, NULL, NULL, NULL}, - {0x19D2, 0x0033, NULL, NULL, NULL}, - {0x19D2, 0x0031, NULL, NULL, NULL}, - {0x19D2, 0x0026, NULL, NULL, NULL}, - {0x19D2, 0x0017, NULL, NULL, NULL}, - {0x19D2, 0x0015, NULL, NULL, NULL}, - {0x19D2, 0x0154, NULL, NULL, NULL}, - {0x19D2, 0x2003, NULL, NULL, NULL}, - {0x19D2, 0x0151, NULL, NULL, NULL}, - {0x04CC, 0x225A, NULL, NULL, NULL}, - {0x04CC, 0x2259, NULL, NULL, NULL}, - - {0x1410, 0x5010, NULL, NULL, NULL}, - {0x1410, 0x4400, NULL, NULL, NULL}, - - {0x1D09, 0xAEF4, NULL, NULL, NULL}, - - {0x1BBB, 0xF000, NULL, NULL, NULL}, - {0x1BBB, 0x0017, NULL, NULL, NULL}, - -// 山寨 -// {0x05C6, -1, NULL, NULL, NULL}, - {0x05C6, 0x1000, NULL, NULL, NULL}, - {0x05C6, 0xF000, NULL, NULL, NULL}, - {0x05C6, 0x0016, NULL, NULL, NULL}, - {0x1AB7, 0x5700, NULL, NULL, NULL}, - {0x20B9, 0x1682, NULL, NULL, NULL}, - - {0x028A, 0x1006, NULL, NULL, NULL}, - - {0x1C9E, 0x6061, NULL, NULL, NULL}, - {0x1C9E, 0x6000, NULL, NULL, NULL}, - {0x1C9E, 0x1001, NULL, NULL, NULL}, - - {0x1C9E, 0xF000, NULL, NULL, NULL}, - {0x1C9E, 0x9605, NULL, NULL, NULL}, - {0x21F5, 0x2008, NULL, NULL, NULL}, - {0x21F5, 0x1000, NULL, NULL, NULL}, - - {0x6000, 0x1000, NULL, NULL, NULL}, - - {0x0685, 0x7000, NULL, NULL, NULL}, - - {0x20A6, 0xF00E, NULL, NULL, NULL}, - {0x20A6, 0x1105, NULL, NULL, NULL}, - {0x1614, 0x0800, NULL, NULL, NULL}, - //begain add by xxh - {0x1A8D, 0x2000, NULL, NULL, NULL}, - {0x1C9E, 0x9913, NULL, NULL, NULL}, - {0x1C9E, 0x9915, NULL, NULL, NULL}, - {0x230D, 0x000C, NULL, NULL, NULL}, - {0x230D, 0x0003, NULL, NULL, NULL}, - {0x230D, 0x0001, NULL, NULL, NULL}, - {0x257A, 0x2601, NULL, NULL, NULL}, - {0x1E89, 0x1E16, NULL, NULL, NULL}, - {0x1C9E, 0x9800, NULL, NULL, NULL}, - {0x1dbc, 0x0669, NULL, NULL, NULL}, - {0x2020, 0x0002, NULL, NULL, NULL}, - {0x2020, 0x4000, NULL, NULL, NULL}, - {0x1C9E, 0x9916, NULL, NULL, NULL}, - {0x1C9E, 0x9918, NULL, NULL, NULL}, - {0x2001, 0xA80B, NULL, NULL, NULL}, - {0x2001, 0x7D00, NULL, NULL, NULL}, - {0x0421, 0x0610, NULL, NULL, NULL}, - {0x0af0, 0xd157, NULL, NULL, NULL}, - {0x19d2, 0x1216, NULL, NULL, NULL}, - {0x19d2, 0x1218, NULL, NULL, NULL}, - {0x05c6, 0x9000, NULL, NULL, NULL}, - {0x19d2, 0x0016, NULL, NULL, NULL},//MF110 - {0x1C9E, 0x9914, NULL, NULL, NULL},//SMART BRO WM66E - {0x2077, 0xF000, NULL, NULL, NULL}, - {0x2077, 0xA000, NULL, NULL, NULL},//beyond - {0x12d1, 0x140b, NULL, NULL, NULL},//EC122 India - {0x19D2, 0x1266, NULL, NULL, NULL},//MF190U - {0x19D2, 0x1514, NULL, NULL, NULL}, - {0x19D2, 0x1515, NULL, NULL, NULL},//MF195 - {0x1bbb, 0xf017, NULL, NULL, NULL}, - {0x19d2, 0x0117, NULL, NULL, NULL}, - {0x1C9E, 0xF001, NULL, NULL, NULL}, - {0x1C9E, 0x9801, NULL, NULL, NULL}, - //end xxh -}; - -/* 1 - match - * 0 - no match - */ -static int __must_check inline match_for_each_entry(usb_parameter* pusbp1, usb_parameter* pusbp2) -{ - if( pusbp1->vid>=0 && pusbp1->vid!=pusbp2->vid) - return 0; - - if( pusbp1->pid>=0 && pusbp1->pid!=pusbp2->pid) - return 0; - - if( pusbp1->manufacturer ) - { - if( pusbp2->manufacturer==NULL ) - return 0; - else if( strcmp(pusbp1->manufacturer, pusbp2->manufacturer) ) - return 0; - } - - if( pusbp1->product ) - { - if( pusbp2->product==NULL ) - return 0; - else if( strcmp(pusbp1->product, pusbp2->product) ) - return 0; - } - - return 1; -} - -/* - 0 - don't skip - 1 - skip the device - */ -static int is_skip_device(usb_parameter *pusbp) -{ - int i = 0; -/* - 在 not_skip_device_list 中寻找匹é…,找到则该 device 正常æµç¨‹ - 在 skip_device_list 中寻找匹é…,找到则该 device 跳过attach - 对于ä¸åœ¨ skip_device_list,not_skip_device_list,则正常æµç¨‹ - */ - for(i = 0; i < USB_ARRAY_SIZE(not_skip_device_list); i++) - { - if(match_for_each_entry(not_skip_device_list+i, pusbp)){ - return 0; - } - } - - for(i = 0; i < USB_ARRAY_SIZE(skip_device_list); i++) - { - if(match_for_each_entry(skip_device_list+i, pusbp)){ - return 1; - } - } - - return 0; -} - -#endif //__DEVICES_FILTER_H From 9be9564661c66f120ba8cf866192eb39360183ec Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 31 Jan 2018 18:02:07 +0800 Subject: [PATCH 159/427] drivers/media/video: remove unused icatch7002 Change-Id: Iba11051d729b3546b279eccb14d981c85332d38d Signed-off-by: Tao Huang --- drivers/media/video/icatch7002/Kconfig | 30 - drivers/media/video/icatch7002/Makefile | 12 - .../video/icatch7002/app_i2c_lib_icatch.c | 2298 --------------- .../video/icatch7002/app_i2c_lib_icatch.h | 451 --- .../icatch7002/burn_spi_sample_code_0910.c | 1247 -------- .../video/icatch7002/icatch7002_common.c | 2582 ----------------- .../video/icatch7002/icatch7002_common.h | 212 -- .../video/icatch7002/icatch7002_mi1040.c | 629 ---- .../video/icatch7002/icatch7002_ov2720.c | 629 ---- .../video/icatch7002/icatch7002_ov5693.c | 638 ---- .../video/icatch7002/icatch7002_ov8825.c | 639 ---- .../media/video/icatch7002/icatch_spi_host.c | 82 - .../media/video/icatch7002/icatch_spi_host.h | 23 - 13 files changed, 9472 deletions(-) delete mode 100755 drivers/media/video/icatch7002/Kconfig delete mode 100755 drivers/media/video/icatch7002/Makefile delete mode 100755 drivers/media/video/icatch7002/app_i2c_lib_icatch.c delete mode 100755 drivers/media/video/icatch7002/app_i2c_lib_icatch.h delete mode 100755 drivers/media/video/icatch7002/burn_spi_sample_code_0910.c delete mode 100755 drivers/media/video/icatch7002/icatch7002_common.c delete mode 100755 drivers/media/video/icatch7002/icatch7002_common.h delete mode 100755 drivers/media/video/icatch7002/icatch7002_mi1040.c delete mode 100755 drivers/media/video/icatch7002/icatch7002_ov2720.c delete mode 100755 drivers/media/video/icatch7002/icatch7002_ov5693.c delete mode 100755 drivers/media/video/icatch7002/icatch7002_ov8825.c delete mode 100755 drivers/media/video/icatch7002/icatch_spi_host.c delete mode 100755 drivers/media/video/icatch7002/icatch_spi_host.h diff --git a/drivers/media/video/icatch7002/Kconfig b/drivers/media/video/icatch7002/Kconfig deleted file mode 100755 index 52306b014745..000000000000 --- a/drivers/media/video/icatch7002/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -# -# Fujitsu camera isp chip: m6moj. -# -config ICATCH7002_OV5693 - depends on SOC_CAMERA_ICATCH7002 - tristate "icatch7002 attached ov5693" - default n - help - Choose Y here if you have this this sensor and it is attach to icatch7002 - -config ICATCH7002_OV8825 - depends on SOC_CAMERA_ICATCH7002 - tristate "icatch7002 attached ov8825" - default n - help - Choose Y here if you have this this sensor and it is attach to icatch7002 - -config ICATCH7002_OV2720 - depends on SOC_CAMERA_ICATCH7002 - tristate "icatch7002 attached ov2720" - default n - help - Choose Y here if you have this this sensor and it is attach to icatch7002 - -config ICATCH7002_MI1040 - depends on SOC_CAMERA_ICATCH7002 - tristate "icatch7002 attached mi1040" - default n - help - Choose Y here if you have this this sensor and it is attach to icatch7002 diff --git a/drivers/media/video/icatch7002/Makefile b/drivers/media/video/icatch7002/Makefile deleted file mode 100755 index 916cf8e754d1..000000000000 --- a/drivers/media/video/icatch7002/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for icatch isp driver -# -obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += icatch7002_common.o -#obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += icatch_spi_host.o -obj-$(CONFIG_ICATCH7002_MI1040) += icatch7002_mi1040.o -obj-$(CONFIG_ICATCH7002_OV5693) += icatch7002_ov5693.o -obj-$(CONFIG_ICATCH7002_OV8825) += icatch7002_ov8825.o -obj-$(CONFIG_ICATCH7002_OV2720) += icatch7002_ov2720.o -obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += burn_spi_sample_code_0910.o -obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += app_i2c_lib_icatch.o - diff --git a/drivers/media/video/icatch7002/app_i2c_lib_icatch.c b/drivers/media/video/icatch7002/app_i2c_lib_icatch.c deleted file mode 100755 index c85a1784662f..000000000000 --- a/drivers/media/video/icatch7002/app_i2c_lib_icatch.c +++ /dev/null @@ -1,2298 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2006-2008 by Sunplus mMedia Inc., Ltd. - * - * This software is copyrighted by and is the property of Sunplus - * mMedia Inc., Ltd. All rights are reserved by Sunplus mMedia - * Inc., Ltd. This software may only be used in accordance with the - * corresponding license agreement. Any unauthorized use, duplication, - * distribution, or disclosure of this software is expressly forbidden. - * - * This Copyright notice MUST not be removed or modified without prior - * written consent of Sunplus mMedia Inc., Ltd. - * - * Sunplus mMedia Inc., Ltd. reserves the right to modify this - * software without notice. - * - * Sunplus mMedia Inc., Ltd. - * 19-1, Innovation First Road, Science-Based Industrial Park, - * Hsin-Chu, Taiwan, R.O.C. - * - ****************************************************************************/ -#include -#include - -#include "app_i2c_lib_icatch.h" -#include -#include "icatch7002_common.h" - -#define I2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) -#define I2CDataRead(reg) icatch_sensor_read((reg)) -extern struct spi_device* g_icatch_spi_dev; - -/**************************************************************************** - * C O N S T A N T S * - ****************************************************************************/ -#define FW_HEADER_SIZE 16 -#define RES_3ACALI_HEADER_SIZE 8 -#define RES_LSC_HEADER_SIZE 24 -#define RES_LSCDQ_HEADER_SIZE 16 - -/**************************************************************************** - * M A C R O S * - ****************************************************************************/ -#ifndef tmrUsDelay -#define tmrUsDelay(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) -#endif -/**************************************************************************** - * D A T A T Y P E S * - ****************************************************************************/ - -/**************************************************************************** - * G L O B A L D A T A * - ****************************************************************************/ - -/**************************************************************************** - * E X T E R N A L R E F E R E N C E S * - ****************************************************************************/ - -/**************************************************************************** - * F U N C T I O N D E C L A R A T I O N S * - ****************************************************************************/ - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_BandSelectionSet - * ucParam: - 0x00 Reserved - 0x01 50 - 0x02 60 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_BandSelectionSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_BANDING_SELECTION, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ColorEffectSet - * ucParam: - 0x00 Normal - 0x01 Aqua - 0x02 Negative - 0x03 Sepia - 0x04 Grayscale - 0x05 Vivid - 0x06 Aura - 0x07 Vintage - 0x08 Vintage2 - 0x09 Lomo - 0x0A Red - 0x0B Blue - 0x0C Green - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_ColorEffectSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_COLOR_EFFECT, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_EvSet - * ucParam: - 0x00 +2.0 - 0x01 +1.7 - 0x02 +1.3 - 0x03 +1.0 - 0x04 +0.7 - 0x05 +0.3 - 0x06 0 - 0x07 -0.3 - 0x08 -0.7 - 0x09 -1.0 - 0x0A -1.3 - 0x0B -1.7 - 0x0C -2.0 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_EvSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_EV_COMPENSATION, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_FlashModeSet - * ucParam: - 0x00 Auto - 0x01 Off - 0x02 On - 0x03 Reserved - 0x04 Torch - 0xFF Main Flash(100%, once) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_FlashModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_FLASH_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_FocusModeSet - * ucParam: - 0x00 Auto - 0x01 Macro - 0x02 Infinity Fixed - 0x03 Continuous AF - 0x04 Full Search - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_FocusModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_FOCUS_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvSizeSet - * ucParam: - 0x00 1280x960 - 0x01 3264x2448 - 0x02 1920x1080 - 0x03 320x240(reserved) - 0x04 1280x720 - 0x05 1040x780 - 0x06 2080x1560 - 0x07 3648x2736 - 0x08 4160x3120 - 0x09 3360x1890 - 0x0A 2592x1944 - 0x0B 640x480 - 0x0C 1408x1408 - 0x0D 1920x1088 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvSizeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_PV_SIZE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_SceneModeSet - * ucParam: - 0x00 Normal - 0x01 Action - 0x02 Text - 0x03 Beach - 0x04 Candle light - 0x05 Firework - 0x06 Landscape - 0x07 Night - 0x08 Night Portrait - 0x09 Party - 0x0A Portrait - 0x0B Snow - 0x0C Sport - 0x0D Anti-shake - 0x0E Sunset - 0x0F High Sensitivity - 0x10 Landscape Portrait - 0x11 Kids - 0x12 Pet - 0x13 Flower - 0x14 Soft Flowing Water - 0x15 Food - 0x16 Backlight - 0x17 Indoor - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_SceneModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_SCENE_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_WhiteBalanceSet - * ucParam: - 0x00 Auto - 0x01 Daylight - 0x02 Cloudy - 0x03 Shade - 0x04 Fluorescent_L - 0x05 Fluorescent_H - 0x06 Tungsten - 0x07 Reserved - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_WhiteBalanceSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_WHITE_BALANCE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AEModeSet - * ucParam: - 0x00 Multi - 0x01 Center - 0x02 Spot - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AEModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_AE_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CapModeSet - * ucParam: - 0x00 Single - 0x01 HDR - 0x02 Reserved - 0x03 Burst capture(Unlimited)(ZSL) - 0x04 Burst capture(Unlimited)(mode switch) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CapModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CAP_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ISOSet - * ucParam: - 0x00 Auto - 0x01 ISO 50 - 0x02 ISO 100 - 0x03 ISO 200 - 0x04 ISO 400 - 0x05 ISO 800 - 0x06 ISO 1600 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_ISOSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CAP_ISO, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AuraColorIndexSet - * ucParam : Color index (bit control) - Effect bit : bit 0~5 - 1 : Color enable - 0 : Color disable - bit 0 : Red - bit 1 : Orange - bit 2 : Yellow - bit 3 : Green - bit 4 : Blue - bit 5 : Violet - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AuraColorIndexSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_AURA_COLOR_INDEX, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_OpticalZoomSet - * ucParam: - 0x00 Zoom in - 0x01 Zoom out - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_OpticalZoomSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_OPTICAL_ZOOM, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_IspFuncSet - * ucParam: Function control (bit control) - Effect bit : bit 0~1 - 1 : function enable - 0 : function disable - bit 0 : DWDR - bit 1 : Edge information - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_IspFuncSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_ISP_FUNCTION, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvCapModeSet - * ucParam: - 0x00 Preview mode - 0x01 Capture mode(mode switch) - 0x02 Capture mode(ZSL) - 0x03 Capture mode(Non-ZSL) - 0x04 Idle mode - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvCapModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_PV_CAP_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvStreamSet - * ucParam: - 0x00 Stream off - 0x01 Stream on - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvStreamSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_PV_STREAM, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_BurstAbortSet - * ucParam: - 0x00 Burst abort(mode switch) - 0x01 Burst abort(ZSL) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_BurstAbortSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_BURST_ABORT, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CapEdgeQuantitySet - * ucValue: - Max = 100 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CapEdgeQuantitySet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_CAP_EDGE_QUANTITY, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvFixFrameRateSet - * ucValue : - 0x00 Disable Fix Frame Rate function - 0x01~0xFF : Frame Rate - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvFixFrameRateSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_PV_FIX_FRAME_RATE, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvMaxExposureTimeSet - * ucValue : 1/N - N=0 : Disable Max. Exposure Time function - N=0x01~0xFF : Max. Exposure time - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvMaxExposureTimeSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_PV_MAX_EXPTIME, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_HdrPositiveEvSet - * ucValue: 2.4bits - eg. +1.5EV : 0x15 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_HdrPositiveEvSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_HDR_POSITIVE_EV, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_HdrNegativeEvSet - * ucValue: 2.4bits - eg. -0.4EV : 0x04 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_HdrNegativeEvSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_HDR_NEGATIVE_EV, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvMinISOSet - * ucParam: - 0x00 Disable - 0x01 ISO 50 - 0x02 ISO 100 - 0x03 ISO 200 - 0x04 ISO 400 - 0x05 ISO 800 - 0x06 ISO 1600 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_PvMinISOSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_PV_MIN_ISO, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_GSensorInfoSet - * ucX: G sensor information X axis - ucY: G sensor information Y axis - ucZ: G sensor information Z axis - Value: ((-32.768~32.767)*1000)>>8 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_GSensorInfoSet(SINT8 ucX, SINT8 ucY, SINT8 ucZ) -{ - I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_X, ucX); - I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_Y, ucY); - I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_Z, ucZ); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_GyroInfoSet - * ucX: Gyro information X axis - ucY: Gyro information Y axis - ucZ: Gyro information Z axis - Value: ((Radian : 0~2£k)*1000)>>8 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_GyroInfoSet(UINT8 ucX, UINT8 ucY, UINT8 ucZ) -{ - I2CDataWrite(SP7K_MSG_GYRO_INFO_X, ucX); - I2CDataWrite(SP7K_MSG_GYRO_INFO_Y, ucY); - I2CDataWrite(SP7K_MSG_GYRO_INFO_Z, ucZ); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFROISet - * usSize: AF ROI size - usX: AF ROI x - usY: AF ROI y - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AFROISet(UINT16 usSize, UINT16 usX, UINT16 usY) -{ - I2CDataWrite(SP7K_MSG_AF_ROI_SIZE_H, (usSize>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AF_ROI_SIZE_L, usSize&0x00FF); - I2CDataWrite(SP7K_MSG_AF_ROI_X_H, (usX>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AF_ROI_X_L, usX&0x00FF); - I2CDataWrite(SP7K_MSG_AF_ROI_Y_H, (usY>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AF_ROI_Y_L, usY&0x00FF); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFROITriggerSet - * Input : None - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AFROITriggerSet(void) -{ - I2CDataWrite(SP7K_MSG_AF_ROI_TRIGGER, 0x01); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AEROISet - * usSize: AE ROI size - usX: AE ROI x - usY: AE ROI y - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AEROISet(UINT16 usSize, UINT16 usX, UINT16 usY) -{ - I2CDataWrite(SP7K_MSG_AE_ROI_SIZE_H, (usSize>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AE_ROI_SIZE_L, usSize&0x00FF); - I2CDataWrite(SP7K_MSG_AE_ROI_X_H, (usX>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AE_ROI_X_L, usX&0x00FF); - I2CDataWrite(SP7K_MSG_AE_ROI_Y_H, (usY>>8)&0x00FF); - I2CDataWrite(SP7K_MSG_AE_ROI_Y_L, usY&0x00FF); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AEROITriggerSet - * ucParam: - 0x00 TAE off - 0x01 TAE on (Use TAE ROI : 0x48~0x4D) - 0x02 TAE on (Use TAF ROI : 0x40~0x45) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AEROITriggerSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_AE_ROI_TRIGGER, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFAbortSet - * ucParam: - 0x00 AF abort and go to infinity - 0x01 AF abort and stop in the current position - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AFAbortSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_AF_ABORT, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VcmStepSet - * usValue : VCM step value (0~1023) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VcmStepSet(UINT16 usValue) -{ - I2CDataWrite(SP7K_MSG_VCM_STEP_L, usValue&0x00FF); - I2CDataWrite(SP7K_MSG_VCM_STEP_H, (usValue>>8)&0x00FF); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CapEdgeInfoSet - * ucParam: - 0x00 None - 0x01 Ask for capture edge - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CapEdgeInfoSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CAP_EDGE_INFO, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_RawPathSet - * ucParam: - 0x00 After Front - 0x01 After WB - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_RawPathSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_RAW_PATH, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_RawFormatSet - * ucParam: - 0x00 RAW8 - 0x01 RAW10 - 0x02 RAW12 - 0x03 YUV8 - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_RawFormatSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_RAW_FORMAT, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawLinearSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawLinearSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_LINEAR, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawObSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawObSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_OB, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawBpSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawBpSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_BP, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawLscSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawLscSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_LSC, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawCaSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawCaSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_CA, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawArdSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawArdSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_ARD, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawDepeakSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawDepeakSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_DEPEAK, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationRawWbSet - * ucParam: - 0x00 Off - 0x01 On - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationRawWbSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_WB, ucParam); -} - -/*------------------------------------------------------------------------- - * File Name : EXISP_I2C_CalibrationAwbCriteriaSet - * ucVaule: 1~100, default 10% - * return none - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationAwbCriteriaSet(UINT8 ucVaule) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_AWB_CRITERIA, ucVaule); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AEAWBThreadModeSet - * ucParam: - 0x00 AE/AWB thread off - 0x01 AE/AWB thread on - 0x02 AWB thread off - 0x03 AWB thread on - 0x04 AE thread off - 0x05 AE thread on - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_AEAWBThreadModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_AEAWBTHREAD_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_DqModeSet - * ucParam: - 0x00 Pause on - 0x01 Pause off - 0x02 Interpolation Off - 0x03 Interpolation On - 0x04 Fix Color Temperature On - 0x05 Fix Color Temperature Off - 0x06 Fix ISO On(Reserved) - 0x07 Fix ISO Off(Reserved) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_DqModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_DQ_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CdspOnOffModeSet - * ucParam: - 0x00 CDSP all block off - 0x01 CDSP all block recovery - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CdspOnOffModeSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CDSP_MODE, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationCmd1Set - * ucParam: - bit 0 : Reserved - bit 1 : OB calibration(Reserved) - bit 2 : WB calibration - bit 3 : AF calibration(Reserved) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationCmd1Set(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_CMD1, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationCmd2Set - * ucParam: - bit 0 : LSC_D50 calibration - bit 1 : LSC_A calibration - bit 2 : LSC_CW calibration - bit 3 : LSC_TL84 calibration - bit 4 : LSC_D65 calibration - bit 5 : LSC_H calibration - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationCmd2Set(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_CMD2, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationInitCmdSet - * ucParam: - bit 0, 1: Calibration data target - 0x01 HOST - 0x02 EEPROM - 0x03 SPI - bit 2, 3: Band selection - 0x00 50Hz - 0x04 60Hz - bit 4, 5: LSC compression method - 0x00 Differential - 0x10 Non-compression - bit 6, 7: LSC table number - 0x00 4 table - 0x40 5 table - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationInitCmdSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_INIT_CMD, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationLscMaxGainSet - * ucVaule : 6.2bits - Range : 0x00~0xFF - 0x01 0.25% - 0x02 0.50% - 0x03 0.75% - 0xFF 63.75% - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationLscMaxGainSet(UINT8 ucVaule) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_LENS_MAX_LUM_DECAY, ucVaule); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationDqIndexFixSet - * ucParam: - bit 0~3: Color Temperature Index - 0x00 LSC off - 0x01 SPI flash is 1MB to load golden LSC & LSC_DQ table, auto - 0x02 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix A light table - 0x03 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix TL84 table - 0x04 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix CW table - 0x05 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix D50 table - 0x06 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix D65 table - 0x07 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix H table - bit 4~7: ISO index(0~5) (Reserved) - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CalibrationDqIndexFixSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_DQ_INDEX_FIX, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CaliUtilizationOptionSet - * ucParam: - bit 0: Rear Camera(3ACALI) - 0 : Use Calubration data(default) - 1 : Use Golden data - bit 1: Rear Camera(LSC) - 0 : Use Calubration data(default) - 1 : Use Golden data - bit 2: Front Camera(3ACALI) - 0 : Use Calubration data(default) - 1 : Use Golden data - bit 3: Front Camera(LSC) - 0 : Use Calubration data(default) - 1 : Use Golden data - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_CaliUtilizationOptionSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_CALIBRATION_UTILIZATION_OPTION, ucParam); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ROISwitchSet - * ucParam: - 0x00 ROI off - 0x01 ROI on - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_ROISwitchSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_ROI_SWITCH, ucParam); -} - - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqIdSet - * ucValue: vendor command ID - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqIdSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_ID, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqParamSet - * ucValue: vendor command parameter - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqParamSet(UINT8 ucValue) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_PARAM, ucValue); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqValuesSet_L - * ucVaule: vendor command the low byte of value - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqValuesSet_L(UINT8 ucVaule) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_VALUES_L, ucVaule); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqProcessSet - * Input : None - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqProcessSet(void) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_PROCESS, 0x00); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqValuesSet_H - * ucVaule: vendor command the high byte of value - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqValuesSet_H(UINT8 ucVaule) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_VALUES_H, ucVaule); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendreqCmdSet - * ucParam: - 0x00 Reserved - 0x01 Reserved - 0x02 Reserved - 0x03 AE lock - 0x04 AWB lock - 0x05 AE unlock - 0x06 AWB unlock - * Return : None - *------------------------------------------------------------------------*/ -void EXISP_I2C_VendreqCmdSet(UINT8 ucParam) -{ - I2CDataWrite(SP7K_MSG_VENDREQ_CMD, ucParam); -} - - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFStatusGet - * Input : None - * Return : AF status - 0x00 Idle - 0x01 Busy - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_AFStatusGet(void) -{ - return I2CDataRead(SP7K_RDREG_AF_STATUS); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFResultGet - * Input : None - * Return : AF result - 0x00 Focus success - 0x01 Focus fail - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_AFResultGet(void) -{ - return I2CDataRead(SP7K_RDREG_AF_RESULT); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_AFConsumeTimeGet - * Input : None - * Return : AF consuming time (ms) - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_AFConsumeTimeGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_AF_CONSUME_TIME_H)<<8) | - I2CDataRead(SP7K_RDREG_AF_CONSUME_TIME_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VcmCurrentPosGet - * Input : None - * Return : VCM current position (Range 0~1023) - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_VcmCurrentPosGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_VCM_CURRENT_POS_H)<<8) | - I2CDataRead(SP7K_RDREG_VCM_CURRENT_POS_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ExposureTimeNumeratorGet - * Input : None - * Return : exposure time numerator - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_ExposureTimeNumeratorGet(void) -{ - return I2CDataRead(SP7K_RDREG_EXPTIME_NUMERATOR); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ExposureTimeDenominatorGet - * Input : None - * Return : exposure time denominator - *------------------------------------------------------------------------*/ -UINT32 EXISP_I2C_ExposureTimeDenominatorGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_H)<<16) | - (I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_M)<<8) | - I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ExposureTimeCompensationGet - * Input : None - * Return : exposure time compensation - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_ExposureTimeCompensationGet(void) -{ - return I2CDataRead(SP7K_RDREG_EXPTIME_COMPENSATION); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_LensFocalLengthGet - * Input : None - * Return : lens focal length - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_LensFocalLengthGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_LENS_FOCAL_LENGTH_H)<<8) | - I2CDataRead(SP7K_RDREG_LENS_FOCAL_LENGTH_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_ISOValueGet - * Input : None - * Return : ISO value - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_ISOValueGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_ISO_H)<<8) | - I2CDataRead(SP7K_RDREG_ISO_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_FlashModeGet - * Input : None - * Return : flash mode - 0x00 Flash off - 0x01 Flash on - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_FlashModeGet(void) -{ - return I2CDataRead(SP7K_RDREG_FLASH_MODE); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CapEdgeInfoGet - * Input : None - * Return : capture edge information - *------------------------------------------------------------------------*/ -UINT32 EXISP_I2C_CapEdgeInfoGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B3)<<24) | - (I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B2)<<16) | - (I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B1)<<8) | - I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B0)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_3AStatusGet - * Input : None - * Return : 3A status - bit 0: AE ready bit - 0 : AE not ready - 1 : AE ready - bit 1: AWB ready bit - 0 : AWB not ready - 1 : AWB ready - bit 2: flash info - 0 : Do not flash fire - 1 : Do flash fire - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_3AStatusGet(void) -{ - return I2CDataRead(SP7K_RDREG_3A_STATUS); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_EdgeInfoCountGet - * Input : None - * Return : edge information count - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_EdgeInfoCountGet(void) -{ - return I2CDataRead(SP7K_RDREG_EDGE_INFO_COUNT); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_RearSensorIdGet - * Input : None - * Return : rear sensor id - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_RearSensorIdGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_REAR_SENSORID_H)<<8) | - I2CDataRead(SP7K_RDREG_REAR_SENSORID_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_FrontSensorIdGet - * Input : None - * Return : front sensor id - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_FrontSensorIdGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_FRONT_SENSORID_H)<<8) | - I2CDataRead(SP7K_RDREG_FRONT_SENSORID_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_FWVersionGet - * Input : None - * Return : FW version - *------------------------------------------------------------------------*/ -UINT32 EXISP_I2C_FWVersionGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_FW_VER_H)<<16) | - (I2CDataRead(SP7K_RDREG_FW_VER_M)<<8) | - I2CDataRead(SP7K_RDREG_FW_VER_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_VendorIdGet - * Input : None - * Return : vendor ID (0x7002) - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_VendorIdGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_VENDOR_ID_H)<<8) | - I2CDataRead(SP7K_RDREG_VENDOR_ID_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationLscMaxRGainGet - * Input : None - * Return : the max R gain after LSC calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationLscMaxRGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationLscMaxGGainGet - * Input : None - * Return : the max G gain after LSC calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationLscMaxGGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationLscMaxBGainGet - * Input : None - * Return : the max B gain after LSC calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationLscMaxBGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationAWBRGainGet - * Input : None - * Return : the R gain after AWB calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationAWBRGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_RGain_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_RGain_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationAWBGGainGet - * Input : None - * Return : the G gain after AWB calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationAWBGGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_GGain_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_GGain_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationAWBBGainGet - * Input : None - * Return : the B gain after AWB calibration - *------------------------------------------------------------------------*/ -UINT16 EXISP_I2C_CalibrationAWBBGainGet(void) -{ - return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_BGain_H)<<8) | - I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_BGain_L)); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationExecStatus1Get - * Input : None - * Return : OB/WB/AF calibration execution status - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationExecStatus1Get(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_EXEC_STATUS1); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationExecStatus2Get - * Input : None - * Return : LSC_D50/LSC_A/LSC_CW/LSC_TL84/LSC_D65/LSC_H calibration execution status - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationExecStatus2Get(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_EXEC_STATUS2); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationErrorStatus1Get - * Input : None - * Return : OB/WB/AF calibration error status - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationErrorStatus1Get(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_STATUS1); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationErrorStatus2Get - * Input : None - * Return : LSC_D50/LSC_A/LSC_CW/LSC_TL84/LSC_D65/LSC_H calibration error status - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationErrorStatus2Get(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_STATUS2); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationErrorCodeGet - * Input : None - * Return : calibration error code - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationErrorCodeGet(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_CODE); -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_CalibrationLoadTableStatusGet - * Input : None - * Return : load table status - *------------------------------------------------------------------------*/ -UINT8 EXISP_I2C_CalibrationLoadTableStatusGet(void) -{ - return I2CDataRead(SP7K_RDREG_CALIBRATION_LOAD_TABLE_STATUS); -} - - -/*------------------------------------------------------------------------- - * Function Name : EXISP_SuspendGpioCfgSet - * Description : Suspend GPIO configuration - * ucCtl: - 0x00 GPIO_CTL_LOW(GPIO pull low) - 0x01 GPIO_CTL_HIGH(GPIO pull high) - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_SuspendGpioCfgSet(UINT8 ucCtl) -{ - UINT8 ucRet = SUCCESS; - - if (ucCtl >= GPIO_CTL_MAX) { - ucRet = FAIL; - return ucRet; - } - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_DigitalPowerCfgSet - * Description : Provide digital power to external ISP - On: - 0x00 Close - 0x01 Open - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_DigitalPowerCfgSet(UINT8 On) -{ - UINT8 ucRet = SUCCESS; - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_AnalogPowerCfgSet - * Description : Provide analog power to external ISP - On: - 0x00 Close - 0x01 Open - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_AnalogPowerCfgSet(UINT8 On) -{ - UINT8 ucRet = SUCCESS; - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ClockCfgSet - * Description : Provide clock or not to external ISP - ucEnable: - 0x00 Don't provide clock - 0x01 Provide clock - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ClockCfgSet(UINT8 ucEnable) -{ - UINT8 ucRet = SUCCESS; - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ResetGpioCfgSet - * Description : Reset GPIO configuration - * ucCtl: - 0x00 GPIO_CTL_LOW(GPIO pull low) - 0x01 GPIO_CTL_HIGH(GPIO pull high) - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ResetGpioCfgSet(UINT8 ucCtl) -{ - UINT8 ucRet = SUCCESS; - - if (ucCtl >= GPIO_CTL_MAX) { - ucRet = FAIL; - return ucRet; - } - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_PowerOn - * Description : Power on external ISP - * ucBoot: - 0x00 BOOT_FROM_SPI(Boot from SPI) - 0x01 BOOT_FROM_HOST(Boot from host) - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_PowerOn(UINT8 ucBoot) -{ - UINT8 ucRet = SUCCESS; - - /* 1. Open digital power, 1.2V */ - ucRet = EXISP_DigitalPowerCfgSet(0x01); /* 2. Open analog power, 1.8V and 2.8V */ - ucRet = EXISP_AnalogPowerCfgSet(0x01); - /* 3. Open clock */ - ucRet = EXISP_ClockCfgSet(0x01); - /* 4. Suspend GPIO configuration */ - if (ucBoot == BOOT_FROM_SPI) { - ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_HIGH); - } - else if (ucBoot == BOOT_FROM_HOST) { - ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_LOW); - } - else { - ucRet = FAIL; - return ucRet; - } - /* 5. Reset GPIO configuration */ - ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_LOW); - /* Delay 10ms */ - tmrUsDelay(10000); - /* 6. Reset GPIO configuration */ - ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_HIGH); - /* Delay 16ms */ - tmrUsDelay(16000); - /* 7. Suspend GPIO configuration for boot from SPI */ - if (ucBoot == BOOT_FROM_SPI) { - ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_LOW); - } - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_PowerOff - * Description : Power off external ISP - * Input : None - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_PowerOff(void) -{ - UINT8 ucRet = SUCCESS; - - /* 1. Reset GPIO configuration */ - ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_LOW); - /* 2. Close clock */ - ucRet = EXISP_ClockCfgSet(0x00); - /* 3. Close analog power, 2.8V and 1.8V */ - ucRet = EXISP_AnalogPowerCfgSet(0x00); - /* 4. Close digital power, 1.2V */ - ucRet = EXISP_DigitalPowerCfgSet(0x00); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_LoadCodeStart - * Description : Load code start - * ucBoot: - 0x00 BOOT_FROM_SPI(Boot from SPI) - 0x01 BOOT_FROM_HOST(Boot from host) - ucFwIdx: Set which FW will be loaded - is_calibration: calibration flag, calibration:1 normal:0 - *pIspFw: external ISP FW pointer - *pCalibOpt: read from calibration_option.BIN - *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN - *pLsc: read from LSC.BIN or LSC_F.BIN - *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_LoadCodeStart( - UINT8 ucBoot, - UINT8 ucFwIdx, - UINT8 is_calibration, - UINT8 *pIspFw, - UINT8 *pCalibOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq) -{ - UINT8 ucRet = SUCCESS; - - if (ucBoot >= BOOT_FROM_MAX || ucFwIdx > 2) { - ucRet = FAIL; return ucRet; - } - - DEBUG_TRACE("@@@ISP FW: Load Code Start\n"); - if (ucBoot == BOOT_FROM_SPI) { - I2CDataWrite(0x1011, 1); /* CPU reset */ - /* Reset flash module */ - I2CDataWrite(0x001C, 0x08); /* reset FM */ - I2CDataWrite(0x001C, 0x00); - I2CDataWrite(0x1010, 0x02); - I2CDataWrite(0x1010, 0x00); - - I2CDataWrite(0x1306, ucFwIdx); /* Set which FW will be loaded */ - I2CDataWrite(0x1011, 0); - } - else if (ucBoot == BOOT_FROM_HOST) { - ucRet = EXISP_LoadCode(ucFwIdx, is_calibration, pIspFw, pCalibOpt, p3acali, pLsc, pLscdq); - I2CDataWrite(0x1306, ucFwIdx); /* Set which FW to be loaded */ - } - DEBUG_TRACE("@@@ISP FW: Load Code End, sts=%d\n", ucRet); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_LoadCode - * Description : Load code from host, support boot from host only - * ucFwIdx: Set which FW will be loaded - is_calibration: calibration flag, calibration:1 normal:0 - *pIspFw: external ISP FW pointer - *pCaliOpt: read from calibration_option.BIN - *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN - *pLsc: read from LSC.BIN or LSC_F.BIN - *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_LoadCode( - UINT8 ucFwIdx, - UINT8 is_calibration, - UINT8 *pIspFw, - UINT8 *pCalibOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq) -{ - UINT8 ucRet = SUCCESS; - UINT32 t1=0, t2=0, t3=0, tmrCnt=0, i=0; - UINT32 checksumWrite=0, checksumRead=0; - ispFwHeaderInfo_t *pFwInfo; - ispLoadCodeRet_t loadCodeRet; - - if (pIspFw == NULL) { - return LOADCODE_BOOT_FILE_ERR; - } - - pFwInfo = (ispFwHeaderInfo_t *)pIspFw; - for (i = 0; i < ucFwIdx; i++) { - pIspFw += FW_HEADER_SIZE+pFwInfo->DmemFicdmemSize+pFwInfo->ImemSize; - pFwInfo = (ispFwHeaderInfo_t *)pIspFw; - } - - /* Modify length to 16-alignment */ - pFwInfo->DmemFicdmemSize = (pFwInfo->DmemFicdmemSize+15)&0xFFFFFFF0; - pFwInfo->ImemSize = (pFwInfo->ImemSize+15)&0xFFFFFFF0; - //DEBUG_TRACE(" %s, %d, DmemFicdmemSize=%d\n", __FUNCTION__, __LINE__, pFwInfo->DmemFicdmemSize); - //DEBUG_TRACE(" %s, %d, ImemSize=%d\n", __FUNCTION__, __LINE__, pFwInfo->ImemSize); - //DEBUG_TRACE("0.pIspFw =%x\n", pIspFw); - DEBUG_TRACE("@@@ISP FW: Get BOOT.BIN Bin File End\n"); - -#if 1 //update golden or calibration resource - DEBUG_TRACE("@@@ISP FW: Update Resource Start\n"); - if (is_calibration == 1) { //calibration - //Nothing to do - } - else { //normal - memset(&loadCodeRet, 0, sizeof(ispLoadCodeRet_t)); - - /* pCalibOpt check */ - if (pCalibOpt == NULL) { - loadCodeRet.retCalibOpt= LOADCODE_CALIB_OPT_FILE_ERR; - goto _EXIT_; - } - /* p3acali check */ - if (p3acali == NULL) { - loadCodeRet.ret3acli= LOADCODE_3ACALI_FILE_ERR; - } - /* pLsc check */ - if (pLsc == NULL) { - loadCodeRet.retLsc= LOADCODE_LSC_FILE_ERR; - } - /* pLscdq check */ - if (pLscdq == NULL) { - loadCodeRet.retLscdq = LOADCODE_LSC_DQ_FILE_ERR; - } - - EXISP_UpdateCalibResStart(ucFwIdx, pIspFw, pFwInfo, &loadCodeRet, *pCalibOpt, p3acali, pLsc, pLscdq); - } - DEBUG_TRACE("@@@ISP FW: Update Resource End\n"); -#endif - -_EXIT_: - if (is_calibration == 1) { //calibration - DEBUG_TRACE("********** Load Golden Res **********\n"); - } - else { //normal - if (loadCodeRet.retCalibOpt == SUCCESS && - loadCodeRet.ret3acli == SUCCESS && - loadCodeRet.retLsc == SUCCESS && - loadCodeRet.retLscdq == SUCCESS) { - DEBUG_TRACE("********** Load Calibration Res **********\n"); - } - else { - if (loadCodeRet.retCalibOpt != SUCCESS) { - DEBUG_TRACE("********** Load Golden Res, retCalibOpt=%d **********\n", loadCodeRet.retCalibOpt); - } - else if (loadCodeRet.ret3acli != SUCCESS) { - DEBUG_TRACE("********** Load Golden 3ACALI Res, ret3acli=%d **********\n", loadCodeRet.ret3acli); - } - else if (loadCodeRet.retLsc != SUCCESS || loadCodeRet.retLscdq == SUCCESS) { - DEBUG_TRACE("********** Load Golden LSC Res, retLsc=%d, retLscdq=%d **********\n", loadCodeRet.retLsc, loadCodeRet.retLscdq); - } - } - } - - /* CPU reset */ - I2CDataWrite(0x1011, 1); - - /* Set imemmode*/ - t1 = pFwInfo->ImemSize/8192; - t2 = t1-32; - t3 = 1; - if ((int)t2 < 0) { - t1 = t3 << t1; - --t1; - } - else { - t3 <<= t2; - t1 = -1U; - } - --t3; - I2CDataWrite(0x1070, t1); - I2CDataWrite(0x1071, t1>>8); - I2CDataWrite(0x1072, t1>>16); - I2CDataWrite(0x1073, t1>>24); - I2CDataWrite(0x1074, t3); - - /* @@@ Start load code to SPCA7002 */ - - /* Enable checksum mechanism */ - I2CDataWrite(0x4280, 1); - - /* Wait Ready For Load Code interrupt */ - while (!(I2CDataRead(SP7K_RDREG_INT_STS_REG_0)&0x02)) { - tmrCnt++; - if (tmrCnt >= 10) { - DEBUG_TRACE("@@@ISP FW: polling RFLC bit timeout\n"); - ucRet = FAIL; return ucRet; - } - tmrUsDelay(10000); - } - I2CDataWrite(SP7K_RDREG_INT_STS_REG_0, 0x02); - - /* Load DMEM/FICDMEM bin file Start */ - DEBUG_TRACE("@@@ISP FW: Load DMEM/FICDMEM Bin File Start\n"); - pIspFw += FW_HEADER_SIZE; - /* Reset checksum value */ - I2CDataWrite(0x4284, 0x00); - checksumWrite = 0; - for (i = 0; i < pFwInfo->DmemFicdmemSize; i++) { - checksumWrite += pIspFw[i]; - } - checksumWrite &= 0xFF; - - /* Transmit DMEM/FICDMEM data */ - if(pFwInfo->DmemFicdmemSize <= 6*1024) { /* Data size <6K, load all bin file */ - ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, pFwInfo->DmemFicdmemSize, 0x0800); - I2CDataWrite(0x1011, 0); /* Set CPU to normal operation */ - } - else { - ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, 6*1024, 0x0800); - I2CDataWrite(0x1011, 0); /* Set CPU to normal operation */ - ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw+(6*1024), pFwInfo->DmemFicdmemSize-(6*1024), 0x0800+(6*1024)); - } - - /* Checksum value check */ - checksumRead = I2CDataRead(0x4284); - if (checksumWrite == checksumRead) { - DEBUG_TRACE("@@@ISP FW: Checksum DMEM/FICDMEM test: OK, %x, %x\n", checksumRead, checksumWrite); - } - else { - DEBUG_TRACE("@@@ISP FW: Checksum DMEM/FICDMEM test: FAIL, %x, %x\n", checksumRead, checksumWrite); - ucRet = FAIL; return ucRet; - } - DEBUG_TRACE("@@@ISP FW: Load DMEM/FICDMEM Bin File End\n"); - /* Load DMEM/FICDMEM bin file End */ - - /* Load IMEM bin file Start */ - DEBUG_TRACE("@@@ISP FW: Load IMEM Bin File Start\n"); - pIspFw += pFwInfo->DmemFicdmemSize; - /* Reset checksum value */ - I2CDataWrite(0x4284, 0x00); - checksumWrite = 0; - for (i = 0; i < pFwInfo->ImemSize; i++) { - checksumWrite += pIspFw[i]; - } - checksumWrite &= 0xFF; - - /* Transmit IMEM data */ - ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, pFwInfo->ImemSize, (320*1024)-pFwInfo->ImemSize); - - /* Checksum value check */ - checksumRead = I2CDataRead(0x4284); - if (checksumWrite == checksumRead) { - DEBUG_TRACE("@@@ISP FW: Checksum IMEM test: OK, %x, %x\n", checksumRead, checksumWrite); - } - else { - DEBUG_TRACE("@@@ISP FW: Checksum IMEM test: FAIL, %x, %x\n", checksumRead, checksumWrite); - ucRet = FAIL; return ucRet; - } - DEBUG_TRACE("@@@ISP FW: Load IMEM Bin File End\n"); - /* Load IMEM bin file End */ - - /* @@@ End load code to SPCA7002 */ - - /* Disable checksum mechanism */ - I2CDataWrite(0x4280, 0); - - /* Write load code end register */ - I2CDataWrite(0x1307, 0xA5); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_UpdateCalibResStart - * Description : Update calibration data start - * ucFwIdx: Set which FW will be loaded - *pIspFw: external ISP FW pointer - *pFwInfo: external ISP FW header information - *pLoadCodeRet: load code status result - ucCaliOpt: read from calibration_option.BIN - *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN - *pLsc: read from LSC.BIN or LSC_F.BIN - *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN - * Return : none - *------------------------------------------------------------------------*/ -void EXISP_UpdateCalibResStart( - UINT8 ucFwIdx, - UINT8 *pIspFw, - ispFwHeaderInfo_t *pFwInfo, - ispLoadCodeRet_t *pLoadCodeRet, - UINT8 ucCaliOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq) -{ - //DEBUG_TRACE("1.pIspFw =%x\n", pIspFw); - - if ((ucFwIdx == 0) && (ucCaliOpt != 0xFF)) { //rear sensor - ucCaliOpt = ucCaliOpt & 0x03; - } - else if ((ucFwIdx == 1) && (ucCaliOpt != 0xFF)){ //front sensor - ucCaliOpt = ucCaliOpt >> 2; - } - - switch (ucCaliOpt) { - case 1: /* load golden 3ACALI.BIN and calibrated LSC.BIN & LSC_DQ.BIN */ - if (pLsc == NULL || pLscdq == NULL) { - pLoadCodeRet->retLsc = LOADCODE_LSC_FILE_ERR; - pLoadCodeRet->retLscdq = LOADCODE_LSC_DQ_FILE_ERR; - break; - } - pLoadCodeRet->retLsc = EXISP_UpdateCalibRes(1, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); - pLoadCodeRet->retLscdq = pLoadCodeRet->retLsc; - break; - case 2: /* load calibrated 3ACALI.BIN and golden LSC.BIN & LSC_DQ.BIN */ - if (p3acali == NULL) { - pLoadCodeRet->ret3acli = LOADCODE_3ACALI_FILE_ERR; - break; - } - pLoadCodeRet->ret3acli = EXISP_UpdateCalibRes(0, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); - break; - case 3: /* load golden 3ACALI.BIN and golden LSC.BIN & LSC_DQ.BIN */ - //Nothing to do - break; - default: /* load calibrated 3ACALI.BIN and calibrated LSC.BIN & LSC_DQ.BIN */ - if (p3acali == NULL) { - pLoadCodeRet->ret3acli = LOADCODE_3ACALI_FILE_ERR; - } - if (pLoadCodeRet->ret3acli == SUCCESS) { - pLoadCodeRet->ret3acli = EXISP_UpdateCalibRes(0, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); - } - - if (pLoadCodeRet->ret3acli == LOADCODE_GET_RES_NUM_ERR) { - break; - } - else if (pLsc == NULL || pLscdq == NULL) { - pLoadCodeRet->retLsc = LOADCODE_LSC_FILE_ERR; - pLoadCodeRet->retLscdq = LOADCODE_LSC_DQ_FILE_ERR; - break; - } - pLoadCodeRet->retLsc = EXISP_UpdateCalibRes(1, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); - pLoadCodeRet->retLscdq = pLoadCodeRet->retLsc; - break; - } -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_UpdateCalibRes - * Description : Update calibration data from host, support boot from host only - * idx: Set which resource will be loaded - *pIspFw: external ISP FW pointer - *pFwInfo: external ISP FW header information - *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN - *pLsc: read from LSC.BIN or LSC_F.BIN - *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_UpdateCalibRes( - UINT8 idx, - UINT8 *pIspFw, - ispFwHeaderInfo_t *pFwInfo, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq) -{ - UINT32 iqOffset = 0, resNumCnt = 0, iqSize = 0, caliSize = 0, tempSize = 0, i; - UINT32 start3acali = 0, startLsc = 0, startLscdq = 0, size3acali = 0, sizeLsc = 0, sizeLscdq = 0; - UINT8 ucRet = SUCCESS; - - /* resource header and checksum check */ - ucRet = EXISP_ResCheck(idx, p3acali, pLsc, pLscdq); - if (ucRet != SUCCESS) { - goto _EXIT_; - } - - /* find out where IQ.BIN is */ - pIspFw += FW_HEADER_SIZE + pFwInfo->DmemSize; - //DEBUG_TRACE("2.pIspFw =%x\n", pIspFw); - if (*(pIspFw+0x38) == 0x43 && - *(pIspFw+0x39) == 0x41 && - *(pIspFw+0x3A) == 0x4C && - *(pIspFw+0x3B) == 0x49) { - iqOffset = ((*(pIspFw+0x51)<<8)&0x0000FF00) + (*(pIspFw+0x50)&0x000000FF); - } - else { - iqOffset = ((*(pIspFw+0x31)<<8)&0x0000FF00) + (*(pIspFw+0x30)&0x000000FF); - } - //DEBUG_TRACE("iqOffset=%x\n", iqOffset); - - /* point to IQ.BIN start position */ - pIspFw += iqOffset; - //DEBUG_TRACE("3.pIspFw =%x\n", pIspFw); - - /* parsing out the file size to get the start position of calibration data, - FICDMEM file size should be 16 alignment */ - ucRet = EXISP_ResNumGet(&resNumCnt, pIspFw+0x10); - if (ucRet != SUCCESS) { - goto _EXIT_; - } - //DEBUG_TRACE("resNumCnt=%d\n", resNumCnt); - //DEBUG_TRACE("5.pIspFw =%x\n", pIspFw); - - for (i = 0; i < resNumCnt; i++) { - tempSize = *(pIspFw+14+(1+i)*0x10); - tempSize += ((*(pIspFw+15+((1+i)*0x10)))<<8); - //DEBUG_TRACE("tempSize=0x%02x\n", tempSize); - if ((tempSize%0x10) != 0) { - tempSize = ((tempSize+0xF)>>4)<<4; - } - //DEBUG_TRACE("size of IQ BIN files %d: 0x%02x\n", i, tempSize); - iqSize += tempSize; - } - //DEBUG_TRACE("iqSize=%d\n", iqSize); - //DEBUG_TRACE("6.pIspFw =%x\n", pIspFw); - - /* find out 3ACALI.BIN & LSC.BIN & LSC_DQ.BIN start position */ - start3acali = iqSize+(1+resNumCnt+3)*0x10; - for (i = 0; i < 3; i++) { - tempSize = *(pIspFw+14+(1+resNumCnt+i)*0x10); - tempSize += ((*(pIspFw+15+(1+resNumCnt+i)*0x10))<<8); - if (i == 0) { - size3acali = tempSize; - } - else if (i == 1){ - sizeLsc = tempSize; - } - else { - sizeLscdq = tempSize; - } - - if ((tempSize%0x10) != 0) { - tempSize = ((tempSize+0xF)>>4)<<4; - } - //DEBUG_TRACE("0.size of IQ BIN files %d: 0x%02x\n", i, tempSize); - caliSize += tempSize; - if (i == 0) { - startLsc = start3acali + caliSize; - } - else if (i == 1) { - startLscdq = start3acali + caliSize; - } - } - //DEBUG_TRACE("start3acali=%x, size3acali=%d\n", start3acali, size3acali); - //DEBUG_TRACE("startLsc=%x, sizeLsc=%d\n", startLsc, sizeLsc); - //DEBUG_TRACE("startLscdq=%x, size=%d\n", startLscdq, sizeLscdq); - - /* update calibration data into FW buffer */ - if (idx == 0) { - memcpy(pIspFw+start3acali, p3acali, size3acali); - } - else if (idx == 1) { - memcpy(pIspFw+startLsc, pLsc, sizeLsc); - memcpy(pIspFw+startLscdq, pLscdq, sizeLscdq); - } - -_EXIT_: - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ResCheck - * Description : check resource header and checksum - * idx: Set which resource will be loaded - *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN - *pLsc: read from LSC.BIN or LSC_F.BIN - *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ResCheck(UINT8 idx, UINT8 *p3acali, UINT8 *pLsc, UINT8 *Lscdq) -{ - UINT8 ucRet = SUCCESS; - UINT32 header_3ACALI = 0, header_LSC = 0, header_LSCDQ = 0; - UINT32 chksuum_3ACALI = 0, chksuum_LSC = 0, chksuum_LSCDQ = 0, checksum = 0, dataSize = 0, i; - - /* Header check */ - if (idx == 0) { //3ACALI - header_3ACALI = *(p3acali); - header_3ACALI += (*(p3acali+1)<<8); - header_3ACALI += (*(p3acali+2)<<16); - header_3ACALI += (*(p3acali+3)<<24); - if (header_3ACALI == 0xFFFFFFFF || header_3ACALI == 0x00000000) { - DEBUG_TRACE("header_3ACALI=0x%04x\n", header_3ACALI); - ucRet = LOADCODE_3ACALI_HEADER_ERR; - goto _EXIT_; - } - } - else if (idx == 1) { //LSC & LSC_DQ - header_LSC = *(pLsc); - header_LSC += (*(pLsc+1)<<8); - header_LSC += (*(pLsc+2)<<16); - header_LSC += (*(pLsc+3)<<24); - if (header_LSC == 0xFFFFFFFF || header_LSC == 0x00000000) { - DEBUG_TRACE("header_LSC=0x%04x\n", header_LSC); - ucRet = LOADCODE_LSC_HEADER_ERR; - goto _EXIT_; - } - - header_LSCDQ = *(Lscdq); - header_LSCDQ += (*(Lscdq+1)<<8); - header_LSCDQ += (*(Lscdq+2)<<16); - header_LSCDQ += (*(Lscdq+3)<<24); - if (header_LSCDQ == 0xFFFFFFFF || header_LSCDQ == 0x00000000) { - DEBUG_TRACE("header_LSCDQ=0x%04x\n", header_LSCDQ); - ucRet = LOADCODE_LSC_DQ_HEADER_ERR; - goto _EXIT_; - } - } - - /* Checksum check */ - if (idx == 0) { //3ACALI - dataSize = *(p3acali+6); - dataSize += (*(p3acali+7)<<8); - checksum = *(p3acali+RES_3ACALI_HEADER_SIZE); - checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+1)<<8); - checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+2)<<16); - checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+3)<<24); - - for (i = 0; i < dataSize-sizeof(UINT32); i++) { - chksuum_3ACALI = chksuum_3ACALI + (*(p3acali+RES_3ACALI_HEADER_SIZE+sizeof(UINT32)+i)); - } - if (chksuum_3ACALI != checksum) { - DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_3ACALI=0x%04x\n", dataSize, checksum, chksuum_3ACALI); - ucRet = LOADCODE_3ACALI_CHKSUM_ERR; - goto _EXIT_; - } - } - else if (idx == 1) { //LSC & LSC_DQ - dataSize = *(pLsc+6); - dataSize += (*(pLsc+7)<<8); - checksum = *(pLsc+RES_LSC_HEADER_SIZE-4); - checksum += (*(pLsc+RES_LSC_HEADER_SIZE-3)<<8); - checksum += (*(pLsc+RES_LSC_HEADER_SIZE-2)<<16); - checksum += (*(pLsc+RES_LSC_HEADER_SIZE-1)<<24); - for (i = 0; i < dataSize; i++) { - chksuum_LSC = chksuum_LSC + (*(pLsc+RES_LSC_HEADER_SIZE+i)); - } - if (chksuum_LSC != checksum) { - DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_LSC=0x%04x\n", dataSize, checksum, chksuum_LSC); - ucRet = LOADCODE_LSC_CHKSUM_ERR; - goto _EXIT_; - } - - dataSize = *(Lscdq+6); - dataSize += (*(Lscdq+7)<<8); - checksum = *(Lscdq+RES_LSCDQ_HEADER_SIZE-4); - checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-3)<<8); - checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-2)<<16); - checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-1)<<24); - for (i = 0; i < dataSize; i++) { - chksuum_LSCDQ = chksuum_LSCDQ + (*(Lscdq+RES_LSCDQ_HEADER_SIZE+i)); - } - if (chksuum_LSCDQ != checksum) { - DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_LSCDQ=0x%04x\n", dataSize, checksum, chksuum_LSCDQ); - ucRet = LOADCODE_LSC_DQ_CHKSUN_ERR; - goto _EXIT_; - } - } - -_EXIT_: - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ResNumGet - * Description : get the resource number in the IQ.BIN - * *resNum: resource number - *pIspFw: external ISP FW pointer - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ResNumGet(UINT32 *resNum, UINT8 *pIspFw) -{ - UINT8 i = 0, ucRet = SUCCESS; - - //DEBUG_TRACE("4.pIspFw =%x\n", pIspFw); - while (1) { - //DEBUG_TRACE("[%s] %d 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__, __LINE__, - // *(pIspFw),*(pIspFw+1),*(pIspFw+2), *(pIspFw+3),*(pIspFw+4),*(pIspFw+5)); - if ((*(pIspFw) == 0x33) && (*(pIspFw+1) == 0x41) && (*(pIspFw+2) == 0x43) && - (*(pIspFw+3)==0x41) && (*(pIspFw+4)==0x4C) && (*(pIspFw+5)==0x49)) { - break; - } - i++; - pIspFw += 0x10; - if (i > 30) { - ucRet = LOADCODE_GET_RES_NUM_ERR; - goto _EXIT_; - } - } - -_EXIT_: - *resNum = i; - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_SPIDataWrite - * Description : write data to external ISP through SPI interface - * ucSPIMode: SPI mode - *ucStartAddr: buffer to be wrote - ulTransByteCnt: buffer size to be wrote - ulDmaAddr: SPCA7002 DMA start address - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_SPIDataWrite(UINT8 ucSPIMode, UINT8 *ucStartAddr, UINT32 ulTransByteCnt, UINT32 ulDmaAddr) -{ - UINT8 ucRet = SUCCESS; - UINT16 tmrCnt = 0; - - EXISP_7002SPICfg(ucSPIMode, ulDmaAddr, ulTransByteCnt); - - /*Trigger the 7002 SPI DMA0*/ - I2CDataWrite(0x4160, 0x01); - /* Enable data transaction */ - if(g_icatch_spi_dev) - spi_write(g_icatch_spi_dev, (void*)ucStartAddr, ulTransByteCnt); - else{ - DEBUG_TRACE("%s:g_icatch_spi_dev is null\n",__func__); - return FAIL; - } - /* Wait SPCA7002 DAM done */ - while ((I2CDataRead(0x4003)&0x02) != 0x02) { - tmrUsDelay(5000); - tmrCnt++; - if (1000 < tmrCnt) { - DEBUG_TRACE("Wait 7002 DMA0 INT Timeout.\n"); - return FAIL; - } - } - - /* Restore SPCA7002 DMA setting */ - I2CDataWrite(0x1084, 0); - I2CDataWrite(0x1085, 0); - I2CDataWrite(0x1086, 0); - I2CDataWrite(0x1087, 0); - I2CDataWrite(0x1088, 0); - I2CDataWrite(0x108c, 0); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_7002SPICfg - * Description : external SPI configuration - * ucSPIMode: SPI mode - ulDmaAddr: SPCA7002 DMA start address - ulTransByteCnt: buffer size to be wrote - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_7002SPICfg(UINT8 ucSPIMode, UINT32 ulDmaAddr, UINT32 ulTransByteCnt) -{ - UINT8 ucRet = SUCCESS; - UINT8 startBank, endBank, realEndBank, readData, i; - UINT32 bankEndValue=0; - const UINT16 bankSize = 8192; - const UINT32 maxTransByteCnt = 0x50000; - - static UINT8 regdata1[][3] = { - {0x40, 0x10, 0x10}, /*SPI reset*/ - {0x40, 0xe1, 0x00}, /*SPI mode*/ - {0x40, 0x51, 0x01}, /*SPI enable*/ - {0x40, 0x11, 0x10}, /*DMA0 reset*/ - {0x41, 0x64, 0x01}, /*Read data from host*/ - {0x41, 0x70, 0x0f}, /*Byte Cnt Low*/ - {0x41, 0x71, 0x0f}, /*Byte Cnt Mid*/ - {0x41, 0x72, 0x0f}, /*Byte Cnt High*/ - {0x10, 0x8c, 0x00}, /*DMA master select FM*/ - {0x10, 0x80, 0x00}, /*DMA start addr Low*/ - {0x10, 0x81, 0x00}, /*DMA start addr Mid*/ - {0x10, 0x82, 0x00}, /*DMA start addr High*/ - {0x10, 0x84, 0x00}, /*DMA bank enable*/ - {0x10, 0x85, 0x00}, - {0x10, 0x86, 0x00}, - {0x10, 0x87, 0x00}, - {0x10, 0x88, 0x00}, - {0x00, 0x26, 0x00}, - {0x40, 0x03, 0x02}, /*Clear DMA0 INT status*/ - }; - - regdata1[1][2] = (((UINT8)ucSPIMode) & 0xf); - regdata1[4][2] = (1&0x1); - - if (maxTransByteCnt < ulTransByteCnt) - ulTransByteCnt = (maxTransByteCnt-1); - else - ulTransByteCnt--; - - regdata1[5][2] = (ulTransByteCnt & 0xff); - regdata1[6][2] = ((ulTransByteCnt >> 8) & 0xff); - regdata1[7][2] = ((ulTransByteCnt >> 16) & 0xff); - regdata1[8][2] = 0<<4; - regdata1[9][2] = (ulDmaAddr & 0xff); - regdata1[10][2] = ((ulDmaAddr >> 8) & 0xff); - regdata1[11][2] = ((ulDmaAddr >> 16) & 0xff); - - startBank = (ulDmaAddr&0xffffff)/bankSize; - endBank = ((ulDmaAddr&0xffffff)+ulTransByteCnt)/bankSize; - realEndBank = endBank; - - if (endBank > 31) { - - for (i = 32; i <= endBank; i++) - bankEndValue |= (1 << (i-32)); - - regdata1[16][2] = (bankEndValue & 0xff); - realEndBank = 32; - bankEndValue = 0; - } - - for (i = startBank; i <= realEndBank; i++) - bankEndValue |= (1 << i); - - regdata1[12][2] = (bankEndValue & 0xff); - regdata1[13][2] = ((bankEndValue >> 8) & 0xff); - regdata1[14][2] = ((bankEndValue >>16) & 0xff); - regdata1[15][2] = ((bankEndValue >>24) & 0xff); - - readData = I2CDataRead(0x0026); /*Config the SPI pin GPIO/Function mode.*/ - readData &= (~0xf); - regdata1[17][2] = readData; - - for (i = 0; i < sizeof(regdata1)/sizeof(regdata1[0]); i++) - I2CDataWrite(((regdata1[i][0]<<8)&0xFF00)+(regdata1[i][1]&0x00FF), regdata1[i][2]); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_PvSizeSet - * Description : Set preview size - * ucResolutionIdx: resolution index - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_PvSizeSet(UINT8 ucResolutionIdx) -{ - UINT8 ucRet = SUCCESS; - - EXISP_I2C_PvSizeSet(ucResolutionIdx); - EXISP_I2C_PvCapModeSet(0x00); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ImageCapSet - * Description : Image capture - * ucImageCapIdx: image capture index - 0x00 IMAGE_CAP_SINGLE - 0x01 IMAGE_CAP_HDR - 0x02 IMAGE_CAP_ZSL_SINGLE_FLASH - 0x03 IMAGE_CAP_ZSL_BURST_FLASH - 0x04 IMAGE_CAP_NONZSL_SINGLE - 0x05 IMAGE_CAP_NONZSL_BURST - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ImageCapSet(UINT8 ucImageCapIdx) -{ - UINT8 ucRet = SUCCESS; - - if (ucImageCapIdx >= IMAGE_CAP_MAX) { - ucRet = FAIL; - return ucRet; - } - - switch (ucImageCapIdx) { - case IMAGE_CAP_SINGLE: - EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP); - break; - case IMAGE_CAP_HDR: - EXISP_I2C_CapModeSet(CAP_MODE_HDR); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP); - break; - case IMAGE_CAP_ZSL_SINGLE_FLASH: - EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_ZSL); - break; - case IMAGE_CAP_ZSL_BURST_FLASH: - EXISP_I2C_CapModeSet(CAP_MODE_BURST); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_ZSL); - break; - case IMAGE_CAP_NONZSL_SINGLE: - EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_NONZSL); - break; - case IMAGE_CAP_NONZSL_BURST: - EXISP_I2C_CapModeSet(CAP_MODE_BURST); - EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_NONZSL); - break; - } - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_TAFTAEROISet - * Description : Set TAF or TAE ROI and trigger - * ucTrg: - 0x00 TAFTAE_TAF_ONLY - 0x01 TAFTAE_TAE_OFF - 0x02 TAFTAE_TAE_USE_TAE_ROI - 0x03 TAFTAE_TAE_USE_TAF_ROI - 0x04 TAFTAE_TAE_ONLY - usTAFSize: AF ROI size - usTAFX: AF ROI x - usTAFY: AF ROI y - usTAESize: AE ROI size - usTAEX: AE ROI x - usTAEY: AE ROI y - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_TAFTAEROISet( - UINT8 ucTrg, - UINT16 usTAFSize, - UINT16 usTAFX, - UINT16 usTAFY, - UINT16 usTAESize, - UINT16 usTAEX, - UINT16 usTAEY) -{ - UINT8 ucRet = SUCCESS; - - if (ucTrg >= TAFTAE_MAX) { - ucRet = FAIL; - return ucRet; - } - - switch (ucTrg) { - case TAFTAE_TAF_ONLY: - EXISP_I2C_ROISwitchSet(0x01); - EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); - EXISP_I2C_AFROITriggerSet(); - break; - case TAFTAE_TAE_OFF: - EXISP_I2C_AEROITriggerSet(0x00); - break; - - case TAFTAE_TAE_USE_TAE_ROI: - EXISP_I2C_ROISwitchSet(0x01); - EXISP_I2C_AEROISet(usTAESize, usTAEX, usTAEY); - EXISP_I2C_AEROITriggerSet(0x01); - EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); - EXISP_I2C_AFROITriggerSet(); - break; - case TAFTAE_TAE_USE_TAF_ROI: - EXISP_I2C_ROISwitchSet(0x01); - EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); - EXISP_I2C_AEROITriggerSet(0x02); - EXISP_I2C_AFROITriggerSet(); - break; - case TAFTAE_TAE_ONLY: - EXISP_I2C_ROISwitchSet(0x01); - EXISP_I2C_AEROISet(usTAESize, usTAEX, usTAEY); - EXISP_I2C_AEROITriggerSet(0x01); - } - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_SwitchRAWFormatSet - * Description : Switch to RAW format from YUV format - * Input : None - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_SwitchRAWFormatSet(void) -{ - UINT8 ucRet = SUCCESS; - - EXISP_I2C_RawPathSet(0x00); - EXISP_I2C_RawFormatSet(0x01); - - return ucRet; -} - -/*------------------------------------------------------------------------- - * Function Name : EXISP_ExifInfoGet - * Description : Get EXIF information from external ISP - * Input : None - * Return : status result - *------------------------------------------------------------------------*/ -UINT8 EXISP_ExifInfoGet( - UINT8 *ucExpTimeNumerator, - UINT32 *ulExpTimeDenominator, - UINT8 *ucExpTimeCompensation, - UINT16 *usLensFocalLength, - UINT16 *usIsoInfo, - UINT8 *ucFlashInfo) -{ - UINT8 ucRet = SUCCESS; - - /* Get exposure time numerator */ - *ucExpTimeNumerator = EXISP_I2C_ExposureTimeNumeratorGet(); - /* Get exposure time denominator */ - *ulExpTimeDenominator = EXISP_I2C_ExposureTimeDenominatorGet(); - /* Get exposure time compensation */ - *ucExpTimeCompensation = EXISP_I2C_ExposureTimeCompensationGet(); - /* Get lens focal length */ - *usLensFocalLength = EXISP_I2C_LensFocalLengthGet(); - /* Get ISO information */ - *usIsoInfo = EXISP_I2C_ISOValueGet(); - /* Get flash mode information */ - *ucFlashInfo = EXISP_I2C_FlashModeGet(); - - return ucRet; -} - diff --git a/drivers/media/video/icatch7002/app_i2c_lib_icatch.h b/drivers/media/video/icatch7002/app_i2c_lib_icatch.h deleted file mode 100755 index 5a0a79572f1d..000000000000 --- a/drivers/media/video/icatch7002/app_i2c_lib_icatch.h +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2006-2008 by Sunplus mMedia Inc., Ltd. - * - * This software is copyrighted by and is the property of Sunplus - * mMedia Inc., Ltd. All rights are reserved by Sunplus mMedia - * Inc., Ltd. This software may only be used in accordance with the - * corresponding license agreement. Any unauthorized use, duplication, - * distribution, or disclosure of this software is expressly forbidden. - * - * This Copyright notice MUST not be removed or modified without prior - * written consent of Sunplus mMedia Inc., Ltd. - * - * Sunplus mMedia Inc., Ltd. reserves the right to modify this - * software without notice. - * - * Sunplus mMedia Inc., Ltd. - * 19-1, Innovation First Road, Science-Based Industrial Park, - * Hsin-Chu, Taiwan, R.O.C. - * - ****************************************************************************/ -#ifndef APP_I2C_LIB_ICATCH_H -#define APP_I2C_LIB_ICATCH_H - - -/**************************************************************************** - * C O N S T A N T S * - ****************************************************************************/ -#ifndef NULL -#define NULL ((void *)0) -#endif -#ifndef SUCCESS -#define SUCCESS 0 -#endif -#ifndef FAIL -#define FAIL 1 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define UINT64 unsigned long long -#define UINT32 unsigned int -#define UINT16 unsigned short -#define UINT8 unsigned char -#define SINT64 signed long long -#define SINT32 signed int -#define SINT16 signed short -#define SINT8 signed char -#define BOOL unsigned char - -#define SP7K_MSG_BASE 0x7100 -#define SP7K_REG_BASE 0x7280 - -/**************************************************************************** - * D A T A T Y P E S * - ****************************************************************************/ -typedef enum { - SP7K_MSG_BANDING_SELECTION = (SP7K_MSG_BASE | 0x01), - SP7K_MSG_COLOR_EFFECT = (SP7K_MSG_BASE | 0x02), - SP7K_MSG_EV_COMPENSATION = (SP7K_MSG_BASE | 0x03), - SP7K_MSG_FLASH_MODE = (SP7K_MSG_BASE | 0x04), - SP7K_MSG_FOCUS_MODE = (SP7K_MSG_BASE | 0x05), - SP7K_MSG_PV_SIZE = (SP7K_MSG_BASE | 0x06), - SP7K_MSG_SCENE_MODE = (SP7K_MSG_BASE | 0x09), - SP7K_MSG_WHITE_BALANCE = (SP7K_MSG_BASE | 0x0A), - SP7K_MSG_AE_MODE = (SP7K_MSG_BASE | 0x0E), - SP7K_MSG_CAP_MODE = (SP7K_MSG_BASE | 0x0F), - SP7K_MSG_CAP_ISO = (SP7K_MSG_BASE | 0x10), - SP7K_MSG_AURA_COLOR_INDEX = (SP7K_MSG_BASE | 0x19), - SP7K_MSG_OPTICAL_ZOOM = (SP7K_MSG_BASE | 0x1A), - SP7K_MSG_ISP_FUNCTION = (SP7K_MSG_BASE | 0x1B), - SP7K_MSG_PV_CAP_MODE = (SP7K_MSG_BASE | 0x20), - SP7K_MSG_PV_STREAM = (SP7K_MSG_BASE | 0x21), - SP7K_MSG_BURST_ABORT = (SP7K_MSG_BASE | 0x22), - SP7K_MSG_CAP_EDGE_QUANTITY = (SP7K_MSG_BASE | 0x23), - SP7K_MSG_PV_FIX_FRAME_RATE = (SP7K_MSG_BASE | 0x24), - SP7K_MSG_PV_MAX_EXPTIME = (SP7K_MSG_BASE | 0x25), - SP7K_MSG_HDR_POSITIVE_EV = (SP7K_MSG_BASE | 0x27), - SP7K_MSG_HDR_NEGATIVE_EV = (SP7K_MSG_BASE | 0x28), - SP7K_MSG_PV_MIN_ISO = (SP7K_MSG_BASE | 0x29), - SP7K_MSG_G_SENSOR_INFO_X = (SP7K_MSG_BASE | 0x2A), - SP7K_MSG_G_SENSOR_INFO_Y = (SP7K_MSG_BASE | 0x2B), - SP7K_MSG_G_SENSOR_INFO_Z = (SP7K_MSG_BASE | 0x2C), - SP7K_MSG_GYRO_INFO_X = (SP7K_MSG_BASE | 0x2D), - SP7K_MSG_GYRO_INFO_Y = (SP7K_MSG_BASE | 0x2E), - SP7K_MSG_GYRO_INFO_Z = (SP7K_MSG_BASE | 0x2F), - SP7K_MSG_AF_ROI_SIZE_H = (SP7K_MSG_BASE | 0x40), - SP7K_MSG_AF_ROI_SIZE_L = (SP7K_MSG_BASE | 0x41), - SP7K_MSG_AF_ROI_X_H = (SP7K_MSG_BASE | 0x42), - SP7K_MSG_AF_ROI_X_L = (SP7K_MSG_BASE | 0x43), - SP7K_MSG_AF_ROI_Y_H = (SP7K_MSG_BASE | 0x44), - SP7K_MSG_AF_ROI_Y_L = (SP7K_MSG_BASE | 0x45), - SP7K_MSG_AF_ROI_TRIGGER = (SP7K_MSG_BASE | 0x46), - SP7K_MSG_AE_ROI_SIZE_H = (SP7K_MSG_BASE | 0x48), - SP7K_MSG_AE_ROI_SIZE_L = (SP7K_MSG_BASE | 0x49), - SP7K_MSG_AE_ROI_X_H = (SP7K_MSG_BASE | 0x4A), - SP7K_MSG_AE_ROI_X_L = (SP7K_MSG_BASE | 0x4B), - SP7K_MSG_AE_ROI_Y_H = (SP7K_MSG_BASE | 0x4C), - SP7K_MSG_AE_ROI_Y_L = (SP7K_MSG_BASE | 0x4D), - SP7K_MSG_AE_ROI_TRIGGER = (SP7K_MSG_BASE | 0x4E), - SP7K_MSG_AF_ABORT = (SP7K_MSG_BASE | 0x4F), - SP7K_MSG_VCM_STEP_L = (SP7K_MSG_BASE | 0x5C), - SP7K_MSG_VCM_STEP_H = (SP7K_MSG_BASE | 0x5D), - SP7K_MSG_CAP_EDGE_INFO = (SP7K_MSG_BASE | 0x5F), - SP7K_MSG_RAW_PATH = (SP7K_MSG_BASE | 0x60), - SP7K_MSG_RAW_FORMAT = (SP7K_MSG_BASE | 0x61), - SP7K_MSG_CALIBRATION_RAW_LINEAR = (SP7K_MSG_BASE | 0x62), - SP7K_MSG_CALIBRATION_RAW_OB = (SP7K_MSG_BASE | 0x63), - SP7K_MSG_CALIBRATION_RAW_BP = (SP7K_MSG_BASE | 0x64), - SP7K_MSG_CALIBRATION_RAW_LSC = (SP7K_MSG_BASE | 0x65), - SP7K_MSG_CALIBRATION_RAW_CA = (SP7K_MSG_BASE | 0x66), - SP7K_MSG_CALIBRATION_RAW_ARD = (SP7K_MSG_BASE | 0x67), - SP7K_MSG_CALIBRATION_RAW_DEPEAK = (SP7K_MSG_BASE | 0x68), - SP7K_MSG_CALIBRATION_RAW_WB = (SP7K_MSG_BASE | 0x69), - SP7K_MSG_CALIBRATION_AWB_CRITERIA = (SP7K_MSG_BASE | 0x6D), - SP7K_MSG_AEAWBTHREAD_MODE = (SP7K_MSG_BASE | 0x70), - SP7K_MSG_DQ_MODE = (SP7K_MSG_BASE | 0x71), - SP7K_MSG_CDSP_MODE = (SP7K_MSG_BASE | 0x72), - SP7K_MSG_CALIBRATION_CMD1 = (SP7K_MSG_BASE | 0x74), - SP7K_MSG_CALIBRATION_CMD2 = (SP7K_MSG_BASE | 0x75), - SP7K_MSG_CALIBRATION_INIT_CMD = (SP7K_MSG_BASE | 0x76), - SP7K_MSG_CALIBRATION_LENS_MAX_LUM_DECAY = (SP7K_MSG_BASE | 0x77), - SP7K_MSG_CALIBRATION_DQ_INDEX_FIX = (SP7K_MSG_BASE | 0x78), - SP7K_MSG_CALIBRATION_UTILIZATION_OPTION = (SP7K_MSG_BASE | 0x7F), - SP7K_MSG_ROI_SWITCH = (SP7K_MSG_BASE | 0x88), - - SP7K_MSG_VENDREQ_ID = (SP7K_MSG_BASE | 0xE4), - SP7K_MSG_VENDREQ_PARAM = (SP7K_MSG_BASE | 0xE5), - SP7K_MSG_VENDREQ_VALUES_L = (SP7K_MSG_BASE | 0xE6), - SP7K_MSG_VENDREQ_PROCESS = (SP7K_MSG_BASE | 0xE8), - SP7K_MSG_VENDREQ_VALUES_H = (SP7K_MSG_BASE | 0xEA), - SP7K_MSG_VENDREQ_CMD = (SP7K_MSG_BASE | 0xEB), -} sp7kHostMsgList_e; - -typedef enum { - SP7K_RDREG_AF_STATUS = (SP7K_REG_BASE | 0xA0), - SP7K_RDREG_AF_RESULT = (SP7K_REG_BASE | 0xA1), - SP7K_RDREG_AF_CONSUME_TIME_L = (SP7K_REG_BASE | 0xA2), - SP7K_RDREG_AF_CONSUME_TIME_H = (SP7K_REG_BASE | 0xA3), - SP7K_RDREG_VCM_CURRENT_POS_L = (SP7K_REG_BASE | 0xA4), - SP7K_RDREG_VCM_CURRENT_POS_H = (SP7K_REG_BASE | 0xA5), - SP7K_RDREG_EXPTIME_NUMERATOR = (SP7K_REG_BASE | 0xB0), - SP7K_RDREG_EXPTIME_DENOMINATOR_L = (SP7K_REG_BASE | 0xB1), - SP7K_RDREG_EXPTIME_DENOMINATOR_M = (SP7K_REG_BASE | 0xB2), - SP7K_RDREG_EXPTIME_DENOMINATOR_H = (SP7K_REG_BASE | 0xB3), - SP7K_RDREG_EXPTIME_COMPENSATION = (SP7K_REG_BASE | 0xB4), - SP7K_RDREG_LENS_FOCAL_LENGTH_L = (SP7K_REG_BASE | 0xB5), - SP7K_RDREG_LENS_FOCAL_LENGTH_H = (SP7K_REG_BASE | 0xB6), - SP7K_RDREG_ISO_L = (SP7K_REG_BASE | 0xB7), - SP7K_RDREG_ISO_H = (SP7K_REG_BASE | 0xB8), - SP7K_RDREG_FLASH_MODE = (SP7K_REG_BASE | 0xB9), - SP7K_RDREG_CAP_EDGE_INFO_B0 = (SP7K_REG_BASE | 0xBA), - SP7K_RDREG_CAP_EDGE_INFO_B1 = (SP7K_REG_BASE | 0xBB), - SP7K_RDREG_CAP_EDGE_INFO_B2 = (SP7K_REG_BASE | 0xBC), - SP7K_RDREG_CAP_EDGE_INFO_B3 = (SP7K_REG_BASE | 0xBD), - SP7K_RDREG_3A_STATUS = (SP7K_REG_BASE | 0xC3), - SP7K_RDREG_EDGE_INFO_COUNT = (SP7K_REG_BASE | 0xC4), - SP7K_RDREG_REAR_SENSORID_L = (SP7K_REG_BASE | 0xC6), - SP7K_RDREG_REAR_SENSORID_H = (SP7K_REG_BASE | 0xC7), - SP7K_RDREG_FRONT_SENSORID_L = (SP7K_REG_BASE | 0xC8), - SP7K_RDREG_FRONT_SENSORID_H = (SP7K_REG_BASE | 0xC9), - SP7K_RDREG_FW_VER_L = (SP7K_REG_BASE | 0xCA), - SP7K_RDREG_FW_VER_M = (SP7K_REG_BASE | 0xCB), - SP7K_RDREG_FW_VER_H = (SP7K_REG_BASE | 0xCC), - SP7K_RDREG_VENDOR_ID_L = (SP7K_REG_BASE | 0xCE), - SP7K_RDREG_VENDOR_ID_H = (SP7K_REG_BASE | 0xCF), - SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_L = (SP7K_REG_BASE | 0xD8), - SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_H = (SP7K_REG_BASE | 0xD9), - SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_L = (SP7K_REG_BASE | 0xDA), - SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_H = (SP7K_REG_BASE | 0xDB), - SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_L = (SP7K_REG_BASE | 0xDC), - SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_H = (SP7K_REG_BASE | 0xDD), - SP7K_RDREG_CALIBRATION_AWB_RGain_L = (SP7K_REG_BASE | 0xE1), - SP7K_RDREG_CALIBRATION_AWB_RGain_H = (SP7K_REG_BASE | 0xE2), - SP7K_RDREG_CALIBRATION_AWB_GGain_L = (SP7K_REG_BASE | 0xE3), - SP7K_RDREG_CALIBRATION_AWB_GGain_H = (SP7K_REG_BASE | 0xE4), - SP7K_RDREG_CALIBRATION_AWB_BGain_L = (SP7K_REG_BASE | 0xE5), - SP7K_RDREG_CALIBRATION_AWB_BGain_H = (SP7K_REG_BASE | 0xE6), - SP7K_RDREG_CALIBRATION_EXEC_STATUS1 = (SP7K_REG_BASE | 0xF0), - SP7K_RDREG_CALIBRATION_EXEC_STATUS2 = (SP7K_REG_BASE | 0xF1), - SP7K_RDREG_CALIBRATION_ERROR_STATUS1 = (SP7K_REG_BASE | 0xF2), - SP7K_RDREG_CALIBRATION_ERROR_STATUS2 = (SP7K_REG_BASE | 0xF3), - SP7K_RDREG_CALIBRATION_ERROR_CODE = (SP7K_REG_BASE | 0xF4), - SP7K_RDREG_CALIBRATION_LOAD_TABLE_STATUS= (SP7K_REG_BASE | 0xF5), - SP7K_RDREG_INT_STS_REG_0 = (SP7K_REG_BASE | 0xF8), - SP7K_RDREG_INT_MASK_REG_0 = (SP7K_REG_BASE | 0xFC), -} sp7kReadRegList_e; - -typedef enum { - GPIO_CTL_LOW, - GPIO_CTL_HIGH, - GPIO_CTL_MAX, -} sp7kGpioCtlList_e; - -typedef enum { - BOOT_FROM_SPI, - BOOT_FROM_HOST, - BOOT_FROM_MAX, -} sp7kPowerOnList_e; - -typedef enum { - SENSOR_ID_REAR, - SENSOR_ID_FRONT, - SENSOR_ID_REAR_CALIBRATION, - SENSOR_ID_MAX, -} sp7kSensorIdList_e; - -typedef enum { - IMAGE_CAP_SINGLE, - IMAGE_CAP_HDR, - IMAGE_CAP_ZSL_SINGLE_FLASH, - IMAGE_CAP_ZSL_BURST_FLASH, - IMAGE_CAP_NONZSL_SINGLE, - IMAGE_CAP_NONZSL_BURST, - IMAGE_CAP_MAX, -} sp7kImageCapList_e; - -typedef enum { - CAP_MODE_SINGLE, - CAP_MODE_HDR, - CAP_MODE_RSV, - CAP_MODE_BURST, - CAP_MODE_MAX, -} sp7kCapModeList_e; - -typedef enum { - PVCAP_MODE_PV, - PVCAP_MODE_CAP, - PVCAP_MODE_CAP_ZSL, - PVCAP_MODE_CAP_NONZSL, - PVCAP_MODE_MAX, -} sp7kPvCapModeList_e; - -typedef enum { - TAFTAE_TAF_ONLY, - TAFTAE_TAE_OFF, - TAFTAE_TAE_USE_TAE_ROI, - TAFTAE_TAE_USE_TAF_ROI, - TAFTAE_TAE_ONLY, - TAFTAE_MAX, -} sp7kTAFTAEList_e; - -typedef enum { - NONE, - LOADCODE_BOOT_FILE_ERR, - - LOADCODE_CALIB_OPT_FILE_ERR, - LOADCODE_CALIB_OPT_MAX_ERR, - - LOADCODE_3ACALI_FILE_ERR, - LOADCODE_3ACALI_HEADER_ERR, - LOADCODE_3ACALI_CHKSUM_ERR, - - LOADCODE_LSC_FILE_ERR, - LOADCODE_LSC_HEADER_ERR, - LOADCODE_LSC_CHKSUM_ERR, - - LOADCODE_LSC_DQ_FILE_ERR, - LOADCODE_LSC_DQ_HEADER_ERR, - LOADCODE_LSC_DQ_CHKSUN_ERR, - - LOADCODE_GET_RES_NUM_ERR, -} LoadCodeErrList_e; - -typedef struct { - UINT32 DmemFicdmemSize; /*DMEM+FICDMEM size*/ - UINT32 ImemSize; /*IMEM size*/ - UINT16 FmClk; /*FM clock*/ - UINT16 Checksum; /*checksum*/ - UINT32 DmemSize; /*DMEM size*/ -} ispFwHeaderInfo_t; - -typedef struct { - UINT32 retCalibOpt; - UINT32 ret3acli; - UINT32 retLsc; - UINT32 retLscdq; -} ispLoadCodeRet_t; - -/**************************************************************************** - * M A C R O S * - ****************************************************************************/ - -/**************************************************************************** - * E X T E R N V A R I A B L E S D E C L A R A T I O N S * - ****************************************************************************/ - -/**************************************************************************** - * F U N C T I O N D E C L A R A T I O N S * - ****************************************************************************/ -void EXISP_I2C_BandSelectionSet(UINT8 ucParam); -void EXISP_I2C_ColorEffectSet(UINT8 ucParam); -void EXISP_I2C_EvSet(UINT8 ucParam); -void EXISP_I2C_FlashModeSet(UINT8 ucParam); -void EXISP_I2C_FocusModeSet(UINT8 ucParam); -void EXISP_I2C_PvSizeSet(UINT8 ucParam); -void EXISP_I2C_SceneModeSet(UINT8 ucParam); -void EXISP_I2C_WhiteBalanceSet(UINT8 ucParam); -void EXISP_I2C_AEModeSet(UINT8 ucParam); -void EXISP_I2C_CapModeSet(UINT8 ucParam); -void EXISP_I2C_ISOSet(UINT8 ucParam); -void EXISP_I2C_AuraColorIndexSet(UINT8 ucParam); -void EXISP_I2C_OpticalZoomSet(UINT8 ucParam); -void EXISP_I2C_IspFuncSet(UINT8 ucParam); -void EXISP_I2C_PvCapModeSet(UINT8 ucParam); -void EXISP_I2C_PvStreamSet(UINT8 ucParam); -void EXISP_I2C_BurstAbortSet(UINT8 ucParam); -void EXISP_I2C_CapEdgeQuantitySet(UINT8 ucValue); -void EXISP_I2C_PvFixFrameRateSet(UINT8 ucValue); -void EXISP_I2C_PvMaxExposureTimeSet(UINT8 ucValue); -void EXISP_I2C_HdrPositiveEvSet(UINT8 ucValue); -void EXISP_I2C_HdrNegativeEvSet(UINT8 ucValue); -void EXISP_I2C_PvMinISOSet(UINT8 ucParam); -void EXISP_I2C_GSensorInfoSet(SINT8 ucX, SINT8 ucY, SINT8 ucZ); -void EXISP_I2C_GyroInfoSet(UINT8 ucX, UINT8 ucY, UINT8 ucZ); -void EXISP_I2C_AFROISet(UINT16 usSize, UINT16 usX, UINT16 usY); -void EXISP_I2C_AFROITriggerSet(void); -void EXISP_I2C_AEROISet(UINT16 usSize, UINT16 usX, UINT16 usY); -void EXISP_I2C_AEROITriggerSet(UINT8 ucParam); -void EXISP_I2C_AFAbortSet(UINT8 ucParam); -void EXISP_I2C_VcmStepSet(UINT16 usValue); -void EXISP_I2C_CapEdgeInfoSet(UINT8 ucParam); -void EXISP_I2C_RawPathSet(UINT8 ucParam); -void EXISP_I2C_RawFormatSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawLinearSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawObSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawBpSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawLscSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawCaSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawArdSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawDepeakSet(UINT8 ucParam); -void EXISP_I2C_CalibrationRawWbSet(UINT8 ucParam); -void EXISP_I2C_CalibrationAwbCriteriaSet(UINT8 ucVaule); -void EXISP_I2C_AEAWBThreadModeSet(UINT8 ucParam); -void EXISP_I2C_DqModeSet(UINT8 ucParam); -void EXISP_I2C_CdspOnOffModeSet(UINT8 ucParam); -void EXISP_I2C_CalibrationCmd1Set(UINT8 ucParam); -void EXISP_I2C_CalibrationCmd2Set(UINT8 ucParam); -void EXISP_I2C_CalibrationInitCmdSet(UINT8 ucParam); -void EXISP_I2C_CalibrationLscMaxGainSet(UINT8 ucVaule); -void EXISP_I2C_CalibrationDqIndexFixSet(UINT8 ucParam); -void EXISP_I2C_CaliUtilizationOptionSet(UINT8 ucParam); -void EXISP_I2C_ROISwitchSet(UINT8 ucParam); -void EXISP_I2C_VendreqIdSet(UINT8 ucValue); -void EXISP_I2C_VendreqParamSet(UINT8 ucValue); -void EXISP_I2C_VendreqValuesSet_L(UINT8 ucVaule); -void EXISP_I2C_VendreqProcessSet(void); -void EXISP_I2C_VendreqValuesSet_H(UINT8 ucVaule); -void EXISP_I2C_VendreqCmdSet(UINT8 ucParam); - - -UINT8 EXISP_I2C_AFStatusGet(void); -UINT8 EXISP_I2C_AFResultGet(void); -UINT16 EXISP_I2C_AFConsumeTimeGet(void); -UINT16 EXISP_I2C_VcmCurrentPosGet(void); -UINT8 EXISP_I2C_ExposureTimeNumeratorGet(void); -UINT32 EXISP_I2C_ExposureTimeDenominatorGet(void); -UINT8 EXISP_I2C_ExposureTimeCompensationGet(void); -UINT16 EXISP_I2C_LensFocalLengthGet(void); -UINT16 EXISP_I2C_ISOValueGet(void); -UINT8 EXISP_I2C_FlashModeGet(void); -UINT32 EXISP_I2C_CapEdgeInfoGet(void); -UINT8 EXISP_I2C_3AStatusGet(void); -UINT8 EXISP_I2C_EdgeInfoCountGet(void); -UINT16 EXISP_I2C_RearSensorIdGet(void); -UINT16 EXISP_I2C_FrontSensorIdGet(void); -UINT32 EXISP_I2C_FWVersionGet(void); -UINT16 EXISP_I2C_VendorIdGet(void); -UINT16 EXISP_I2C_CalibrationLscMaxRGainGet(void); -UINT16 EXISP_I2C_CalibrationLscMaxGGainGet(void); -UINT16 EXISP_I2C_CalibrationLscMaxBGainGet(void); -UINT16 EXISP_I2C_CalibrationAWBRGainGet(void); -UINT16 EXISP_I2C_CalibrationAWBGGainGet(void); -UINT16 EXISP_I2C_CalibrationAWBBGainGet(void); -UINT8 EXISP_I2C_CalibrationExecStatus1Get(void); -UINT8 EXISP_I2C_CalibrationExecStatus2Get(void); -UINT8 EXISP_I2C_CalibrationErrorStatus1Get(void); -UINT8 EXISP_I2C_CalibrationErrorStatus2Get(void); -UINT8 EXISP_I2C_CalibrationErrorCodeGet(void); -UINT8 EXISP_I2C_CalibrationLoadTableStatusGet(void); - - -UINT8 EXISP_SuspendGpioCfgSet(UINT8 ucCtl); -UINT8 EXISP_DigitalPowerCfgSet(UINT8 On); -UINT8 EXISP_AnalogPowerCfgSet(UINT8 On); -UINT8 EXISP_ClockCfgSet(UINT8 ucEnable); -UINT8 EXISP_ResetGpioCfgSet(UINT8 ucCtl); -UINT8 EXISP_PowerOn(UINT8 ucBoot); -UINT8 EXISP_PowerOff(void); -UINT8 EXISP_LoadCodeStart( - UINT8 ucBoot, - UINT8 ucFwIdx, - UINT8 is_calibration, - UINT8 *pIspFw, - UINT8 *pCalibOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq); -UINT8 EXISP_LoadCode( - UINT8 ucFwIdx, - UINT8 is_calibration, - UINT8 *pIspFw, - UINT8 *pCalibOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq); -void EXISP_UpdateCalibResStart( - UINT8 ucFwIdx, - UINT8 *pIspFw, - ispFwHeaderInfo_t *pFwInfo, - ispLoadCodeRet_t *pLoadCodeRet, - UINT8 ucCaliOpt, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq); -UINT8 EXISP_UpdateCalibRes( - UINT8 idx, - UINT8 *pIspFw, - ispFwHeaderInfo_t *pFwInfo, - UINT8 *p3acali, - UINT8 *pLsc, - UINT8 *pLscdq); -UINT8 EXISP_ResCheck(UINT8 idx, UINT8 *p3acali, UINT8 *pLsc, UINT8 *Lscdq); -UINT8 EXISP_ResNumGet(UINT32 *resNum, UINT8 *pIspFw); -UINT8 EXISP_SPIDataWrite(UINT8 ucSPIMode, UINT8 *ucStartAddr, UINT32 ulTransByteCnt, UINT32 ulDmaAddr); -UINT8 EXISP_7002SPICfg(UINT8 ucSPIMode, UINT32 ulDmaAddr, UINT32 ulTransByteCnt); -UINT8 EXISP_PvSizeSet(UINT8 ucResolutionIdx); -UINT8 EXISP_ImageCapSet(UINT8 ucImageCapIdx); -UINT8 EXISP_TAFTAEROISet( - UINT8 ucTrg, - UINT16 usTAFSize, - UINT16 usTAFX, - UINT16 usTAFY, - UINT16 usTAESize, - UINT16 usTAEX, - UINT16 usTAEY); -UINT8 EXISP_SwitchRAWFormatSet(void); -UINT8 EXISP_ExifInfoGet( - UINT8 *ucExpTimeNumerator, - UINT32 *ulExpTimeDenominator, - UINT8 *ucExpTimeCompensation, - UINT16 *usLensFocalLength, - UINT16 *usIsoInfo, - UINT8 *ucFlashInfo); - -#endif /* APP_I2C_LIB_ICATCH_H */ - diff --git a/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c b/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c deleted file mode 100755 index 0053acd99719..000000000000 --- a/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c +++ /dev/null @@ -1,1247 +0,0 @@ -#include "app_i2c_lib_icatch.h" -#include -#include -#include -#include "icatch7002_common.h" - -#define SPI_CMD_BYTE_READ 0x03 -#define SPI_CMD_RD_ID 0x9F -#define SPI_CMD_WRT_EN 0x06 -#define SPI_CMD_BYTE_PROG 0x02 -#define SPI_CMD_RD_STS 0x05 -#define SPI_CMD_BYTE_PROG_AAI 0xAD -#define SPI_CMD_WRT_STS_EN 0x50 -#define SPI_CMD_WRT_STS 0x01 -#define SPI_CMD_WRT_DIS 0x04 -#define SPI_CMD_ERASE_ALL 0xC7 -#define SPI_CMD_SECTOR_ERASE 0x20 -#define SPI_CMD_32KB_BLOCK_ERASE 0x52 -#define SPI_CMD_64KB_BLOCK_ERASE 0xD8 -#define WAIT_COUNT 100 - -#define I2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) -#define I2CDataRead(reg) icatch_sensor_read((reg)) -#define osMemAlloc(len) kzalloc((len), GFP_KERNEL); -#define osMemFree(pbuf) kfree(pbuf) -#define seqI2CDataRead(reg,buf) *((u8*)(buf))= icatch_sensor_read(reg) -#define seqI2CDataWrite(reg,buf) icatch_sensor_write((reg),(*(u8*)(buf))) - -#define hsI2CDataRead(reg) icatch_sensor_read((reg)) -#define hsI2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) - -#ifndef tmrUsDelay -#define tmrUsWait(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) -#endif -#define ros_thread_sleep(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) - - -//local declare -void I2C_SPIInit(void); -UINT32 I2C_SPIFlashReadId(void); -UINT32 BB_SerialFlashTypeCheck(UINT32 id,UINT32 *spiSize); -void BB_EraseSPIFlash(UINT32 type,UINT32 spiSize); -UINT32 I2C_SPISstFlashWrite(UINT32 addr,UINT32 pages,UINT8 *pbuf); -UINT32 I2C_SPIFlashWrite_DMA(UINT32 addr,UINT32 pages,UINT32 usage,UINT8 *pbuf); -UINT32 I2C_SPI64KBBlockErase(UINT32 address,UINT32 stFlag); -UINT32 I2C_SPI32KBBlockErase(UINT32 address,UINT32 stFlag); -UINT32 I2C_SPISectorErase(UINT32 address,UINT32 stFlag); - -static const UINT32 stSpiIdInfo[7][3] = -{ - /*Winbond*/ - {0x00EF3017,4096, 2048}, - {0x00EF3016,4096, 1024}, - {0x00EF3015,4096, 512}, - {0x00EF3014,4096, 256}, - {0x00EF5014,4096, 256}, - {0x00EF3013,4096, 128}, - {0x00EF5013,4096, 128}, - /*Fail*/ - {0x00000000,0,0}, -}; - -static const UINT32 sstSpiIdInfo[6][3] = -{ - /*ESMT*/ - {0x008C4016,4096,512}, - /*SST*/ - {0x00BF254A,4096,1024}, - {0x00BF2541,4096,512}, - {0x00BF258E,4096,256}, - {0x00BF258D,4096,128}, - /*Fail*/ - {0x00000000,0,0}, -}; - -/* BB_WrSPIFlash ¬° main function for burning SPI */ -UINT32 I2C_SPIStChipErase( - void -); - -void -BB_WrSPIFlash( - UINT32 size -) -{ - UINT32 id, type; - UINT32 pages, spiSize; - - UINT32 fd, fileSize; - UINT8* pbootBuf = NULL; - const struct firmware *fw = NULL; - - printk("loadcode from file\n"); - /*#define FILE_PATH_BOOTCODE "D:\\FPGA.IME"*/ - //#define FILE_PATH_BOOTCODE "D:\\DCIM\\BOOT.BIN" - - //fd = sp5kFsFileOpen( FILE_PATH_BOOTCODE, SP5K_FS_OPEN_RDONLY ); - #if 0 - if( icatch_request_firmware(&fw) !=0){ - printk("%s:%d,requst firmware failed!!\n",__func__,__LINE__); - goto out; - } - #endif - I2CDataWrite(0x70c4,0x00); - I2CDataWrite(0x70c5,0x00); - - I2CDataWrite(0x1011,0x01); /* CPU Reset */ - I2CDataWrite(0x001C,0x08);/* FM reset */ - I2CDataWrite(0x001C,0x00); - I2CDataWrite(0x108C,0x00);/* DMA select */ - I2CDataWrite(0x009a,0x00);/*CPU normal operation */ -#if 0 - if(fd != 0) - { - fileSize = sp5kFsFileSizeGet(fd); - printk("fileSize:0x%x\n",fileSize); - pbootBuf= (UINT8*)sp5kMalloc(fileSize); - sp5kFsFileRead(fd, pbootBuf, fileSize); - printk("pbootBuf:0x%x\n",pbootBuf); - fsFileClose(fd); - } - else - { - printk("file open error\n"); - return; - } -#endif - fileSize = fw->data; - pbootBuf = fw->size; - if(pbootBuf == NULL) - { - printk("buffer allocate failed\n"); - goto out; - } - - I2C_SPIInit(); - - id = I2C_SPIFlashReadId(); - if(id==0) - { - printk("read id failed\n"); - goto out; - } - /*printk("spiSize:0x%x\n",&spiSize);*/ - type = BB_SerialFlashTypeCheck(id, &spiSize); - if( type == 0 ) - { - printk("read id failed\n"); - goto out; - } - - if( size > 0 && size < fileSize ) - { - pages = size/0x100; - if((size%0x100)!=0) - pages += 1; - } - else - { - pages = fileSize/0x100; - } - /*printk("pages:0x%x\n",pages);*/ - - //BB_EraseSPIFlash(type,spiSize); - I2C_SPIStChipErase(); - msleep(4*1000); - if( type == 2 ) - { - printk("SST operation\n"); - I2C_SPISstFlashWrite(0,pages,pbootBuf); - } - else if( type == 1 || type == 3 ) - { - printk("ST operation\n"); - I2C_SPIFlashWrite_DMA(0,pages,1,pbootBuf); - } -out: - if(fw) - icatch_release_firmware(fw); - return; - -// osMemFree(pbootBuf); -} - -UINT32 -BB_SerialFlashTypeCheck( - UINT32 id, - UINT32 *spiSize -) -{ - UINT32 i=0; - UINT32 fullID = 1; - UINT32 shift = 0, tblId, type = 0; - /*printk("id:0x%x spiSize:0x%x\n",id,spiSize);*/ - /* check whether SST type serial flash */ - while( 1 ){ - tblId = sstSpiIdInfo[i][0] >> shift; - if( id == tblId ) { - printk("SST type serial flash:%x %x %x\n",i,id,sstSpiIdInfo[i][0]); - type = 2; - *spiSize = sstSpiIdInfo[i][1]*sstSpiIdInfo[i][2]; - break; - } - if( id == 0x00FFFFFF || id == 0x00000000) { - return 0; - } - if( sstSpiIdInfo[i][0] == 0x00000000 ) { - #if 0 - if( fullID ){ - fullID = 0;/* sarch partial ID */ - i = 0; - shift = 16; - id = id >> shift; - continue; - } - #endif - type = 3; - break; - } - i ++; - } - if( type == 2 ) - return type; - - i = 0; - /* check whether ST type serial flash */ - while( 1 ){ - tblId = stSpiIdInfo[i][0] >> shift; - if( id == tblId ) { - printk("ST Type serial flash:%x %x %x\n",i,id,stSpiIdInfo[i][0]); - type = 1; - *spiSize = stSpiIdInfo[i][1]*stSpiIdInfo[i][2]; - /*printk("spiSize:0x%x\n",*spiSize);*/ - break; - } - if( id == 0x00FFFFFF || id == 0x00000000) { - return 0; - } - if( stSpiIdInfo[i][0] == 0x00000000 ) { - if( fullID ){ - fullID = 0;/* sarch partial ID */ - i = 0; - shift = 16; - id = id >> shift; - continue; - } - type = 3; - break; - } - i ++; - } - - return type; -} - -void -BB_EraseSPIFlash( - UINT32 type, - UINT32 spiSize -) -{ - UINT8 typeFlag; - UINT32 i, temp1; - if( type == 2 )/* SST */ - { - typeFlag = 0; - } - else if( type == 1 || type == 3 )/* ST */ - { - typeFlag = 1; - } - /*printk("spiSize:0x%x\n",spiSize);*/ - if(spiSize == (512*1024)) - { - /* skip 0x7B000 ~ 0x7EFF, to keep calibration data */ - temp1 = (spiSize / 0x10000)-1; - for(i=0;i 4.8us */ { - break; - } - time ++; - if( *ptimeOut < time ) { - printk("TimeOut %d, sts=0x%x, poll=0x%x\n",time,sts,poll); - break; - } - } -} - -UINT32 I2C_SPIStChipErase( - void -) -{ - UINT32 timeout; - printk("ST Chip Erasing...\n"); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); - I2C_SPIFlashPortWrite(0x02); - hsI2CDataWrite(0x40e7,0x01); - - I2C_SPIFlashWrEnable(); - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_ERASE_ALL); - hsI2CDataWrite(0x40e7,0x01); - - timeout = 0xffffffff; - I2C_SPITimeOutWait(0x01, &timeout); - ros_thread_sleep(1); - hsI2CDataWrite(0x40e7,0x01); - return SUCCESS; -} - - -UINT32 I2C_SPISstChipErase( - void -) -{ - UINT32 timeout; - printk("SST Chip Erasing...\n"); - - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ - hsI2CDataWrite(0x40e7,0x01); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); - I2C_SPIFlashPortWrite(0x02); - hsI2CDataWrite(0x40e7,0x01); - - I2C_SPIFlashWrEnable(); - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_ERASE_ALL); - hsI2CDataWrite(0x40e7,0x01); - - timeout = 0xffffffff; - I2C_SPITimeOutWait(0x01, &timeout); - - return SUCCESS; -} - -UINT32 I2C_SPISectorErase( - UINT32 address, - UINT32 stFlag -) -{ - UINT32 timeout; - printk("addr:0x%x\n",address); - if(!stFlag) - { - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ - hsI2CDataWrite(0x40e7,0x01); - } - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ - I2C_SPIFlashPortWrite(0x02); - hsI2CDataWrite(0x40e7,0x01); - - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_SECTOR_ERASE); - I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ - I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ - I2C_SPIFlashPortWrite(address); /* A07~A00 */ - hsI2CDataWrite(0x40e7,0x01); - - timeout = 5000000; - I2C_SPITimeOutWait(0x01, &timeout); - - return SUCCESS; -} - -UINT32 I2C_SPI32KBBlockErase( - UINT32 address, - UINT32 stFlag -) -{ - UINT32 timeout; - printk("addr:0x%x\n",address); - if(!stFlag) - { - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ - hsI2CDataWrite(0x40e7,0x01); - } - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ - I2C_SPIFlashPortWrite(0x02); - hsI2CDataWrite(0x40e7,0x01); - - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_32KB_BLOCK_ERASE); - I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ - I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ - I2C_SPIFlashPortWrite(address); /* A07~A00 */ - hsI2CDataWrite(0x40e7,0x01); - - timeout = 5000000; - I2C_SPITimeOutWait(0x01, &timeout); - - return SUCCESS; -} - -UINT32 I2C_SPI64KBBlockErase( - UINT32 address, - UINT32 stFlag -) -{ - UINT32 timeout; - printk("addr:0x%x\n",address); - if(!stFlag) - { - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ - hsI2CDataWrite(0x40e7,0x01); - } - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ - I2C_SPIFlashPortWrite(0x02); - hsI2CDataWrite(0x40e7,0x01); - - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_64KB_BLOCK_ERASE); - I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ - I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ - I2C_SPIFlashPortWrite(address); /* A07~A00 */ - hsI2CDataWrite(0x40e7,0x01); - - timeout = 5000000; - I2C_SPITimeOutWait(0x01, &timeout); - - return SUCCESS; -} - - -/*------------------------------------------------------------------------- - * File Name : I2C_SPIFlashWrite - * addr: SPI flash starting address - pages: pages size for data -> datasize = pages * pagesize(0x100) - pbuf: data buffer - * return SUCCESS: normal finish - FAIL: write failed - *------------------------------------------------------------------------*/ -UINT32 I2C_SPIFlashWrite( - UINT32 addr, - UINT32 pages, - UINT8 *pbuf -) -{ - UINT32 i, err = SUCCESS; - UINT32 pageSize = 0x100; - UINT32 timeout = 100000; - UINT32 rsvSec1, rsvSec2; - - rsvSec1 = pages*pageSize - 0x5000; - rsvSec2 = pages*pageSize - 0x1000; - addr = addr * pageSize; - - printk("ST type writing...\n"); - while( pages ) { - if((pages%0x40)==0)printk("page:0x%x\n",pages); - if((addr>=rsvSec1) && (addr > 16)); /* Send 3 bytes address*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); - I2C_SPIFlashPortWrite((UINT8)(addr)); - - for (i = 0; i < pageSize ; i++) { - I2C_SPIFlashPortWrite(*pbuf); - pbuf++; - } - hsI2CDataWrite(0x40e7,0x01); - addr += pageSize; - pages --; - tmrUsWait(400); - } - - return err; -} - -void I2C_SPISstStatusWrite(UINT8 dat) -{ - UINT32 timeout, poll; - - I2C_SPIFlashWrEnable(); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); - hsI2CDataWrite(0x40e7,0x01); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); - I2C_SPIFlashPortWrite(dat); - hsI2CDataWrite(0x40e7,0x01); - - poll = 0x01; - - timeout = 100000; - I2C_SPITimeOutWait(poll, &timeout); - return; -} - -void I2C_SPIStStatusWrite( - UINT8 value, - UINT8 value2 -) -{ - I2C_SPIFlashWrEnable(); - - #if 1 - hsI2CDataWrite(0x40e7,0x00); - //has not implement spi related interface,zyc -// halSpiPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ -// halSpiPortWrite(value); -// halSpiPortWrite(value2); - hsI2CDataWrite(0x40e7,0x01); - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(0x04); - hsI2CDataWrite(0x40e7,0x01); - #endif -} - -UINT32 I2C_SPISstFlashWrite( - UINT32 addr, - UINT32 pages, - UINT8 *pbuf -) -{ - UINT32 i, err = SUCCESS; - UINT32 pageSize = 0x100; - UINT32 timeout = 100000; - - addr = addr * pageSize; - - printk("SST type writing...\n"); - I2C_SPISstStatusWrite(0x40); - while( pages ) { - printk("page:0x%x\n",pages); - if((addr>=0x7C000) && (addr <0x7F000)) - { - addr += 0x1000; - pages -= 0x10; - continue; - } - I2C_SPIFlashWrEnable(); - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_BYTE_PROG_AAI); /* Write one byte command*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); - I2C_SPIFlashPortWrite((UINT8)(addr)); - I2C_SPIFlashPortWrite(*pbuf); - pbuf++; - I2C_SPIFlashPortWrite(*pbuf); - pbuf++; - hsI2CDataWrite(0x40e7,0x01); - timeout = 100000; - I2C_SPITimeOutWait(0x01,&timeout); - - for (i = 2; i < pageSize ; i = i+2) { - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_BYTE_PROG_AAI); - I2C_SPIFlashPortWrite(*pbuf); - pbuf++; - I2C_SPIFlashPortWrite(*pbuf); - pbuf++; - hsI2CDataWrite(0x40e7,0x01); - timeout = 100000; - I2C_SPITimeOutWait(0x01,&timeout); - } - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_DIS); - hsI2CDataWrite(0x40e7,0x01); - - addr += pageSize; - pages --; - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_WRT_DIS); - hsI2CDataWrite(0x40e7,0x01); - } - - return err; -} - - -/*------------------------------------------------------------------------- - * File Name : I2C_SPIFlashRead - * addr: SPI flash starting address - pages: pages size for data -> datasize = pages * pagesize(0x100) - pbuf: data buffer - * return SUCCESS: normal finish - FAIL: read failed - *------------------------------------------------------------------------*/ -UINT32 I2C_SPIFlashRead( - UINT32 addr, - UINT32 pages, - UINT8 *pbuf -) -{ - UINT8* pbufR; - UINT32 ch, err = SUCCESS; - UINT32 i, ret, count=0, size=0, bytes, offset; - UINT32 pageSize = 0x100; - - - addr = addr * pageSize; - size = pages*pageSize; - - I2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_BYTE_READ); /* Write one byte command*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); - I2C_SPIFlashPortWrite((UINT8)(addr)); - - for (i = 0; i < size ; i++) { - *pbuf = I2C_SPIFlashPortRead(); - if((i%256)==0) - printk("page:0x%x\n",(i/256)); - pbuf ++; - } - - I2CDataWrite(0x40e7,0x01); - - return err; -} - -UINT32 I2C_7002DmemWr( - UINT32 bankNum, - UINT32 byteNum, - UINT8* pbuf -) -{ - UINT32 i, bank; - - bank = 0x40+bankNum; - I2CDataWrite(0x10A6,bank); - - //for(i=0;i=rsvSec2) || (i =0x10000) - { - chk1 -= 0x10000; - } - } - - while( pages ) { - if((pages%0x40)==0) - { - printk("page:0x%x",pages); - } - if((addr>=rsvSec1) && (addr > 16)); /* Send 3 bytes address*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); - I2C_SPIFlashPortWrite((UINT8)(addr)); - - I2CDataWrite(0x4160,0x01); - count = 30; - pbuf += pageSize; - addr += pageSize; - pages --; - while( hsI2CDataRead(0x4003) == 0 ) - { - count--; - tmrUsWait(200);/* wait for DMA done */ - if( count == 0 ) - { - printk("DMA time out: %2x, 0x%2x%2x, %2x\n",pages, - hsI2CDataRead(0x4179),hsI2CDataRead(0x4178),hsI2CDataRead(0x40E6)); - hsI2CDataWrite(0x4011,0x10); - hsI2CDataWrite(0x1010,0x02); - pbuf -= pageSize; - addr -= pageSize; - pages ++; - hsI2CDataWrite(0x1010,0x00); - break; - } - } - hsI2CDataWrite(0x4003, 0x02); - I2CDataWrite(0x40e7,0x01); - } - - tmrUsWait(500);/* wait for DMA done */ - - temp = hsI2CDataRead(0x4285); - chk2 = hsI2CDataRead(0x4284); - chk2 = chk2 | (temp<<8); - printk("checksum: 0x%x 0x%x\n",chk1,chk2); - - return err; -} - -UINT32 I2C_7002DmemRd( - UINT32 bankNum, - UINT32 byteNum, - UINT8* pbuf -) -{ - UINT32 i, bank; - - bank = 0x40+bankNum; - hsI2CDataWrite(0x10A6,bank); - - //for(i=0;i pageSize ) - { - tempSize = 0x100; - size -= tempSize; - } - else - { - tempSize = size; - size = 0; - } - - hsI2CDataWrite(0x40e7,0x00); - I2C_SPIFlashPortWrite(SPI_CMD_BYTE_READ); /* Write one byte command*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ - I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); - I2C_SPIFlashPortWrite((UINT8)(addr)); - - if( ((size/0x100)%0x40)==0x00 ) - { - printk("RE:0x%x\n",((size/0x100)%0x40)); - } - dmemBank = count % 2; - hsI2CDataWrite(0x1081,dmemBank*0x20); - hsI2CDataWrite(0x1084,(1<>4)<<4; - UINT32 resLscDqSize = ((13276+15)>>4)<<4; -#else /* for 8M sensor IMX175 */ - UINT32 resOffset = 0x5000; - UINT32 res3acaliSize = 528; - UINT32 resLscSize = ((2292+15)>>4)<<4; - UINT32 resLscDqSize = ((8521+15)>>4)<<4; -#endif - - UINT32 startSector, finalSector, sectorCount; - - UINT8* pBuf; - - if( resId > 0x02 ) - { - printk(" ID ERROR \n"); - return FAIL; - } - - I2C_SPIInit(); - - spiId = I2C_SPIFlashReadId(); - if( spiId == 0 ) - { - printk("read id failed\n"); - return FAIL; - } - /*printk("spiSize:0x%x\n",&spiSize);*/ - spiType = BB_SerialFlashTypeCheck(spiId, &spiSize); - - if( resId == 0x00 )/* 3ACALI.BIN */ - { - resStartAddr = spiSize - resOffset; - resEndAddr = resStartAddr + res3acaliSize; - resSize = res3acaliSize; - } - else if( resId == 0x01 )/* LSC.BIN */ - { - resStartAddr = spiSize - resOffset + res3acaliSize; - resEndAddr = resStartAddr + resLscSize; - resSize = resLscSize; - } - else /* LSC_DQ.BIN */ - { - resStartAddr = spiSize -resOffset + res3acaliSize + resLscSize; - resEndAddr = resStartAddr + resLscDqSize; - resSize = resLscDqSize; - } - printk("%x %x %x\n", resStartAddr, resEndAddr, resSize); - - startSector = (resStartAddr/sectorSize)*sectorSize; - finalSector = (resEndAddr/sectorSize)*sectorSize; - sectorCount = ((finalSector - startSector)/sectorSize) + 1; - residue = resStartAddr - startSector; - - pBuf = osMemAlloc( sectorCount * sectorSize ); - printk("%x %x %x %x\n", startSector, finalSector, sectorCount, residue); - - I2C_SPIFlashRead_DMA(startSector,(sectorCount*sectorSize),pBuf); - - memcpy((pBuf+residue), resBuf, resSize); - - if( spiType == 2 ) - { - for( i=0; i 0x02 ) - { - printk(" ID ERROR \n"); - return FAIL; - } - - I2C_SPIInit(); - - spiId = I2C_SPIFlashReadId(); - if( spiId == 0 ) - { - printk("read id failed\n"); - return FAIL; - } - /*printk("spiSize:0x%x\n",&spiSize);*/ - spiType = BB_SerialFlashTypeCheck(spiId, &spiSize); - - if( resId == 0x00 )/* 3ACALI.BIN */ - { - resStartAddr = spiSize - resOffset; - resSize = res3acaliSize; - } - else if( resId == 0x01 )/* LSC.BIN */ - { - resStartAddr = spiSize - resOffset + (((res3acaliSize+0x0f)>>4)<<4); - resSize = resLscSize; - } - else /* LSC_DQ.BIN */ - { - resStartAddr = spiSize -resOffset + (((res3acaliSize+0x0f)>>4)<<4) - + (((resLscSize+0x0f)>>4)<<4); - resSize = resLscDqSize; - } - /*printk("%x %x\n", resStartAddr, resSize);*/ - - /* buffer used to stored calibration data */ - pBuf = osMemAlloc( resSize ); - printk("pBuf resSize:%x %x\n", pBuf, resSize); - - I2C_SPIFlashRead_DMA(resStartAddr,resSize,pBuf); - *bufAddr = pBuf; - printk("pBuf resSize:%x %x\n", (*bufAddr), resSize); - - *size = resSize; - - return SUCCESS; -} diff --git a/drivers/media/video/icatch7002/icatch7002_common.c b/drivers/media/video/icatch7002/icatch7002_common.c deleted file mode 100755 index 217a309b2ca3..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_common.c +++ /dev/null @@ -1,2582 +0,0 @@ -#define __ICATCH7002_COMMON_CFILE__ -#include "icatch7002_common.h" -#include -#include - -#define CONFIG_SENSOR_I2C_SPEED 300000 /* Hz */ -/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */ -#define CONFIG_SENSOR_I2C_NOSCHED 0 -#define CONFIG_SENSOR_I2C_RDWRCHK 0 -#define SENSOR_NAME_STRING() sensor->dev_name - - -#define ICATCHFWNAME "icatch7002boot.bin" - -u8 g_Calibration_Option_Def = 0xff; -bool IsZSL = FALSE; - -#ifdef CALIBRATION_MODE_FUN -struct icatch_cali_fw_data { - const char * const fname_option; - struct firmware const*fw_option; - const char * const fname_3acali; - struct firmware const*fw_3acali; - const char * const fname_lsc; - struct firmware const*fw_lsc; - const char * const fname_lscdq; - struct firmware const*fw_lscdq; -}; - -struct icatch_cali_fw_data g_cali_fw_data_front = { - .fname_option = "icatch7002/calibration_option.BIN", - .fname_3acali = "icatch7002/3ACALI_F.BIN", - .fname_lsc = "icatch7002/LSC_F.BIN", - .fname_lscdq = "icatch7002/LSC_DQ_F.BIN", -}; - -struct icatch_cali_fw_data g_cali_fw_data_back = { - .fname_option = "icatch7002/calibration_option.BIN", - .fname_3acali = "icatch7002/3ACALI.BIN", - .fname_lsc = "icatch7002/LSC.BIN", - .fname_lscdq = "icatch7002/LSC_DQ.BIN", -}; -#endif - -#define ICATCH_BOOT_FROM_SPI 0 -#define ICATCH_BOOT_FROM_HOST 1 -#define ICATCH_BOOT ICATCH_BOOT_FROM_HOST -#define ASUS_CAMERA_SUPPORT 1 - -#ifndef FAIL -#define FAIL 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#if 1 - -static struct rk_sensor_reg rs_reset_data[]={ - {0x1011,0x01}, - {0x001c,0x08}, - {0x001c,0x00}, - {0x1010,0x02}, - {0x1010,0x00}, - {0x1306,0x00},//0 rear,1 front - {0x1011,0x00}, - SensorEnd -}; - -static struct rk_sensor_reg fs_reset_data[]={ - {0x1011,0x01}, - {0x001c,0x08}, - {0x001c,0x00}, - {0x1010,0x02}, - {0x1010,0x00}, - {0x1306,0x01},//0 rear,1 front - {0x1011,0x00}, - SensorEnd -}; - -static struct rk_sensor_reg init_data[]={ - {SP7K_MSG_COLOR_EFFECT, 0x0}, // normal - {SP7K_MSG_EV_COMPENSATION, 0x6}, // 0 - {SP7K_MSG_FLASH_MODE, 0x1}, // off - {SP7K_MSG_FOCUS_MODE, 0x0}, // auto - {SP7K_MSG_PV_SIZE, 0x0}, // 1280*960 - {SP7K_MSG_SCENE_MODE, 0x0}, // normal - {SP7K_MSG_WHITE_BALANCE, 0x0}, // auto - {SP7K_MSG_CAP_ISO, 0x0}, //auto - {SP7K_MSG_AURA_COLOR_INDEX, 0x0}, // disable - {SP7K_MSG_PV_CAP_MODE, 0x4}, // idle - SensorEnd -}; -#endif - -struct i2c_client *g_icatch_i2c_client = NULL; -#if CONFIG_SENSOR_WhiteBalance -static int icatch_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - u8 set_val = 0; - struct generic_sensor*sensor = to_generic_sensor(client); - - DEBUG_TRACE("%s: value = %d\n", __FUNCTION__, value); - - if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) - { - switch(value){ - case 0: //enable auto - set_val = 0x0; - break; - case 1: //incandescent Tungsten - set_val = 0x6; - break; - case 2: //fluorescent - set_val = 0x5; - break; - case 3: //daylight - set_val = 0x1; - break; - case 4: //cloudy-daylight - set_val = 0x2; - break; - default: - break; - } - //awb - EXISP_I2C_WhiteBalanceSet(set_val); - return 0; - } - DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); - return -1; -} -#endif - -#if CONFIG_SENSOR_Effect -static int icatch_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value, int auravalue) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - u8 set_val = 0; - struct generic_sensor*sensor = to_generic_sensor(client); - DEBUG_TRACE("set effect,value = %d ......\n",value); - if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) - { - switch(value){ - case 0: //normal - case 5: //none - set_val = 0x00; - break; - case 1: //aqua - set_val = 0x01; - break; - case 2: //negative - set_val = 0x02; - break; - case 3: //sepia - set_val = 0x03; - break; - case 4: //mono Grayscale - set_val = 0x04; - break; - case 6: //aura - set_val = 0x06; - break; - case 7: //vintage - set_val = 0x07; - break; - case 8: //vintage2 - set_val = 0x08; - break; - case 9: //lomo - set_val = 0x09; - break; - case 10: //red - set_val = 0x0A; - break; - case 11: //blue - set_val = 0x0B; - break; - case 12: //green - set_val = 0x0C; - break; - default: - set_val = value; - break; - } - EXISP_I2C_ColorEffectSet(set_val); - if(set_val == 6){ - EXISP_I2C_AuraColorIndexSet(auravalue); - } - return 0; - } - DEBUG_TRACE("\n%s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); - return -1; -} -#endif - -#if CONFIG_SENSOR_Scene -static int icatch_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - u8 set_val = 0; - struct generic_sensor*sensor = to_generic_sensor(client); -//when scene mod is working , face deteciton and awb and iso are not recomemnded. - if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) - { - switch(value){ - case 0: //normal - set_val = 0x00; - break; - case 1: //auto - set_val = 0x00; - break; - case 2: //landscape - set_val = 0x10; - break; - case 3: //night - set_val = 0x07; - break; - case 4: //night_portrait - set_val = 0x08; - break; - case 5: //snow - set_val = 0x0B; - break; - case 6: //sports - set_val = 0x0C; - break; - case 7: //candlelight - set_val = 0x04; - break; - - default: - break; - } - - EXISP_I2C_SceneModeSet(set_val); - DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); - return 0; - } - DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); - return -EINVAL; -} -#endif - - -#if CONFIG_SENSOR_Exposure -static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - u8 set_val = 0x0; - struct generic_sensor*sensor = to_generic_sensor(client); - if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) - { - set_val = 6 - value; - EXISP_I2C_EvSet(set_val); - DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); - return 0; - } - DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); - return -EINVAL; -} -#endif - -#if CONFIG_SENSOR_Mirror -static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - return 0; -} -#endif - -#if CONFIG_SENSOR_Flip -//off 0x00;mirror 0x01,flip 0x10; -static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - return 0; - -} -#endif - -#if CONFIG_SENSOR_ISO -static int sensor_set_iso(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - u8 set_val = 0x0; - struct generic_sensor*sensor = to_generic_sensor(client); - if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) - { - set_val = value; - EXISP_I2C_ISOSet(set_val); - DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); - return 0; - } - DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); - return -EINVAL; -} -#endif -void __dump_i2c(UINT16 addr_s, UINT16 addr_e); -static void sensor_interrupt_wait_clear() -{ - int loop_cnt = 0; - - printk("sensor_interrupt_wait_clear() Entry\n"); - while((icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0) & 0x04) == 0){ - msleep(10); - if(loop_cnt++ == 100){ - __dump_i2c(0x7200,0x727F); - __dump_i2c(0x7072,0x7075); - __dump_i2c(0x72F8,0x72F8); - __dump_i2c(0x7005,0x7006); - } - } - icatch_sensor_write(SP7K_RDREG_INT_STS_REG_0,(icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0)|0x04)); - printk("sensor_interrupt_wait_clear() Exit\n"); -} - -#if CONFIG_SENSOR_Wdr -// EXISP_I2C_IspFuncSet(), bit 0 : DWDR -static void sensor_set_wdr(bool Enable) -{ - if(Enable){ - EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) | 0x01); - }else{ - EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) &~0x01); - } -} -#endif - -#if CONFIG_SENSOR_EDGE -static void sensor_set_edge(bool Enable) -{ - if(Enable){ - EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) | 0x02); - }else{ - EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) &~0x02); - } -} -#endif - - -static int icatch_sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) -{ - return 0; -} -static int icatch_sensor_resume(struct soc_camera_device *icd) -{ - return 0; - -} -static int icatch_sensor_set_bus_param(struct soc_camera_device *icd, - unsigned long flags) -{ - - return 0; -} - - -#if CALIBRATION_MODE_FUN -struct proc_dir_entry *g_icatch7002_proc_entry = NULL; -#define PROC_ENTRY_NAME SENSOR_NAME_STRING() -int g_is_calibrationMode = 0; -char g_procbuff[1024]; -union icatch_fw_version { - __u32 fw; - struct { - __u8 b1; - __u8 b2; - __u8 b3; - __u8 b4; - }; -} g_fw_version; -int icatch_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = 0; - if (off > 0) { - *eof = 1; - return 0; - } - - len = sprintf(page, "fw %02x.%02x.%02x\nis_calibration %d\n", - g_fw_version.b3, g_fw_version.b2, g_fw_version.b1, - g_is_calibrationMode); - return len; -} - -int icatch_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - char *ptr = NULL; - if (count >= sizeof(g_procbuff)) { - DEBUG_TRACE("%s no space\n", __FUNCTION__); - return -ENOSPC; - } - - if (copy_from_user(g_procbuff, buffer, count)) { - DEBUG_TRACE("%s copy from user fail %d\n", __FUNCTION__, count); - return -EFAULT; - } - g_procbuff[count] = 0; - - if ( (ptr = strstr(g_procbuff, "is_calibration")) == NULL) { - goto l_ret; - } - - ptr += strlen("is_calibration"); - while(*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r') { - ptr++; - } - - switch (*ptr) { - case '0': - g_is_calibrationMode = 0; - DEBUG_TRACE("%s disable calibration mode\n", __FUNCTION__); - break; - case '1': - g_is_calibrationMode = 1; - DEBUG_TRACE("%s enable calibration mode\n", __FUNCTION__); - break; - } - -l_ret: - return count; -} - -void icatch_create_proc_entry() -{ - struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); - - if (g_icatch7002_proc_entry == NULL) { - DEBUG_TRACE("%s need create_proc_entry\n", __FUNCTION__); - g_fw_version.fw = 0; - g_icatch7002_proc_entry = create_proc_entry(PROC_ENTRY_NAME, O_RDWR, NULL); - if (g_icatch7002_proc_entry) { - memset(g_procbuff, 0, sizeof(g_procbuff)); - g_icatch7002_proc_entry->read_proc = icatch_proc_read; - g_icatch7002_proc_entry->write_proc = icatch_proc_write; - } else { - DEBUG_TRACE("%s create_proc_entry fail\n", __FUNCTION__); - } - } -} - -void icatch_remove_proc_entry() -{ - struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); - if (g_icatch7002_proc_entry != NULL) { - remove_proc_entry(PROC_ENTRY_NAME, NULL); - g_icatch7002_proc_entry = NULL; - } -} -#endif - -#if 1//CONFIG_SENSOR_Focus - -void __dump_i2c(UINT16 addr_s, UINT16 addr_e) { - int size = (addr_e - addr_s + 1); - int i = 0; - int soffset = addr_s%16; - char buf[100] = {0}; - char lbuf[12]; - - for (i = 0; i < soffset; i++) { - if (i == 0) { - sprintf(lbuf, "%08X:", addr_s / 16 * 16); - strcat(buf, lbuf); - } - sprintf(lbuf, " "); - strcat(buf, lbuf); - } - - size += soffset; - i = soffset; - while( i < size) { - if ((i%16 == 0) && (i != 0)) { - printk("%s\n", buf); - } - if (i%16 == 0) { - buf[0] = 0; - sprintf(lbuf, "%08X:", (addr_s + i - soffset) / 16 * 16); - strcat(buf, lbuf); - } - sprintf(lbuf, " %02X", icatch_sensor_read(addr_s + i - soffset)); - strcat(buf, lbuf); - i++; - } - - printk("%s\n", buf); -} - -static void icatch_mapping_zone(const char * tag, struct rk_sensor_focus_zone *dst, const int *rect) -{ - DEBUG_TRACE("%s: %s set from (%d, %d), (%d, %d)\n", - __FUNCTION__, tag, - dst->lx, dst->ty, - dst->rx, dst->dy); - - dst->lx = ((rect[0] + 1000) * 1024)/2001; - dst->ty = ((rect[1] + 1000) * 1024)/2001; - dst->rx = ((rect[2] + 1000) * 1024)/2001; - dst->dy = ((rect[3] + 1000) * 1024)/2001; - - DEBUG_TRACE("%s: %s to (%d, %d), (%d, %d)\n", - __FUNCTION__, tag, - dst->lx, dst->ty, - dst->rx, dst->dy); -} - -//value: disable metering area -//force_set: if not set, it will not drive the sensor -// to set metering area really if focus is -// supported. -//rect: set to NULL if don't want to change. -static int icatch_set_metering_zone( - struct specific_sensor *sensor, - __s32 value, - rk_sensor_tae_zone zone, - int force_set) -{ - int ret = 0, w = 0, iret = 0; - - if ( sensor->isp_priv_info.MeteringAreas != value) { - DEBUG_TRACE("%s set metering areas to %d\n", - __FUNCTION__, - value); - } - - if (value == 0) { - if (sensor->isp_priv_info.MeteringAreas > 0) { - if ( EXISP_TAFTAEROISet( - TAFTAE_TAE_OFF, - 0,0,0,0,0,0 ) != SUCCESS) - { - ret = -EINVAL; - } - } - sensor->isp_priv_info.MeteringAreas = value; - return ret; - } - - sensor->isp_priv_info.MeteringAreas = value; - - if (force_set) { - goto f_set; - } - - if (sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_AUTO) || - sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_CONTINUOUS) || - sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_ABSOLUTE) ) { - return ret; - } - -f_set: - //set TAE if focus is not supported - - w = sensor->isp_priv_info.tae_zone.rx - sensor->isp_priv_info.tae_zone.lx; - if (w < 0) { - w = -w; - } - - DEBUG_TRACE("%s: set TAE zone to (%d, %d), (%d, %d)\n", - __FUNCTION__, - sensor->isp_priv_info.tae_zone.lx, - sensor->isp_priv_info.tae_zone.ty, - sensor->isp_priv_info.tae_zone.rx, - sensor->isp_priv_info.tae_zone.dy); - - if (w == 0) { - iret = EXISP_TAFTAEROISet(TAFTAE_TAE_ONLY, 0, 0, 0, 0x80, 0x1bf, 0x1bf); - } else { - iret = EXISP_TAFTAEROISet( - TAFTAE_TAE_ONLY, - 0, 0, 0, - w, - sensor->isp_priv_info.tae_zone.lx, - sensor->isp_priv_info.tae_zone.ty); - } - - if (iret != SUCCESS) { - ret = -EINVAL; - } - - return ret; -} - -int icatch_sensor_set_auto_focus(struct i2c_client *client, int value,int *tmp_zone) -{ - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - - //u8 zone_x = 0x0,zone_y = 0x0; // 0->0x0f - UINT16 w = 0; - int ret = 0; - int cnt = 100; - int set_val; - - ret = icatch_set_metering_zone( - sensor, - sensor->isp_priv_info.MeteringAreas, - sensor->isp_priv_info.tae_zone, - 1); - if (ret) { - return ret; - } - - if(value == WqCmd_af_single) - set_val = 0; - else if(value == WqCmd_af_update_zone){ - icatch_mapping_zone( - "focus zone", - &sensor->isp_priv_info.focus_zone, - tmp_zone); - return 0; - - }else if(value == WqCmd_af_continues) - set_val = 3; - else{ - DEBUG_TRACE("%s:focus value is invalidate!\n",__func__); - } - - EXISP_I2C_FocusModeSet(set_val); - - //EXISP_I2C_AFROITriggerSet(); - if (value != WqCmd_af_far_pos) { - //EXISP_I2C_ROISwitchSet(01); - //set the zone - DEBUG_TRACE("%s: lx = %d,rx = %d,ty = %d,dy = %d\n", __FUNCTION__, sensor->isp_priv_info.focus_zone.lx,sensor->isp_priv_info.focus_zone.rx,sensor->isp_priv_info.focus_zone.ty,sensor->isp_priv_info.focus_zone.dy); - w = sensor->isp_priv_info.focus_zone.rx - sensor->isp_priv_info.focus_zone.lx; - //zone_x = (sensor->isp_priv_info.focus_zone.lx << 4) | (sensor->isp_priv_info.focus_zone.rx & 0x0f); - //zone_y = (sensor->isp_priv_info.focus_zone.ty << 4) | (sensor->isp_priv_info.focus_zone.dy & 0x0f); - //auto focus - //sendI2cCmd(client, 0x0E, 0x00); - if( w != 0) { - EXISP_TAFTAEROISet( - TAFTAE_TAF_ONLY, - w, - sensor->isp_priv_info.focus_zone.lx, - sensor->isp_priv_info.focus_zone.ty, - 0, 0, 0); - DEBUG_TRACE("%s:auto focus, val = %d, w = 0x%x, x = 0x%x y = 0x%x\n",__func__,value, w, sensor->isp_priv_info.focus_zone.lx, sensor->isp_priv_info.focus_zone.ty); - }else{ - EXISP_TAFTAEROISet(TAFTAE_TAF_ONLY, 0x80, 0x1bf, 0x1bf, 0, 0, 0); - DEBUG_TRACE("%s:auto focus, all zero, val = %d, size=0x80, x=0x1bf, y=0x1bf\n",__func__,value); - } - } - - int staus_value = 0; - if(value == WqCmd_af_continues) - //staus_value = 0x10; - goto icatch_sensor_set_auto_focus_end; - else if(value == WqCmd_af_single) - staus_value = 0x0; - - - while (cnt--) { - if (EXISP_I2C_AFStatusGet() == staus_value) { - break; - } - msleep(30); - } - - //__dump_i2c(0x7200, 0x727f); - - if (cnt <= 0) { - DEBUG_TRACE("%s: focus timeout %d\n",__func__, value); - __dump_i2c(0x7200, 0x727f); - - __dump_i2c(0x7005, 0x7006); - return 1; - } - - if (EXISP_I2C_AFResultGet() != 0) { - DEBUG_TRACE("%s: focus fail %d\n",__func__, value); - return 1; - } -icatch_sensor_set_auto_focus_end: - DEBUG_TRACE("%s: focus success %d\n\n",__func__, value); - return 0; -} - - -#endif - -int icatch_sensor_init(struct i2c_client *client) -{ - struct soc_camera_device *icd = client->dev.platform_data; - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - // struct isp_data * sensor = spnsor->isp_priv_info; - struct v4l2_queryctrl* qctrl; - int pid = 0; - u8 sensorid = 0; - char* sensorid_str = NULL; - struct sensor_v4l2ctrl_info_s* qctrl_info; - - sensorid_str = strstr(dev_name(icd->pdev),"front"); - if(sensorid_str) - sensorid = 1; - else - sensorid = 0; - -#if CALIBRATION_MODE_FUN - if (g_is_calibrationMode == 1 ) { - if (sensorid == SENSOR_ID_REAR) - sensorid = SENSOR_ID_REAR_CALIBRATION; - - DEBUG_TRACE("%s CALIBRATION MODE is enable, SENSOR_ID:%d\n", __FUNCTION__, sensorid); - } - sensor->isp_priv_info.sensor_id = sensorid; -#endif - - DEBUG_TRACE("@@NY@@%s: %d\n", __FUNCTION__, sensorid); - sensor->isp_priv_info.curRes = -1; - sensor->isp_priv_info.curPreviewCapMode = IDLE_MODE; - sensor->isp_priv_info.had_setprvsize = 0; - sensor->isp_priv_info.hdr = false; - -#if CALIBRATION_MODE_FUN - sensor->isp_priv_info.rk_query_PreviewCapMode = IDLE_MODE; -#endif - g_icatch_i2c_client = client; - - -#if 0 - //get id check -{ - int count = 200; - while(count--){ - pid = icatch_sensor_read(0x0004); - DEBUG_TRACE("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid); - mdelay(1000); - } -} -#endif - - if(icatch_load_fw(icd,sensorid)<0){ - DEBUG_TRACE("icatch7002 load sensor %d firmware failed!!-->%s:%d\n",sensorid, __FUNCTION__, __LINE__); - return -ENODEV; - } -#if 0 - if(sensorid == SENSOR_ID_FRONT){ - // front camera - icatch_sensor_write_array((void*)fs_reset_data); - } - else{ - // rear camera - icatch_sensor_write_array((void*)rs_reset_data); - } - - //50Hz - EXISP_I2C_BandSelectionSet(0x01); - //DEBUG_TRACE("%s Set BandSelection to 50Hz\n", __FUNCTION__); - - //get id check - mdelay(100); - pid = EXISP_I2C_RearSensorIdGet(); - DEBUG_TRACE("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid); - if (pid != SENSOR_ID) { - DEBUG_TRACE("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid); - return -ENODEV; - } -#endif - - //50Hz - EXISP_I2C_BandSelectionSet(0x01); - /* sensor sensor information for initialization */ - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_DO_WHITE_BALANCE); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.whiteBalance = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_BRIGHTNESS); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.brightness = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EFFECT); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.effect = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EXPOSURE); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl){ - sensor->isp_priv_info.exposure = qctrl->default_value; - } - - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_SATURATION); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.saturation = qctrl->default_value; - - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_CONTRAST); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.contrast = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_HFLIP); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.mirror = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_VFLIP); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.flip = qctrl->default_value; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_SCENE); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl){ - sensor->isp_priv_info.scene = qctrl->default_value; - } -#if CONFIG_SENSOR_AntiBanding - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ANTIBANDING); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.antibanding = qctrl->default_value; -#endif -#if CONFIG_SENSOR_WhiteBalanceLock - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_WHITEBALANCE_LOCK); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.WhiteBalanceLock = qctrl->default_value; -#endif -#if CONFIG_SENSOR_ExposureLock - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EXPOSURE_LOCK); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.ExposureLock = qctrl->default_value; -#endif -#if CONFIG_SENSOR_MeteringAreas - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_METERING_AREAS); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.MeteringAreas = qctrl->default_value; -#endif -#if CONFIG_SENSOR_Wdr - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_WDR); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.Wdr = qctrl->default_value; -#endif -#if CONFIG_SENSOR_EDGE - sensor_set_edge(1); -#endif - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ZOOM_ABSOLUTE); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.digitalzoom = qctrl->default_value; - /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */ - //qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_AUTO); -#if 0 - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_FOCUS_AUTO); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.auto_focus = SENSOR_AF_AUTO; - - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_FACEDETECT); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.face = qctrl->default_value; -#endif -#if CONFIG_SENSOR_ISO - qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ISO); - if(qctrl_info) - qctrl = qctrl_info->qctrl; - if (qctrl) - sensor->isp_priv_info.iso = qctrl->default_value; -#endif - return 0; -} - - - -/* sensor register read */ -static int icatch_sensor_burst_read( u16 reg, u16 len, __u8 *buffer) -{ - struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); - - int err,cnt; - u8 buf[2]; - struct i2c_msg msg[2]; - struct i2c_client* client =g_icatch_i2c_client; - - buf[0] = reg >> 8; - buf[1] = reg & 0xFF; - - msg[0].addr = client->addr; - msg[0].flags = client->flags; - msg[0].buf = buf; - msg[0].len = sizeof(buf); - msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */ - msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */ - - msg[1].addr = client->addr; - msg[1].flags = client->flags|I2C_M_RD; - msg[1].buf = buffer; - msg[1].len = len; - msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */ - msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */ - - cnt = 3; - err = -EAGAIN; - while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */ - err = i2c_transfer(client->adapter, &msg[0], 1); - - if (err >= 0) { - break; - } else { - DEBUG_TRACE("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, buf[0]); - udelay(10); - } - } - - if(err <0) - return -FAIL; - - cnt = 3; - err = -EAGAIN; - while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */ - err = i2c_transfer(client->adapter, &msg[1], 1); - - if (err >= 0) { - break; - } else { - DEBUG_TRACE("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, buf[0]); - udelay(10); - } - } - if(err >=0) - return 0; - else - return -FAIL; -} - -struct icatch_dumpreg_dsc { - __u16 addr; - __u16 len; - unsigned long user_ptr; -}; - -static int icatch_dump_regs(void __user * arg) -{ - int err, ret = 0; - struct icatch_dumpreg_dsc dsc; - __u8 *buf = NULL; - - err = !access_ok(VERIFY_READ, - (void __user *)arg, sizeof(struct icatch_dumpreg_dsc)); - - if (err) { - DEBUG_TRACE("%s(%d) error to access argument\n", - __FUNCTION__, __LINE__); - return -EACCES; - } - - if (copy_from_user( - &dsc, arg, - sizeof(struct icatch_dumpreg_dsc))) { - return -EFAULT; - } - - if (dsc.len == 0) { - DEBUG_TRACE("%s length is 0\n", __FUNCTION__); - return -EINVAL; - } - - DEBUG_TRACE("%s add=0x%04x len=%d\n", - __FUNCTION__, - dsc.addr, dsc.len); - - if ( !access_ok(VERIFY_WRITE, - (void __user *)dsc.user_ptr, dsc.len)) { - DEBUG_TRACE("%s(%d) error to access user_ptr\n", - __FUNCTION__, __LINE__); - return -EACCES; - } - - buf = kmalloc( dsc.len, GFP_KERNEL); - if (buf == NULL) { - return -ENOMEM; - } - - //dump - ret = icatch_sensor_burst_read(dsc.addr, dsc.len, buf); - if (ret < 0) { - DEBUG_TRACE("%s(%d) error read these regs\n", - __FUNCTION__, __LINE__); - goto l_exit; - } - - - if (copy_to_user(dsc.user_ptr, buf, dsc.len)) { - DEBUG_TRACE("%s(%d) fail to copy to user_ptr\n", - __FUNCTION__, __LINE__); - ret = -EFAULT; - goto l_exit; - } - -l_exit: - if (buf != NULL) - kfree(buf); - DEBUG_TRACE("%s(%d) return value %d\n", - __FUNCTION__, __LINE__, - ret); - return ret; -} - -static int icatch_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl,struct v4l2_queryctrl *qctrl) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - int ret = 0; - - switch (ext_ctrl->id) - { - case V4L2_CID_SCENE: - { - ext_ctrl->value = sensor->isp_priv_info.scene; - break; - } -#if CONFIG_SENSOR_AntiBanding - case V4L2_CID_ANTIBANDING: - { - ext_ctrl->value = sensor->isp_priv_info.antibanding; - break; - } -#endif -#if CONFIG_SENSOR_WhiteBalanceLock - case V4L2_CID_WHITEBALANCE_LOCK: - { - ext_ctrl->value = sensor->isp_priv_info.WhiteBalanceLock; - break; - } -#endif -#if CONFIG_SENSOR_ExposureLock - case V4L2_CID_EXPOSURE_LOCK: - { - ext_ctrl->value = sensor->isp_priv_info.ExposureLock; - break; - } -#endif -#if CONFIG_SENSOR_MeteringAreas - case V4L2_CID_METERING_AREAS: - { - ext_ctrl->value = sensor->isp_priv_info.MeteringAreas; - break; - } -#endif -#if CONFIG_SENSOR_Wdr - case V4L2_CID_WDR: - { - ext_ctrl->value = sensor->isp_priv_info.Wdr; - break; - } -#endif -#if CONFIG_SENSOR_EDGE - case V4L2_CID_EDGE: - { - ext_ctrl->value = EXISP_I2C_CapEdgeInfoGet(); - break; - } -#endif - case V4L2_CID_EFFECT: - { - ext_ctrl->value = sensor->isp_priv_info.effect; - break; - } - case V4L2_CID_ZOOM_ABSOLUTE: - { - ext_ctrl->value = sensor->isp_priv_info.digitalzoom; - break; - } - case V4L2_CID_ZOOM_RELATIVE: - { - return -EINVAL; - } - case V4L2_CID_FOCUS_ABSOLUTE: - { - return -EINVAL; - } - case V4L2_CID_FOCUS_RELATIVE: - { - return -EINVAL; - } - case V4L2_CID_FLASH: - { - ext_ctrl->value = sensor->isp_priv_info.flash; - break; - } - case V4L2_CID_FACEDETECT: - { - ext_ctrl->value =sensor->isp_priv_info.face ; - break; - } -#if CONFIG_SENSOR_ISO - case V4L2_CID_ISO: - { - ext_ctrl->value = sensor->isp_priv_info.iso; - if(ext_ctrl->value == 0){ - ext_ctrl->value = icatch_sensor_read(SP7K_RDREG_ISO_H); - ext_ctrl->value <<= 8; - ext_ctrl->value |= icatch_sensor_read(SP7K_RDREG_ISO_L); - } - break; - } -#endif -#if CONFIG_SENSOR_JPEG_EXIF - case V4L2_CID_JPEG_EXIF: - { - RkExifInfo *pExitInfo = (RkExifInfo *)ext_ctrl->value; - - UINT8 ucExpTimeNumerator; - UINT32 ulExpTimeDenominator; - UINT8 ucExpTimeCompensation; - UINT16 usLensFocalLength; - UINT16 usIsoInfo; - UINT8 ucFlashInfo; - - EXISP_ExifInfoGet( - &ucExpTimeNumerator, - &ulExpTimeDenominator, - &ucExpTimeCompensation, - &usLensFocalLength, - &usIsoInfo, - &ucFlashInfo); - - pExitInfo->ExposureTime.num = ucExpTimeNumerator; - pExitInfo->ExposureTime.denom = ulExpTimeDenominator; - //pExitInfo->Flash = ucFlashInfo; - pExitInfo->ISOSpeedRatings = usIsoInfo; - pExitInfo->FocalPlaneYResolution.num = EXISP_I2C_CapEdgeInfoGet(); - pExitInfo->ExposureBiasValue.num = sensor->isp_priv_info.exposure ; - pExitInfo->ExposureBiasValue.denom = 3; - - break; - } -#endif - -#if CONFIG_SENSOR_DUMPREGS - case V4L2_CID_DUMPREGS: - { - //static long icatch_dump_regs(void __user * arg); - return icatch_dump_regs(ext_ctrl->string); - } -#endif - default : - ret = -1; - break; - } - return ret; -} - - -static int icatch_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl,struct v4l2_queryctrl *qctrl) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - int val_offset; - int ret = 0; - - val_offset = 0; - switch (ext_ctrl->id) - { -#if CONFIG_SENSOR_Scene - case V4L2_CID_SCENE: - { - if (ext_ctrl->value != sensor->isp_priv_info.scene) - { - if (icatch_set_scene(icd, qctrl,ext_ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.scene = ext_ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_AntiBanding - case V4L2_CID_ANTIBANDING: - { - if (ext_ctrl->value != sensor->isp_priv_info.antibanding) - { - if(ext_ctrl->value){ - EXISP_I2C_BandSelectionSet(2); //60Hz - }else{ - EXISP_I2C_BandSelectionSet(1); //50Hz - } - sensor->isp_priv_info.antibanding = ext_ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_WhiteBalanceLock - case V4L2_CID_WHITEBALANCE_LOCK: - { - if (ext_ctrl->value != sensor->isp_priv_info.WhiteBalanceLock) - { - if(ext_ctrl->value){ - EXISP_I2C_VendreqCmdSet(4); - }else{ - EXISP_I2C_VendreqCmdSet(6); - } - sensor->isp_priv_info.WhiteBalanceLock = ext_ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_ExposureLock - case V4L2_CID_EXPOSURE_LOCK: - { - if (ext_ctrl->value != sensor->isp_priv_info.ExposureLock) - { - if(ext_ctrl->value){ - EXISP_I2C_VendreqCmdSet(3); - }else{ - EXISP_I2C_VendreqCmdSet(5); - } - sensor->isp_priv_info.ExposureLock = ext_ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_MeteringAreas - case V4L2_CID_METERING_AREAS: - { - if (ext_ctrl->value) { - icatch_mapping_zone( - "metering zone", - &sensor->isp_priv_info.tae_zone, - ext_ctrl->rect); - } - ret = icatch_set_metering_zone( - sensor, - ext_ctrl->value, - sensor->isp_priv_info.tae_zone, - 0); - sensor->isp_priv_info.MeteringAreas = ext_ctrl->value; - break; - } -#endif -#if CONFIG_SENSOR_Wdr - case V4L2_CID_WDR: - { - if (ext_ctrl->value != sensor->isp_priv_info.Wdr) - { - sensor_set_wdr(ext_ctrl->value); - sensor->isp_priv_info.Wdr = ext_ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Effect - case V4L2_CID_EFFECT: - { - if (ext_ctrl->value != sensor->isp_priv_info.effect) - { - if (icatch_set_effect(icd, qctrl,ext_ctrl->value,ext_ctrl->rect[0]) != 0) - return -EINVAL; - sensor->isp_priv_info.effect= ext_ctrl->value; - } - if(sensor->isp_priv_info.effect == 6) - { - EXISP_I2C_AuraColorIndexSet(ext_ctrl->rect[0]); - } - break; - } -#endif -#if CONFIG_SENSOR_DigitalZoom - case V4L2_CID_ZOOM_ABSOLUTE: - { - DEBUG_TRACE("V4L2_CID_ZOOM_ABSOLUTE ...... ext_ctrl->value = %d\n",ext_ctrl->value); - if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum)){ - return -EINVAL; - } - - if (ext_ctrl->value != sensor->isp_priv_info.digitalzoom) - { - val_offset = ext_ctrl->value -sensor->isp_priv_info.digitalzoom; - - if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0) - return -EINVAL; - sensor->isp_priv_info.digitalzoom += val_offset; - - DEBUG_TRACE("%s digitalzoom is %x\n",sgensor->dev_name, sensor->isp_priv_info.digitalzoom); - } - - break; - } - case V4L2_CID_ZOOM_RELATIVE: - { - if (ext_ctrl->value) - { - if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.digitalzoom += ext_ctrl->value; - - DEBUG_TRACE("%s digitalzoom is %x\n", sgensor->dev_name, sensor->isp_priv_info.digitalzoom); - } - break; - } -#endif -#if CONFIG_SENSOR_Flash - case V4L2_CID_FLASH: - { - if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0) - return -EINVAL; - sensor->info_priv.flash = ext_ctrl->value; - - DEBUG_TRACE("%s flash is %x\n",sgensor->dev_name, sensor->isp_priv_info.flash); - break; - } -#endif -#if CONFIG_SENSOR_FACE_DETECT - case V4L2_CID_FACEDETECT: - { - if(sensor->isp_priv_info.face != ext_ctrl->value){ - if (sensor_set_face_detect(client, ext_ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.face = ext_ctrl->value; - DEBUG_TRACE("%s face value is %x\n",sgensor->dev_name, sensor->isp_priv_info.face); - } - break; - } -#endif -#if CONFIG_SENSOR_ISO - case V4L2_CID_ISO: - { - if (sensor->isp_priv_info.iso != ext_ctrl->value) { - if (sensor_set_iso(icd, qctrl, ext_ctrl->value) != 0) { - return -EINVAL; - } - sensor->isp_priv_info.iso = ext_ctrl->value; - DEBUG_TRACE("%s set ISO to %d\n", sgensor->dev_name, sensor->isp_priv_info.iso); - } - break; - } -#endif - default: - ret = -1; - break; - } - - return ret; -} - -static int icatch_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl,struct v4l2_queryctrl *qctrl) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - int ret = 0; - - - switch (ctrl->id) - { - case V4L2_CID_BRIGHTNESS: - { - ctrl->value = sensor->isp_priv_info.brightness; - break; - } - case V4L2_CID_SATURATION: - { - ctrl->value = sensor->isp_priv_info.saturation; - break; - } - case V4L2_CID_CONTRAST: - { - ctrl->value = sensor->isp_priv_info.contrast; - break; - } - case V4L2_CID_DO_WHITE_BALANCE: - { - ctrl->value = sensor->isp_priv_info.whiteBalance; - break; - } - case V4L2_CID_EXPOSURE: - { - ctrl->value = sensor->isp_priv_info.exposure; - break; - } - case V4L2_CID_HFLIP: - { - ctrl->value = sensor->isp_priv_info.mirror; - break; - } - case V4L2_CID_VFLIP: - { - ctrl->value = sensor->isp_priv_info.flip; - break; - } - case V4L2_CID_ZOOM_ABSOLUTE: - { - ctrl->value = sensor->isp_priv_info.digitalzoom; - break; - } - default : - ret = -1; - break; - } - return ret; -} - -static int icatch_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl,struct v4l2_queryctrl *qctrl) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - struct soc_camera_device *icd = client->dev.platform_data; - int ret = 0; - - switch (ctrl->id) - { -#if CONFIG_SENSOR_Brightness - case V4L2_CID_BRIGHTNESS: - { - if (ctrl->value != sensor->isp_priv_info.brightness) - { - if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0) - { - return -EINVAL; - } - sensor->isp_priv_info.brightness = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Exposure - case V4L2_CID_EXPOSURE: - { - if (ctrl->value != sensor->isp_priv_info.exposure) - { - if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0) - { - return -EINVAL; - } - sensor->isp_priv_info.exposure = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Saturation - case V4L2_CID_SATURATION: - { - if (ctrl->value != sensor->isp_priv_info.saturation) - { - if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0) - { - return -EINVAL; - } - sensor->isp_priv_info.saturation = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Contrast - case V4L2_CID_CONTRAST: - { - if (ctrl->value != sensor->isp_priv_info.contrast) - { - if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0) - { - return -EINVAL; - } - sensor->isp_priv_info.contrast = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_WhiteBalance - case V4L2_CID_DO_WHITE_BALANCE: - { - if (ctrl->value != sensor->isp_priv_info.whiteBalance) - { - if (icatch_set_whiteBalance(icd, qctrl,ctrl->value) != 0) - { - return -EINVAL; - } - sensor->isp_priv_info.whiteBalance = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Mirror - case V4L2_CID_HFLIP: - { - if (ctrl->value != sensor->isp_priv_info.mirror) - { - if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.mirror = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_Flip - case V4L2_CID_VFLIP: - { - if (ctrl->value != sensor->isp_priv_info.flip) - { - if (sensor_set_flip(icd, qctrl,ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.flip = ctrl->value; - } - break; - } -#endif -#if CONFIG_SENSOR_DigitalZoom - case V4L2_CID_ZOOM_ABSOLUTE: - { - int val_offset = 0; - DEBUG_TRACE("V4L2_CID_ZOOM_ABSOLUTE ...... ctrl->value = %d\n",ctrl->value); - if ((ctrl->value < qctrl->minimum) || (ctrl->value > qctrl->maximum)){ - return -EINVAL; - } - - if (ctrl->value != sensor->isp_priv_info.digitalzoom) - { - val_offset = ctrl->value -sensor->isp_priv_info.digitalzoom; - - if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0) - return -EINVAL; - sensor->isp_priv_info.digitalzoom += val_offset; - - DEBUG_TRACE("%s digitalzoom is %x\n",sgensor->dev_name, sensor->isp_priv_info.digitalzoom); - } - - break; - } - case V4L2_CID_ZOOM_RELATIVE: - { - if (ctrl->value) - { - if (sensor_set_digitalzoom(icd, qctrl,&ctrl->value) != 0) - return -EINVAL; - sensor->isp_priv_info.digitalzoom += ctrl->value; - - DEBUG_TRACE("%s digitalzoom is %x\n", sgensor->dev_name, sensor->isp_priv_info.digitalzoom); - } - break; - } -#endif - default: - ret = -1; - break; - } - - return ret; -} - -int sensor_set_get_control_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl,bool is_set) -{ - int ret = 0; - struct v4l2_control ctrl; - - if(is_set){ - // belong to ext_control ? - ret = icatch_s_ext_control(icd, ext_ctrl,ctrl_info->qctrl); - if(ret == 0){ - ctrl_info->cur_value = ext_ctrl->value; - goto sensor_set_get_control_cb_end; - } - // belong to control? - ctrl.id = ext_ctrl->id; - ctrl.value = ext_ctrl->value; - ret = icatch_s_control(soc_camera_to_subdev(icd), &ctrl,ctrl_info->qctrl); - if(ret == 0){ - ctrl_info->cur_value = ctrl.value; - goto sensor_set_get_control_cb_end; - } - - }else{ - // belong to ext_control ? - ret = icatch_g_ext_control(icd, ext_ctrl,ctrl_info->qctrl); - - if(ret == 0){ - ctrl_info->cur_value = ext_ctrl->value; - goto sensor_set_get_control_cb_end; - } - // belong to control? - ctrl.id = ext_ctrl->id; - ret = icatch_g_control(soc_camera_to_subdev(icd), &ctrl,ctrl_info->qctrl); - if(ret == 0){ - ctrl_info->cur_value = ctrl.value; - goto sensor_set_get_control_cb_end; - } - - } - -sensor_set_get_control_cb_end: - return ret; - - -} -static int sensor_hdr_exposure(struct i2c_client *client, unsigned int code) -{ - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - //printk("sensor_hdr_exposure_cb: %d %d\n",code,sensor->isp_priv_info.exposure); - switch (code) - { - case RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1: - { - //if( (sensor->isp_priv_info.exposure - 1 >= -6) && (sensor->isp_priv_info.exposure - 1 <= 6) ){ - // EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure - 1); - //} - printk("RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1\n"); - if(IsZSL){ - printk("EXISP_ImageCapSet(IMAGE_CAP_HDR)\n"); - EXISP_ImageCapSet(IMAGE_CAP_HDR); - sensor_interrupt_wait_clear(); - } - break; - } - - case RK_VIDEOBUF_HDR_EXPOSURE_NORMAL: - { - //EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure); - sensor->isp_priv_info.hdr = true; - break; - } - - case RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1: - { - //if( (sensor->isp_priv_info.exposure + 1 >= -6) && (sensor->isp_priv_info.exposure + 1 <= 6) ){ - // EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure + 1); - //} - break; - } - - case RK_VIDEOBUF_HDR_EXPOSURE_FINISH: - { - printk("HDR_EXPOSURE_FINISH\n"); - sensor->isp_priv_info.hdr = FALSE; - //EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure); - if(IsZSL){ - u8 res_sel = 0; - if(sensor->isp_priv_info.curRes == OUTPUT_QSXGA){ - res_sel = 0xA; - }else if(sensor->isp_priv_info.curRes == OUTPUT_QUADVGA){ - res_sel = 0; - } - printk("HDR_EXPOSURE_FINISH Switch resolution\n"); - EXISP_PvSizeSet(res_sel); - sensor_interrupt_wait_clear(); - } - break; - } - default: - break; - } - - return 0; -} - - long icatch_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - switch (cmd){ - case RK29_CAM_SUBDEV_HDR_EXPOSURE: - { - sensor_hdr_exposure(client,(unsigned int)arg); - break; - } - - default: - { - //SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd); - break; - } - } - - return 0; -} - - - - int icatch_s_fmt(struct i2c_client *client, struct v4l2_mbus_framefmt *mf,bool is_capture) -{ - const struct sensor_datafmt *fmt; - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - //const struct v4l2_queryctrl *qctrl; - //struct soc_camera_device *icd = client->dev.platform_data; - int ret=0; - int set_w,set_h; - int supported_size = sensor->isp_priv_info.outputSize; - int res_set = 0; - u8 preview_cap_mode = 0;//0 is preview mode - set_w = mf->width; - set_h = mf->height; - if (((set_w <= 176) && (set_h <= 144)) && (supported_size & OUTPUT_QCIF)) - { - set_w = 176; - set_h = 144; - res_set = OUTPUT_QCIF; - } - else if (((set_w <= 320) && (set_h <= 240)) && (supported_size & OUTPUT_QVGA)) - { - set_w = 320; - set_h = 240; - res_set = OUTPUT_QVGA; - - } - else if (((set_w <= 352) && (set_h<= 288)) && (supported_size & OUTPUT_CIF)) - { - set_w = 352; - set_h = 288; - res_set = OUTPUT_CIF; - - } - else if (((set_w <= 640) && (set_h <= 480)) && (supported_size & OUTPUT_VGA)) - { - set_w = 640; - set_h = 480; - res_set = OUTPUT_VGA; - - } - else if (((set_w <= 800) && (set_h <= 600)) && (supported_size & OUTPUT_SVGA)) - { - set_w = 800; - set_h = 600; - res_set = OUTPUT_SVGA; - - } - else if (((set_w <= 1024) && (set_h <= 768)) && (supported_size & OUTPUT_XGA)) - { - set_w = 1024; - set_h = 768; - res_set = OUTPUT_XGA; - - } - else if (((set_w <= 1280) && (set_h <= 720)) && (supported_size & OUTPUT_720P)) - { - set_w = 1280; - set_h = 720; - res_set = OUTPUT_720P; - } - - else if (((set_w <= 1280) && (set_h <= 960)) && (supported_size & OUTPUT_QUADVGA)) - { - set_w = 1280; - set_h = 960; - res_set = OUTPUT_QUADVGA; - } - else if (((set_w <= 1280) && (set_h <= 1024)) && (supported_size & OUTPUT_XGA)) - { - set_w = 1280; - set_h = 1024; - res_set = OUTPUT_XGA; - } - else if (((set_w <= 1600) && (set_h <= 1200)) && (supported_size & OUTPUT_UXGA)) - { - set_w = 1600; - set_h = 1200; - res_set = OUTPUT_UXGA; - } - else if (((set_w <= 1920) && (set_h <= 1080)) && (supported_size & OUTPUT_1080P)) - { - set_w = 1920; - set_h = 1080; - res_set = OUTPUT_1080P; - } - else if (((set_w <= 2048) && (set_h <= 1536)) && (supported_size & OUTPUT_QXGA)) - { - set_w = 2048; - set_h = 1536; - res_set = OUTPUT_QXGA; - } - else if (((set_w <= 2592) && (set_h <= 1944)) && (supported_size & OUTPUT_QSXGA)) - { - set_w = 2592; - set_h = 1944; - res_set = OUTPUT_QSXGA; - } - else if (((set_w <= 3264) && (set_h <= 2448)) && (supported_size & OUTPUT_QUXGA)) - { - set_w = 3264; - set_h = 2448; - res_set = OUTPUT_QUXGA; - } - else - { - set_w = 1280; - set_h = 960; - res_set = OUTPUT_QUADVGA; - } - - //if(res_set != sensor->isp_priv_info.curRes) - // sensor_set_isp_output_res(client,res_set); - //res will be setted - sensor->isp_priv_info.curRes = res_set; - if(is_capture) - sensor->isp_priv_info.curPreviewCapMode = CAPTURE_MODE; - else - sensor->isp_priv_info.curPreviewCapMode = PREVIEW_MODE; - - mf->width = set_w; - mf->height = set_h; - //enter capture or preview mode - //EXISP_I2C_PvCapModeSet(preview_cap_mode); - DEBUG_TRACE("%s:setw = %d,seth = %d\n",__func__,set_w,set_h); - - sensor_s_fmt_end: - return ret; - } - -int icatch_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize) -{ - int err = 0,i=0,num = 0; - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - - printk("icatch_enum_framesizes fsize->reserved[0](%x) fsize->reserved[1](%x)\n",fsize->reserved[0],fsize->reserved[1]); - if( (fsize->reserved[1] & 0xff) == 0x01){ - IsZSL = TRUE; - }else{ - IsZSL = FALSE; - } - - //get supported framesize num - - if (fsize->index >= sensor->isp_priv_info.supportedSizeNum) { - err = -1; - goto end; - } - - if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QCIF)) - { - - fsize->discrete.width = 176; - fsize->discrete.height = 144; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QVGA)) - { - fsize->discrete.width = 320; - fsize->discrete.height = 240; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_CIF) ) - { - - fsize->discrete.width = 352; - fsize->discrete.height = 288; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_VGA)) - { - - fsize->discrete.width = 640; - fsize->discrete.height = 480; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_SVGA)) - { - - fsize->discrete.width = 800; - fsize->discrete.height = 600; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_XGA)) - { - - fsize->discrete.width = 1024; - fsize->discrete.height = 768; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_720P)) - { - - fsize->discrete.width = 1280; - fsize->discrete.height = 720; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QUADVGA)) - { - fsize->discrete.width = 1280; - fsize->discrete.height = 960; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_XGA)) - { - fsize->discrete.width = 1280; - fsize->discrete.height = 1024; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_UXGA) ) - { - fsize->discrete.width = 1600; - fsize->discrete.height = 1200; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_1080P)) - { - fsize->discrete.width = 1920; - fsize->discrete.height = 1080; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QXGA)) - { - fsize->discrete.width = 2048; - fsize->discrete.height = 1536; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QSXGA)) - { - - fsize->discrete.width = 2592; - fsize->discrete.height = 1944; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } - else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QUXGA)) - { - - fsize->discrete.width = 3264; - fsize->discrete.height = 2448; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - } else { - err = -1; - } - - - -end: - return err; -} - - -/*------------------------------------------------------------------------- - * Function Name : EXISP_I2C_PvSizeSet - * ucParam: - 0x00 1280x960 - 0x01 3264x2448 - 0x02 1920x1080 - 0x03 320x240(reserved) - 0x04 1280x720 - 0x05 1040x780 - 0x06 2080x1560 - 0x07 3648x2736 - 0x08 4160x3120 - 0x09 3360x1890 - 0x0A 2592x1944 - 0x0B 640x480 - 0x0C 1408x1408 - 0x0D 1920x1088 - * Return : None - *------------------------------------------------------------------------*/ - -static int icatch_set_isp_output_res(struct i2c_client *client,enum ISP_OUTPUT_RES outputSize){ - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); -#if 1 - u8 res_sel = 0; - switch(outputSize) { - case OUTPUT_QCIF: - case OUTPUT_HQVGA: - case OUTPUT_QVGA: - case OUTPUT_CIF: - case OUTPUT_VGA: - case OUTPUT_SVGA: - case OUTPUT_720P: - case OUTPUT_QUADVGA: - res_sel = 0; - break; - case OUTPUT_XGA: - case OUTPUT_SXGA: - case OUTPUT_UXGA: - case OUTPUT_1080P: - res_sel = 0x02; - case OUTPUT_QXGA: - case OUTPUT_QSXGA: - res_sel = 0x0A;// non-zsl single - break; - case OUTPUT_QUXGA: - res_sel = 0x01;// non-zsl single - break; - default: - DEBUG_TRACE("%s %s isp not support this resolution!\n",sgensor->dev_name,__FUNCTION__); - break; - } -#endif - int cnt = 16; - //preview mode set - if((sensor->isp_priv_info.curPreviewCapMode == CAPTURE_MODE) - /*(outputSize == OUTPUT_QSXGA) || (outputSize == OUTPUT_QSXGA)*/){ - //in capture mode , isp output full size if size have not been set. - if(sensor->isp_priv_info.hdr == FALSE){ - if(IsZSL){ - printk("IsZSL EXISP_PvSizeSet(0x0A)\n"); - EXISP_PvSizeSet(res_sel); - //polling until AE ready - while (((EXISP_I2C_3AStatusGet() & 0x1) == 0) && (cnt -- > 0)) { - DEBUG_TRACE("%s %s polling AE ready\n",sgensor->dev_name,__FUNCTION__); - mdelay(50); - } - sensor_interrupt_wait_clear(); - }else{ - printk("Is not ZSL HdrEn FALSE EXISP_ImageCapSet(IMAGE_CAP_NONZSL_SINGLE)\n"); - icatch_sensor_write(SP7K_RDREG_INT_STS_REG_0,icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0)); - EXISP_ImageCapSet(IMAGE_CAP_NONZSL_SINGLE); - sensor_interrupt_wait_clear(); - } - }else{ - printk("HdrEn EXISP_ImageCapSet(IMAGE_CAP_HDR)\n"); - EXISP_ImageCapSet(IMAGE_CAP_HDR); - sensor_interrupt_wait_clear(); - } - //sensor->isp_priv_info.curPreviewCapMode = CAPTURE_NONE_ZSL_MODE; - } - else{ - EXISP_PvSizeSet(res_sel); - //polling until AE ready - while (((EXISP_I2C_3AStatusGet() & 0x1) == 0) && (cnt -- > 0)) { - DEBUG_TRACE("%s %s polling AE ready\n",sgensor->dev_name,__FUNCTION__); - mdelay(50); - } - sensor_interrupt_wait_clear(); - //sensor->isp_priv_info.curPreviewCapMode = PREVIEW_MODE; -#if 1 - DEBUG_TRACE("\n %s pid = 0x%x\n", sgensor->dev_name, EXISP_I2C_VendorIdGet); - DEBUG_TRACE("fw version is 0x%x\n ",EXISP_I2C_FWVersionGet()); - - DEBUG_TRACE("front id= 0x%x,rear id = 0x%x\n ",EXISP_I2C_FrontSensorIdGet(),EXISP_I2C_RearSensorIdGet()); -#endif - } - return 0; -} - - int icatch_s_stream(struct v4l2_subdev *sd, int enable){ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct soc_camera_device *icd = client->dev.platform_data; - struct generic_sensor*sgensor = to_generic_sensor(client); - struct specific_sensor*sensor = to_specific_sensor(sgensor); - DEBUG_TRACE("%s:enable = %d\n",__func__,enable); - DEBUG_TRACE("@@NY@@%s: client %0x\n", __FUNCTION__, client); - if(enable == 0){ - // sensor_set_face_detect(client,0); - // sensor_af_workqueue_set(icd,0,0,true); -#if CALIBRATION_MODE_FUN - if (g_is_calibrationMode) - EXISP_I2C_PvStreamSet(0); // stream off -#endif - sensor->isp_priv_info.curPreviewCapMode = IDLE_MODE; - }else{ -#if CALIBRATION_MODE_FUN - if (g_is_calibrationMode && - sensor->isp_priv_info.sensor_id == SENSOR_ID_REAR_CALIBRATION && - sensor->isp_priv_info.rk_query_PreviewCapMode == PREVIEW_MODE) { - EXISP_PvSizeSet(0x0A); - sensor->isp_priv_info.curPreviewCapMode = PREVIEW_MODE; - EXISP_I2C_PvStreamSet(1); // stream on - return 0; - } -#endif - printk(KERN_ERR"icatch_set_isp_output_res: curRes(%x)\n",sensor->isp_priv_info.curRes); - //sensor_set_face_detect(client,1); - icatch_set_isp_output_res(client, sensor->isp_priv_info.curRes); - - -#if CALIBRATION_MODE_FUN - if (g_is_calibrationMode) - EXISP_I2C_PvStreamSet(1); // stream on -#endif - } - - return 0; -} - - -int icatch_request_firmware(const struct firmware ** fw){ - int ret = 0; - if( request_firmware(fw, ICATCHFWNAME, &g_icatch_i2c_client->dev) !=0){ - DEBUG_TRACE("%s:%d, request firmware erro,please check firmware!\n"); - ret = -1; - }else{ - ret = 0; - } - return ret; -} - -void icatch_release_firmware(const struct firmware * fw){ - if(fw) - release_firmware(fw); -} - -void icatch_sensor_power_ctr(struct soc_camera_device *icd ,int on,int power_mode){ -#if 0 - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct rk29camera_platform_data* pdata = (struct rk29camera_platform_data*)(to_soc_camera_host(icd->dev.parent)->v4l2_dev.dev->platform_data); - if(!on){ - //power down - if(icl->power) - icl->power(icd->pdev,0); - if(pdata && pdata->sensor_mclk) - pdata->sensor_mclk(RK29_CAM_PLATFORM_DEV_ID,0,24*1000*1000); - if(icl->powerdown) - icl->powerdown(icd->pdev,0); - iomux_set(GPIO1_A4); - iomux_set(GPIO1_A5) ; - iomux_set(GPIO1_A6); - iomux_set(GPIO1_A7); - iomux_set(GPIO3_B6); - iomux_set(GPIO3_B7); - iomux_set(GPIO0_C0); - gpio_set_value(RK30_PIN1_PA4,0); - gpio_set_value(RK30_PIN1_PA5,0); - gpio_set_value(RK30_PIN1_PA6,0); // for clk 24M - gpio_set_value(RK30_PIN1_PA7,0); - gpio_set_value(RK30_PIN3_PB6,0); - gpio_set_value(RK30_PIN3_PB7,0); - gpio_set_value(RK30_PIN0_PC0,0); - //msleep(500); - }else{ - //power ON - gpio_set_value(RK30_PIN1_PA6,1); // for clk 24M - - if(icl->power) - icl->power(icd->pdev,1); - if(icl->powerdown){ - if(power_mode == 0)//from spi - icl->powerdown(icd->pdev,1); - else - icl->powerdown(icd->pdev,0); - } - if(pdata && pdata->sensor_mclk) - pdata->sensor_mclk(RK29_CAM_PLATFORM_DEV_ID,1,24*1000*1000); - //reset , reset pin low ,then high - if (icl->reset) - icl->reset(icd->pdev); - if(power_mode == 0)//from spi - icl->powerdown(icd->pdev,0); - iomux_set(SPI0_CLK); - iomux_set(SPI0_RXD); - iomux_set(SPI0_TXD); - iomux_set(SPI0_CS0); - iomux_set(I2C3_SDA); - iomux_set(I2C3_SCL); - msleep(100); - } - #endif -} - -#if CALIBRATION_MODE_FUN -#if 0 -void __dump(const u8 *data, size_t size) { - size_t i = 0; - char buf[100] = {0}; - char lbuf[12]; - - while( i < size) { - if ((i%16 == 0) && (i != 0)) { - DEBUG_TRACE("%s\n", buf); - } - if (i%16 == 0) { - buf[0] = 0; - sprintf(lbuf, "%08X:", i); - strcat(buf, lbuf); - } - sprintf(lbuf, " %02X", *(data + i)); - strcat(buf, lbuf); - i++; - } - - DEBUG_TRACE("%s\n", buf); -} -#endif - -struct icatch_cali_fw_data * icatch_load_cali_fw_data(u8 sensorid) { - - if (g_is_calibrationMode) { - return NULL; - } - - struct icatch_cali_fw_data * fw = NULL; - switch (sensorid) { - case SENSOR_ID_FRONT: - fw = &g_cali_fw_data_front; - break; - case SENSOR_ID_REAR: - fw = &g_cali_fw_data_back; - break; - default: - break; - } - if (fw == NULL) - return NULL; - - if (request_firmware( - &(fw->fw_option), - fw->fname_option, - &g_icatch_i2c_client->dev) != 0) { - DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_option); - fw->fw_option = NULL; - } - - if (request_firmware( - &(fw->fw_3acali), - fw->fname_3acali, - &g_icatch_i2c_client->dev) != 0) { - DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_3acali); - fw->fw_3acali = NULL; - } -#if 0 - else { - DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_3acali, fw->fw_3acali->size); - __dump(fw->fw_3acali->data, fw->fw_3acali->size); - } -#endif - - if (request_firmware( - &(fw->fw_lsc), - fw->fname_lsc, - &g_icatch_i2c_client->dev) != 0) { - DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_lsc); - fw->fw_lsc = NULL; - } -#if 0 - else { - DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_lsc, fw->fw_lsc->size); - __dump(fw->fw_lsc->data, fw->fw_lsc->size); - } -#endif - - if (request_firmware( - &(fw->fw_lscdq), - fw->fname_lscdq, - &g_icatch_i2c_client->dev) != 0) { - DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_lscdq); - fw->fw_lscdq = NULL; - } -#if 0 - else { - DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_lscdq, fw->fw_lscdq->size); - __dump(fw->fw_lscdq->data, fw->fw_lscdq->size); - } -#endif - - return fw; -} - -void icatch_free_cali_fw_data(struct icatch_cali_fw_data * data) { - if (data == NULL) - return ; - - if (data->fw_option != NULL) { - release_firmware(data->fw_option); - } - - if (data->fw_3acali != NULL) { - release_firmware(data->fw_3acali); - } - - if (data->fw_lsc != NULL) { - release_firmware(data->fw_lsc); - } - - if (data->fw_lscdq != NULL) { - release_firmware(data->fw_lscdq); - } -} -#endif - -//#include "BOOT_OV5693_126MHz(075529).c" - int icatch_load_fw(struct soc_camera_device *icd,u8 sensorid){ - struct firmware *fw =NULL; -#if CALIBRATION_MODE_FUN - struct icatch_cali_fw_data * cali_data = NULL; -#endif - int ret = 0; - icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); - icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); - if(ICATCH_BOOT == ICATCH_BOOT_FROM_HOST){ - DEBUG_TRACE("@@NY@@%s: %d\n", __FUNCTION__, sensorid); - if(icatch_request_firmware(&fw)!= 0){ - ret = -1; - goto icatch_load_fw_out; - } - -#if CALIBRATION_MODE_FUN - g_fw_version.fw = *((__u32*)(fw->data + fw->size - 4)); - - cali_data = icatch_load_cali_fw_data(sensorid); - if (cali_data != NULL) { - DEBUG_TRACE("%s:%d,load calibration fw data success !!!!\n",__func__,__LINE__); - ret = EXISP_LoadCodeStart( - ICATCH_BOOT, - sensorid, - g_is_calibrationMode, - (u8*)(fw->data), - cali_data->fw_option ? (u8*)(cali_data->fw_option->data) : &g_Calibration_Option_Def, - cali_data->fw_3acali ? (u8*)(cali_data->fw_3acali->data) : NULL, - cali_data->fw_lsc ? (u8*)(cali_data->fw_lsc->data) : NULL, - cali_data->fw_lscdq ? (u8*)(cali_data->fw_lscdq->data) : NULL); - } else { - DEBUG_TRACE("%s:%d,load calibration fw data fail !!!!\n",__func__,__LINE__); - ret = EXISP_LoadCodeStart( - ICATCH_BOOT, - sensorid, - g_is_calibrationMode, - (u8*)(fw->data), - &g_Calibration_Option_Def, - NULL, - NULL, - NULL); - } -#else - ret = EXISP_LoadCodeStart( - ICATCH_BOOT, - sensorid, - 0, - (u8*)(fw->data), - &g_Calibration_Option_Def, - NULL, - NULL, - NULL); -#endif - - if (ret != SUCCESS) { - DEBUG_TRACE("%s:%d,load firmware failed !!!!\n",__func__,__LINE__); - ret = -1; - } else { - ret = 0; - } - - icatch_release_firmware(fw); - icatch_free_cali_fw_data(cali_data); - - if(ret < 0) - goto icatch_load_fw_out; - - }else{ - #if 1 - BB_WrSPIFlash(0xffffff); - - icatch_sensor_power_ctr(icd,0,0); - icatch_sensor_power_ctr(icd,1,0); - gpio_set_value(RK30_PIN1_PA6,0); // for clk 24M - #endif - } - // msleep(100); - return 0; -icatch_load_fw_out: - return ret; -} - - -int icatch_get_rearid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *rear_id) -{ - static int ret = 0; - static int done = 0; - static UINT16 _rear_id = 0; - - static const struct rk_sensor_reg reset_1[]={ - {0x1011, 0x01}, /* CPU suspend */ - {0x0084, 0x14}, /* To sensor clock divider */ - {0x0034, 0xFF}, /* Turn on all clock */ - {0x9032, 0x00}, - {0x9033, 0x10}, - {0x9030, 0x3f}, - {0x9031, 0x04}, - {0x9034, 0xf2}, - {0x9035, 0x04}, - {0x9032, 0x10}, - {0x00, 0x00}, - }; - - //tmrUsWait(10000); /*10ms*/ - - static const struct rk_sensor_reg reset_2[] = { - {0x9032, 0x30}, - {0x00, 0x00}, - }; - - //tmrUsWait(10000); /*10ms*/ - - - static const struct rk_sensor_reg reset_3[] = { - /*End - Power on sensor & enable clock */ - {0x9008, 0x00}, - {0x9009, 0x00}, - {0x900A, 0x00}, - {0x900B, 0x00}, - - /*Start - I2C Read*/ - {0x923C, 0x01}, /* Sub address enable */ - {0x9238, 0x30}, /* Sub address enable */ - {0x9240, 0x6C}, /* Slave address */ - {0x9200, 0x03}, /* Read mode */ - {0x9210, 0x00}, /* Register addr MSB */ - {0x9212, 0x00}, /* Register addr LSB */ - {0x9204, 0x01}, /* Trigger I2C read */ - {0x00, 0x00}, - }; - - // tmrUsWait(2000);/*2ms*/ - - DEBUG_TRACE("%s: entry!\n", __FUNCTION__); - - if (done == 1) { - if (rear_id != NULL) - *rear_id = _rear_id; - return ret; - } - - icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); - icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); - - if (icatch_sensor_write_array(reset_1) != 0) { - ret = -ENXIO; - goto l_ret; - } - msleep(10); - - if (icatch_sensor_write_array(reset_2) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(10); - if (icatch_sensor_write_array(reset_3) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(2); - _rear_id = (UINT16)icatch_sensor_read(0x9211) << 8; - _rear_id += icatch_sensor_read(0x9213); - DEBUG_TRACE("%s: rear_id = 0x%04X\n", __FUNCTION__, _rear_id); - *rear_id = _rear_id; - - -l_ret: - icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); - done = 1; - return ret; -} - - -int icatch_get_frontid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *front_id) -{ - static int ret = 0; - static int done = 0; - static UINT16 _front_id = 0; - - static const struct rk_sensor_reg reset_1[]={ - { 0x1011, 0x01,0x0,0x0}, /* CPU Suspend */ - - { 0x0084, 0x14}, /* To sensor clock divider */ - { 0x0034, 0xFF}, /* Turn on all clock */ - { 0x9030, 0x3f}, - { 0x9031, 0x04}, - { 0x9034, 0xf2}, - { 0x9035, 0x04}, - { 0x9033, 0x04}, - { 0x9032, 0x3c}, - SensorEnd - }; - - //tmrUsWait(10000); /* 10ms */ - - static const struct rk_sensor_reg reset_2[] = { - {0x9033, 0x00}, - SensorEnd - }; - - //tmrUsWait(10000); /*10ms*/ - - - static const struct rk_sensor_reg reset_3[] = { - { 0x9033, 0x04}, - { 0x9032, 0x3e}, - SensorEnd - }; - - //tmrUsWait(10000); /* 10ms */ - - static const struct rk_sensor_reg reset_4[] = { - { 0x9032, 0x3c}, - /*End - Power on sensor & enable clock */ - - /*Start - I2C Read ID*/ - { 0x9138, 0x30}, /* Sub address enable */ - { 0x9140, 0x90}, /* Slave address */ - { 0x9100, 0x03}, /* Read mode */ - { 0x9110, 0x00}, /* Register addr MSB */ - { 0x9112, 0x00}, /* Register addr LSB */ - { 0x9104, 0x01 }, /* Trigger I2C read */ - SensorEnd - }; - - //tmrUsWait(100); /* 0.1ms */ - - static const struct rk_sensor_reg reset_5[] = { - { 0x9110, 0x00}, /* Register addr MSB */ - { 0x9112, 0x01}, /* Register addr LSB */ - { 0x9104, 0x01}, /* Trigger I2C read */ - SensorEnd - }; - - DEBUG_TRACE("%s: entry!\n", __FUNCTION__); - - if (done == 1) { - if (front_id != NULL) - *front_id = _front_id; - return ret; - } - - icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); - icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); - - if (icatch_sensor_write_array(reset_1) != 0) { - ret = -ENXIO; - goto l_ret; - } - msleep(10); - - if (icatch_sensor_write_array(reset_2) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(10); - if (icatch_sensor_write_array(reset_3) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(10); - - - if (icatch_sensor_write_array(reset_4) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(1); - _front_id = (UINT16)icatch_sensor_read(0x9111) << 8; - - if (icatch_sensor_write_array(reset_5) != 0) { - ret = -ENXIO; - goto l_ret; - } - - msleep(1); - _front_id += icatch_sensor_read(0x9111); - DEBUG_TRACE("%s: front_id = 0x%04X\n", __FUNCTION__, _front_id); - *front_id = _front_id; - -l_ret: - icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); - done = 1; - return ret; -} - diff --git a/drivers/media/video/icatch7002/icatch7002_common.h b/drivers/media/video/icatch7002/icatch7002_common.h deleted file mode 100755 index cc7148550078..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_common.h +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef ICATCH7002_COMMON_H -#include "../generic_sensor.h" -#include "app_i2c_lib_icatch.h" -#include - -/* CAMERA_REAR_SENSOR_SETTING:V17.00.18 */ -/* CAMERA_FRONT_SENSOR_SETTING:V17.00.18 */ -#if defined(CONFIG_TRACE_LOG_PRINTK) - #define DEBUG_TRACE(format, ...) printk(KERN_WARNING format, ## __VA_ARGS__) -#else - #define DEBUG_TRACE(format, ...) -#endif -#define LOG_TRACE(format, ...) printk(KERN_WARNING format, ## __VA_ARGS__) - - -#define CALIBRATION_MODE_FUN 1 - -#define SENSOR_REGISTER_LEN 2 // sensor register address bytes -#define SENSOR_VALUE_LEN 1 // sensor register value bytes - -extern struct i2c_client *g_icatch_i2c_client; -#define icatch_sensor_write(reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)((g_icatch_i2c_client),(reg),(v)) -#define icatch_sensor_write_array(regarry) generic_sensor_write_array(g_icatch_i2c_client,regarry) - - -static inline u8 icatch_sensor_read(u16 reg) -{ - u8 val; - sensor_read_reg2val1(g_icatch_i2c_client,reg,&val); - return val; -} - - -enum sensor_work_state { - sensor_work_ready = 0, - sensor_working, -}; - -#define CONFIG_SENSOR_WhiteBalance 1 -#define CONFIG_SENSOR_Brightness 0 -#define CONFIG_SENSOR_Contrast 0 -#define CONFIG_SENSOR_Saturation 0 -#define CONFIG_SENSOR_Effect 1 -#define CONFIG_SENSOR_Scene 1 -#define CONFIG_SENSOR_DigitalZoom 0 -#define CONFIG_SENSOR_Focus 1 -#define CONFIG_SENSOR_Exposure 1 -#define CONFIG_SENSOR_Flash 0 -#define CONFIG_SENSOR_Mirror 0 -#define CONFIG_SENSOR_Flip 0 -#define CONFIG_SENSOR_FOCUS_ZONE 0 -#define CONFIG_SENSOR_FACE_DETECT 0 -#define CONFIG_SENSOR_ISO 1 -#define CONFIG_SENSOR_AntiBanding 1 -#define CONFIG_SENSOR_WhiteBalanceLock 1 -#define CONFIG_SENSOR_ExposureLock 1 -#define CONFIG_SENSOR_MeteringAreas 1 -#define CONFIG_SENSOR_Wdr 1 -#define CONFIG_SENSOR_EDGE 1 -#define CONFIG_SENSOR_JPEG_EXIF 1 -#define CONFIG_SENSOR_DUMPREGS 0 - -#if CONFIG_SENSOR_Focus -extern int icatch_sensor_set_auto_focus(struct i2c_client *client, int value,int *tmp_zone); -#endif - -#if CALIBRATION_MODE_FUN -void icatch_create_proc_entry(void); -void icatch_remove_proc_entry(void); -#endif -extern void BB_WrSPIFlash(u32 size); -extern int icatch_request_firmware(const struct firmware ** fw); -extern void icatch_release_firmware(const struct firmware * fw); -extern void icatch_sensor_power_ctr(struct soc_camera_device *icd ,int on,int power_mode); -extern int icatch_load_fw(struct soc_camera_device *icd,u8 sensorid); -int icatch_get_rearid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *rear_id); -int icatch_get_frontid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *front_id); -extern int icatch_sensor_init(struct i2c_client *client); -extern int icatch_s_fmt(struct i2c_client *client, struct v4l2_mbus_framefmt *mf,bool is_capture); -extern int icatch_s_stream(struct v4l2_subdev *sd, int enable); -extern int sensor_set_get_control_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl,bool is_set); -extern int icatch_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); - -enum ISP_OUTPUT_RES{ - OUTPUT_QCIF =0x0001, // 176*144 - OUTPUT_HQVGA =0x0002,// 240*160 - OUTPUT_QVGA =0x0004, // 320*240 - OUTPUT_CIF =0x0008, // 352*288 - OUTPUT_VGA =0x0010, // 640*480 - OUTPUT_SVGA =0x0020, // 800*600 - OUTPUT_720P =0x0040, // 1280*720 - OUTPUT_XGA =0x0080, // 1024*768 - OUTPUT_QUADVGA =0x0100, // 1280*960 - OUTPUT_SXGA =0x0200, // 1280*1024 - OUTPUT_UXGA =0x0400, // 1600*1200 - OUTPUT_1080P =0x0800, //1920*1080 - OUTPUT_QXGA =0x1000, // 2048*1536 - OUTPUT_QSXGA =0x2000, // 2592*1944 - OUTPUT_QUXGA =0x4000, //3264*2448 -}; - - - -enum sensor_preview_cap_mode{ - PREVIEW_MODE, - CAPTURE_MODE, - CAPTURE_ZSL_MODE, - CAPTURE_NONE_ZSL_MODE, - IDLE_MODE, -}; - - -typedef struct rk_sensor_focus_zone rk_sensor_tae_zone; -typedef struct{ - uint32_t num; - uint32_t denom; -}rat_t; - - -typedef struct{ - /*IFD0*/ - char *maker;//manufacturer of digicam, just to adjust to make inPhybusAddr to align to 64 - int makerchars;//length of maker, contain the end '\0', so equal strlen(maker)+1 - char *modelstr;//model number of digicam - int modelchars;//length of modelstr, contain the end '\0' - int Orientation;//usually 1 - //XResolution, YResolution; if need be not 72, TODO... - char DateTime[20];//must be 20 chars-> yyyy:MM:dd0x20hh:mm:ss'\0' - /*Exif SubIFD*/ - rat_t ExposureTime;//such as 1/400=0.0025s - rat_t ApertureFNumber;//actual f-number - int ISOSpeedRatings;//CCD sensitivity equivalent to Ag-Hr film speedrate - rat_t CompressedBitsPerPixel; - rat_t ShutterSpeedValue; - rat_t ApertureValue; - rat_t ExposureBiasValue; - rat_t MaxApertureValue; - int MeteringMode; - int Flash; - rat_t FocalLength; - rat_t FocalPlaneXResolution; - rat_t FocalPlaneYResolution; - int SensingMethod;//2 means 1 chip color area sensor - int FileSource;//3 means the image source is digital still camera - int CustomRendered;//0 - int ExposureMode;//0 - int WhiteBalance;//0 - rat_t DigitalZoomRatio;// inputw/inputw - //int FocalLengthIn35mmFilm; - int SceneCaptureType;//0 - -}RkExifInfo; - -//flash and focus must be considered. - -//soft isp or external isp used -//if soft isp is defined , the value in this sturct is used in cif driver . cif driver use this value to do isp func. -//value of this sturct MUST be defined(initialized) correctly. -struct isp_data{ - int focus; - int auto_focus; - int flash; - int whiteBalance; - int brightness; - int contrast; - int saturation; - int effect; - int scene; - int digitalzoom; - int exposure; - int iso; - int face; - int antibanding; - int WhiteBalanceLock; - int ExposureLock; - int MeteringAreas; - int Wdr; - int hdr; - //mirror or flip - unsigned char mirror; /* HFLIP */ - unsigned char flip; /* VFLIP */ - //preview or capture - int outputSize; // supported resolution - int curRes; - int curPreviewCapMode; - int supportedSize[10]; - int supportedSizeNum; - int had_setprvsize; - RkExifInfo exifInfo; -#if CALIBRATION_MODE_FUN - int rk_query_PreviewCapMode; - int sensor_id; -#endif - struct rk_sensor_focus_zone focus_zone; - rk_sensor_tae_zone tae_zone; - -}; - - - - -struct specific_sensor{ - struct generic_sensor common_sensor; - //define user data below - struct isp_data isp_priv_info; - -}; - -#endif - - diff --git a/drivers/media/video/icatch7002/icatch7002_mi1040.c b/drivers/media/video/icatch7002/icatch7002_mi1040.c deleted file mode 100755 index 30a50fbaeaa7..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_mi1040.c +++ /dev/null @@ -1,629 +0,0 @@ - -#include "icatch7002_common.h" -/* -* Driver Version Note -*v0.0.1: this driver is compatible with generic_sensor -*v0.0.3: -* add sensor_focus_af_const_pause_usr_cb; -*/ -static int version = KERNEL_VERSION(0,0,3); -module_param(version, int, S_IRUGO); - - - -static int debug; -module_param(debug, int, S_IRUGO|S_IWUSR); - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_WARNING fmt , ## arg); } while (0) - -/* Sensor Driver Configuration Begin */ -#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_MI1040 -#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_MI1040 -#define SENSOR_ID 0x2481 -#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ - SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ - SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) -#define SENSOR_PREVIEW_W 1280 -#define SENSOR_PREVIEW_H 960 -#define SENSOR_PREVIEW_FPS 30000 // 15fps -#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps -#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps -#define SENSOR_720P_FPS 0 -#define SENSOR_1080P_FPS 0 - - -static unsigned int SensorConfiguration = 0; -static unsigned int SensorChipID[] = {SENSOR_ID}; -/* Sensor Driver Configuration End */ - - -#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) -//#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) - -//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) -//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_write_array generic_sensor_write_array - - - -/* -* The follow setting need been filled. -* -* Must Filled: -* sensor_init_data : Sensor initial setting; -* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; -* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; -* sensor_softreset_data : Sensor software reset register; -* sensor_check_id_data : Sensir chip id register; -* -* Optional filled: -* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; -* sensor_720p: Sensor 720p setting, it is for video; -* sensor_1080p: Sensor 1080p setting, it is for video; -* -* :::::WARNING::::: -* The SensorEnd which is the setting end flag must be filled int the last of each setting; -*/ - -/* Sensor initial setting */ -static struct rk_sensor_reg sensor_init_data[] ={ - SensorStreamChk, - SensorEnd -}; -/* Senor full resolution setting: recommand for capture */ -static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ - SensorEnd - -}; - -/* Senor full resolution setting: recommand for video */ -static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ - SensorEnd -}; -/* Preview resolution setting*/ -static struct rk_sensor_reg sensor_preview_data[] = -{ - SensorStreamChk, - SensorEnd -}; -/* 1280x720 */ -static struct rk_sensor_reg sensor_720p[]={ - SensorEnd -}; - -/* 1920x1080 */ -static struct rk_sensor_reg sensor_1080p[]={ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_softreset_data[]={ - SensorEnd -}; - -static struct rk_sensor_reg sensor_check_id_data[]={ - SensorEnd -}; -/* -* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx -*/ -static struct rk_sensor_reg sensor_WhiteB_Auto[]= -{ - SensorEnd -}; -/* Cloudy Colour Temperature : 6500K - 8000K */ -static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= -{ - SensorEnd -}; -/* ClearDay Colour Temperature : 5000K - 6500K */ -static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= -{ - //Sunny - SensorEnd -}; -/* Office Colour Temperature : 3500K - 5000K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= -{ - //Office - SensorEnd - -}; -/* Home Colour Temperature : 2500K - 3500K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= -{ - //Home - SensorEnd -}; -static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, - sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, -}; - -static struct rk_sensor_reg sensor_Brightness0[]= -{ - // Brightness -2 - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness1[]= -{ - // Brightness -1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness2[]= -{ - // Brightness 0 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness3[]= -{ - // Brightness +1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness4[]= -{ - // Brightness +2 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness5[]= -{ - // Brightness +3 - - SensorEnd -}; -static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, - sensor_Brightness4, sensor_Brightness5,NULL, -}; - -static struct rk_sensor_reg sensor_Effect_Normal[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_WandB[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Sepia[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Negative[] = -{ - //Negative - SensorEnd -}; -static struct rk_sensor_reg sensor_Effect_Bluish[] = -{ - // Bluish - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Green[] = -{ - // Greenish - SensorEnd -}; -static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, - sensor_Effect_Bluish, sensor_Effect_Green,NULL, -}; - -static struct rk_sensor_reg sensor_Exposure0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure2[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure3[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure4[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure5[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure6[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, - sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, -}; - -static struct rk_sensor_reg sensor_Saturation0[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation2[]= -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; - -static struct rk_sensor_reg sensor_Contrast0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast1[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast2[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast3[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast4[]= -{ - - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Contrast5[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast6[]= -{ - - SensorEnd -}; -static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, - sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, -}; -static struct rk_sensor_reg sensor_SceneAuto[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_SceneNight[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; - -static struct rk_sensor_reg sensor_Zoom0[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom1[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom2[] = -{ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Zoom3[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; - -/* -* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu -*/ -static struct v4l2_querymenu sensor_menus[] = -{ - //white balance - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), - - //speical effect - new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), - - //scence - new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), - new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), - new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), - new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), - new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), - new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), - new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), - - //antibanding - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), - - //ISO - new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), - new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), - new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), - new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), - new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), - new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), -}; -/* -* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl -*/ -static struct sensor_v4l2ctrl_usr_s sensor_controls[] = -{ - new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), -}; - -//MUST define the current used format as the first item -static struct rk_sensor_datafmt sensor_colour_fmts[] = { - {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} -}; - - -/* -********************************************************** -* Following is local code: -* -* Please codeing your program here -********************************************************** -*/ -/* -********************************************************** -* Following is callback -* If necessary, you could coding these callback -********************************************************** -*/ -/* -* the function is called in open sensor -*/ -static int sensor_activate_cb(struct i2c_client *client) -{ - return icatch_sensor_init(client); -} -/* -* the function is called in close sensor -*/ -static int sensor_deactivate_cb(struct i2c_client *client) -{ - - return 0; -} -/* -* the function is called before sensor register setting in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return icatch_s_fmt(client, mf,capture); -} -/* -* the function is called after sensor register setting finished in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return 0; -} -static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) -{ - return 0; -} - -static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - - return 0; -} -static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - struct generic_sensor *sensor = to_generic_sensor(client); - return sensor->info_priv.chip_id[0]; -} -static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) -{ - //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - if (pm_msg.event == PM_EVENT_SUSPEND) { - SENSOR_DG("Suspend"); - - } else { - SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); - return -EINVAL; - } - return 0; -} - -static int sensor_resume(struct soc_camera_device *icd) -{ - - SENSOR_DG("Resume"); - - return 0; - -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ -static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} - -/* -* the function is v4l2 control V4L2_CID_VFLIP callback -*/ -static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ - -static int sensor_flip_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} -static int sensor_mirror_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} - -/* -* the functions are focus callbacks -*/ -static int sensor_focus_init_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ - return 0; -} - -static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ - - return 0; -} -static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) -{ - return 0; -} -static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) -{ - return 0; -} - -/* -face defect call back -*/ -static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ - return 0; -} - -/* -* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some -* initialization in the function. -*/ -static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) -{ - spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; - spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; - - spsensor->isp_priv_info.outputSize =OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSizeNum = 1; - spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; - - - return; -} - -/* -* :::::WARNING::::: -* It is not allowed to modify the following code -*/ - -sensor_init_parameters_default_code(); - -sensor_v4l2_struct_initialization(); - -sensor_probe_default_code(); - -sensor_remove_default_code(); - -sensor_driver_default_module_code(); - - - - diff --git a/drivers/media/video/icatch7002/icatch7002_ov2720.c b/drivers/media/video/icatch7002/icatch7002_ov2720.c deleted file mode 100755 index a2302abf03b3..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_ov2720.c +++ /dev/null @@ -1,629 +0,0 @@ - -#include "icatch7002_common.h" -/* -* Driver Version Note -*v0.0.1: this driver is compatible with generic_sensor -*v0.0.3: -* add sensor_focus_af_const_pause_usr_cb; -*/ -static int version = KERNEL_VERSION(0,0,3); -module_param(version, int, S_IRUGO); - - - -static int debug; -module_param(debug, int, S_IRUGO|S_IWUSR); - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_WARNING fmt , ## arg); } while (0) - -/* Sensor Driver Configuration Begin */ -#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_OV2720 -#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_OV2720 -#define SENSOR_ID 0x2720 -#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ - SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ - SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) -#define SENSOR_PREVIEW_W 1280 -#define SENSOR_PREVIEW_H 960 -#define SENSOR_PREVIEW_FPS 30000 // 15fps -#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps -#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps -#define SENSOR_720P_FPS 30000 -#define SENSOR_1080P_FPS 0 - - -static unsigned int SensorConfiguration = 0; -static unsigned int SensorChipID[] = {SENSOR_ID}; -/* Sensor Driver Configuration End */ - - -#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) -//#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) - -//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) -//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_write_array generic_sensor_write_array - - - -/* -* The follow setting need been filled. -* -* Must Filled: -* sensor_init_data : Sensor initial setting; -* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; -* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; -* sensor_softreset_data : Sensor software reset register; -* sensor_check_id_data : Sensir chip id register; -* -* Optional filled: -* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; -* sensor_720p: Sensor 720p setting, it is for video; -* sensor_1080p: Sensor 1080p setting, it is for video; -* -* :::::WARNING::::: -* The SensorEnd which is the setting end flag must be filled int the last of each setting; -*/ - -/* Sensor initial setting */ -static struct rk_sensor_reg sensor_init_data[] ={ - SensorStreamChk, - SensorEnd -}; -/* Senor full resolution setting: recommand for capture */ -static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ - SensorEnd - -}; - -/* Senor full resolution setting: recommand for video */ -static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ - SensorEnd -}; -/* Preview resolution setting*/ -static struct rk_sensor_reg sensor_preview_data[] = -{ - SensorStreamChk, - SensorEnd -}; -/* 1280x720 */ -static struct rk_sensor_reg sensor_720p[]={ - SensorStreamChk, - SensorEnd -}; - -/* 1920x1080 */ -static struct rk_sensor_reg sensor_1080p[]={ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_softreset_data[]={ - SensorEnd -}; - -static struct rk_sensor_reg sensor_check_id_data[]={ - SensorEnd -}; -/* -* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx -*/ -static struct rk_sensor_reg sensor_WhiteB_Auto[]= -{ - SensorEnd -}; -/* Cloudy Colour Temperature : 6500K - 8000K */ -static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= -{ - SensorEnd -}; -/* ClearDay Colour Temperature : 5000K - 6500K */ -static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= -{ - //Sunny - SensorEnd -}; -/* Office Colour Temperature : 3500K - 5000K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= -{ - //Office - SensorEnd - -}; -/* Home Colour Temperature : 2500K - 3500K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= -{ - //Home - SensorEnd -}; -static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, - sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, -}; - -static struct rk_sensor_reg sensor_Brightness0[]= -{ - // Brightness -2 - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness1[]= -{ - // Brightness -1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness2[]= -{ - // Brightness 0 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness3[]= -{ - // Brightness +1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness4[]= -{ - // Brightness +2 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness5[]= -{ - // Brightness +3 - - SensorEnd -}; -static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, - sensor_Brightness4, sensor_Brightness5,NULL, -}; - -static struct rk_sensor_reg sensor_Effect_Normal[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_WandB[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Sepia[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Negative[] = -{ - //Negative - SensorEnd -}; -static struct rk_sensor_reg sensor_Effect_Bluish[] = -{ - // Bluish - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Green[] = -{ - // Greenish - SensorEnd -}; -static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, - sensor_Effect_Bluish, sensor_Effect_Green,NULL, -}; - -static struct rk_sensor_reg sensor_Exposure0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure2[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure3[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure4[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure5[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure6[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, - sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, -}; - -static struct rk_sensor_reg sensor_Saturation0[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation2[]= -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; - -static struct rk_sensor_reg sensor_Contrast0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast1[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast2[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast3[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast4[]= -{ - - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Contrast5[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast6[]= -{ - - SensorEnd -}; -static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, - sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, -}; -static struct rk_sensor_reg sensor_SceneAuto[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_SceneNight[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; - -static struct rk_sensor_reg sensor_Zoom0[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom1[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom2[] = -{ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Zoom3[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; - -/* -* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu -*/ -static struct v4l2_querymenu sensor_menus[] = -{ - //white balance - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), - - //speical effect - new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), - - //scence - new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), - new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), - new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), - new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), - new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), - new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), - new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), - - //antibanding - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), - - //ISO - new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), - new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), - new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), - new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), - new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), - new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), -}; -/* -* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl -*/ -static struct sensor_v4l2ctrl_usr_s sensor_controls[] = -{ - new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), -}; - -//MUST define the current used format as the first item -static struct rk_sensor_datafmt sensor_colour_fmts[] = { - {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} -}; - - -/* -********************************************************** -* Following is local code: -* -* Please codeing your program here -********************************************************** -*/ -/* -********************************************************** -* Following is callback -* If necessary, you could coding these callback -********************************************************** -*/ -/* -* the function is called in open sensor -*/ -static int sensor_activate_cb(struct i2c_client *client) -{ - return icatch_sensor_init(client); -} -/* -* the function is called in close sensor -*/ -static int sensor_deactivate_cb(struct i2c_client *client) -{ - - return 0; -} -/* -* the function is called before sensor register setting in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return icatch_s_fmt(client, mf,capture); -} -/* -* the function is called after sensor register setting finished in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return 0; -} -static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) -{ - return 0; -} - -static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - - return 0; -} -static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - struct generic_sensor *sensor = to_generic_sensor(client); - return sensor->info_priv.chip_id[0]; -} -static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) -{ - //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - if (pm_msg.event == PM_EVENT_SUSPEND) { - SENSOR_DG("Suspend"); - - } else { - SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); - return -EINVAL; - } - return 0; -} - -static int sensor_resume(struct soc_camera_device *icd) -{ - - SENSOR_DG("Resume"); - - return 0; - -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ -static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} - -/* -* the function is v4l2 control V4L2_CID_VFLIP callback -*/ -static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ - -static int sensor_flip_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} -static int sensor_mirror_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} - -/* -* the functions are focus callbacks -*/ -static int sensor_focus_init_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ - return 0; -} - -static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ - - return 0; -} -static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) -{ - return 0; -} -static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) -{ - return 0; -} - -/* -face defect call back -*/ -static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ - return 0; -} - -/* -* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some -* initialization in the function. -*/ -static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) -{ - spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; - spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; - - spsensor->isp_priv_info.outputSize =OUTPUT_1080P|OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSizeNum = 2; - spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSize[1] = OUTPUT_1080P; - return; -} - -/* -* :::::WARNING::::: -* It is not allowed to modify the following code -*/ - -sensor_init_parameters_default_code(); - -sensor_v4l2_struct_initialization(); - -sensor_probe_default_code(); - -sensor_remove_default_code(); - -sensor_driver_default_module_code(); - - - - diff --git a/drivers/media/video/icatch7002/icatch7002_ov5693.c b/drivers/media/video/icatch7002/icatch7002_ov5693.c deleted file mode 100755 index d7094b9e2445..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_ov5693.c +++ /dev/null @@ -1,638 +0,0 @@ - -#include "icatch7002_common.h" -/* -* Driver Version Note -*v0.0.1: this driver is compatible with generic_sensor -*v0.0.3: -* add sensor_focus_af_const_pause_usr_cb; -*/ -static int version = KERNEL_VERSION(0,0,3); -module_param(version, int, S_IRUGO); - - - -static int debug; -module_param(debug, int, S_IRUGO|S_IWUSR); - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_WARNING fmt , ## arg); } while (0) - -/* Sensor Driver Configuration Begin */ -#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_OV5693 -#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_OV5693 -#define SENSOR_ID 0x5690 -#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ - SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ - SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) -#define SENSOR_PREVIEW_W 1280 -#define SENSOR_PREVIEW_H 960 -#define SENSOR_PREVIEW_FPS 30000 // 15fps -#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps -#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps -#define SENSOR_720P_FPS 0 -#define SENSOR_1080P_FPS 0 - - -static unsigned int SensorConfiguration = CFG_Focus |CFG_FocusContinues|CFG_FocusZone; -static unsigned int SensorChipID[] = {SENSOR_ID}; -/* Sensor Driver Configuration End */ - - -#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) -#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) - -//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) -//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_write_array generic_sensor_write_array - - - -/* -* The follow setting need been filled. -* -* Must Filled: -* sensor_init_data : Sensor initial setting; -* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; -* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; -* sensor_softreset_data : Sensor software reset register; -* sensor_check_id_data : Sensir chip id register; -* -* Optional filled: -* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; -* sensor_720p: Sensor 720p setting, it is for video; -* sensor_1080p: Sensor 1080p setting, it is for video; -* -* :::::WARNING::::: -* The SensorEnd which is the setting end flag must be filled int the last of each setting; -*/ - -/* Sensor initial setting */ -static struct rk_sensor_reg sensor_init_data[] ={ - SensorStreamChk, - SensorEnd -}; -/* Senor full resolution setting: recommand for capture */ -static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ - SensorStreamChk, - SensorEnd - -}; - -/* Senor full resolution setting: recommand for video */ -static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ - SensorEnd -}; -/* Preview resolution setting*/ -static struct rk_sensor_reg sensor_preview_data[] = -{ - SensorStreamChk, - SensorEnd -}; -/* 1280x720 */ -static struct rk_sensor_reg sensor_720p[]={ - SensorEnd -}; - -/* 1920x1080 */ -static struct rk_sensor_reg sensor_1080p[]={ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_softreset_data[]={ - SensorEnd -}; - -static struct rk_sensor_reg sensor_check_id_data[]={ - SensorEnd -}; -/* -* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx -*/ -static struct rk_sensor_reg sensor_WhiteB_Auto[]= -{ - SensorEnd -}; -/* Cloudy Colour Temperature : 6500K - 8000K */ -static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= -{ - SensorEnd -}; -/* ClearDay Colour Temperature : 5000K - 6500K */ -static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= -{ - //Sunny - SensorEnd -}; -/* Office Colour Temperature : 3500K - 5000K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= -{ - //Office - SensorEnd - -}; -/* Home Colour Temperature : 2500K - 3500K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= -{ - //Home - SensorEnd -}; -static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, - sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, -}; - -static struct rk_sensor_reg sensor_Brightness0[]= -{ - // Brightness -2 - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness1[]= -{ - // Brightness -1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness2[]= -{ - // Brightness 0 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness3[]= -{ - // Brightness +1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness4[]= -{ - // Brightness +2 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness5[]= -{ - // Brightness +3 - - SensorEnd -}; -static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, - sensor_Brightness4, sensor_Brightness5,NULL, -}; - -static struct rk_sensor_reg sensor_Effect_Normal[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_WandB[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Sepia[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Negative[] = -{ - //Negative - SensorEnd -}; -static struct rk_sensor_reg sensor_Effect_Bluish[] = -{ - // Bluish - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Green[] = -{ - // Greenish - SensorEnd -}; -static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, - sensor_Effect_Bluish, sensor_Effect_Green,NULL, -}; - -static struct rk_sensor_reg sensor_Exposure0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure2[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure3[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure4[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure5[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure6[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, - sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, -}; - -static struct rk_sensor_reg sensor_Saturation0[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation2[]= -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; - -static struct rk_sensor_reg sensor_Contrast0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast1[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast2[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast3[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast4[]= -{ - - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Contrast5[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast6[]= -{ - - SensorEnd -}; -static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, - sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, -}; -static struct rk_sensor_reg sensor_SceneAuto[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_SceneNight[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; - -static struct rk_sensor_reg sensor_Zoom0[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom1[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom2[] = -{ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Zoom3[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; - -/* -* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu -*/ -static struct v4l2_querymenu sensor_menus[] = -{ - //white balance - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), - - //speical effect - new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), - - //scence - new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), - new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), - new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), - new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), - new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), - new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), - new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), - - //antibanding - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), - - //ISO - new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), - new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), - new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), - new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), - new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), - new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), -}; -/* -* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl -*/ -static struct sensor_v4l2ctrl_usr_s sensor_controls[] = -{ - new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), - -// new_user_v4l2ctrl(V4L2_CID_FOCUSZONE,V4L2_CTRL_TYPE_BOOLEAN,"FocusZone Control", 0, 1, 1, 1,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_ABSOLUTE,V4L2_CTRL_TYPE_INTEGER,"Focus Control", 0, 0xff, 1, 0,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_AUTO,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_CONTINUOUS,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), -}; - -//MUST define the current used format as the first item -static struct rk_sensor_datafmt sensor_colour_fmts[] = { - {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} -}; - - -/* -********************************************************** -* Following is local code: -* -* Please codeing your program here -********************************************************** -*/ -/* -********************************************************** -* Following is callback -* If necessary, you could coding these callback -********************************************************** -*/ -/* -* the function is called in open sensor -*/ -static int sensor_activate_cb(struct i2c_client *client) -{ - return icatch_sensor_init(client); -} -/* -* the function is called in close sensor -*/ -static int sensor_deactivate_cb(struct i2c_client *client) -{ - - return 0; -} -/* -* the function is called before sensor register setting in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return icatch_s_fmt(client, mf,capture); -} -/* -* the function is called after sensor register setting finished in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return 0; -} -static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) -{ - return 0; -} - -static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - - return 0; -} -static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - struct generic_sensor *sensor = to_generic_sensor(client); - return sensor->info_priv.chip_id[0]; -} -static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) -{ - //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - if (pm_msg.event == PM_EVENT_SUSPEND) { - SENSOR_DG("Suspend"); - - } else { - SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); - return -EINVAL; - } - return 0; -} - -static int sensor_resume(struct soc_camera_device *icd) -{ - - SENSOR_DG("Resume"); - - return 0; - -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ -static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} - -/* -* the function is v4l2 control V4L2_CID_VFLIP callback -*/ -static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ - -static int sensor_flip_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} -static int sensor_mirror_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} - -/* -* the functions are focus callbacks -*/ -static int sensor_focus_init_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ - return icatch_sensor_set_auto_focus(client, WqCmd_af_single,NULL); -} - -static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ - return 0; -} - -static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ - - return icatch_sensor_set_auto_focus(client, WqCmd_af_continues,NULL); -} -static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) -{ - return 0; -} -static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) -{ - return icatch_sensor_set_auto_focus(client, WqCmd_af_update_zone,zone_tm_pos); -} - -/* -face defect call back -*/ -static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ - return 0; -} - -/* -* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some -* initialization in the function. -*/ -static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) -{ - spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; - spsensor->isp_priv_info.focus_zone.lx = 256; - spsensor->isp_priv_info.focus_zone.rx = 768; - spsensor->isp_priv_info.focus_zone.ty = 256; - spsensor->isp_priv_info.focus_zone.dy = 768; - spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; - - spsensor->isp_priv_info.outputSize = OUTPUT_QSXGA|OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSizeNum = 2; - spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSize[1] = OUTPUT_QSXGA; - return; -} - -/* -* :::::WARNING::::: -* It is not allowed to modify the following code -*/ - -sensor_init_parameters_default_code(); - -sensor_v4l2_struct_initialization(); - -sensor_probe_default_code(); - -sensor_remove_default_code(); - -sensor_driver_default_module_code(); - - - - diff --git a/drivers/media/video/icatch7002/icatch7002_ov8825.c b/drivers/media/video/icatch7002/icatch7002_ov8825.c deleted file mode 100755 index c31912fbc60c..000000000000 --- a/drivers/media/video/icatch7002/icatch7002_ov8825.c +++ /dev/null @@ -1,639 +0,0 @@ - -#include "icatch7002_common.h" -/* -* Driver Version Note -*v0.0.1: this driver is compatible with generic_sensor -*v0.0.3: -* add sensor_focus_af_const_pause_usr_cb; -*/ -static int version = KERNEL_VERSION(0,0,3); -module_param(version, int, S_IRUGO); - - - -static int debug; -module_param(debug, int, S_IRUGO|S_IWUSR); - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_WARNING fmt , ## arg); } while (0) - -/* Sensor Driver Configuration Begin */ -#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_OV8825 -#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_OV8825 -#define SENSOR_ID 0x8825 -#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ - SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ - SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) -#define SENSOR_PREVIEW_W 1280 -#define SENSOR_PREVIEW_H 960 -#define SENSOR_PREVIEW_FPS 30000 // 15fps -#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps -#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps -#define SENSOR_720P_FPS 30000 -#define SENSOR_1080P_FPS 0 - - -static unsigned int SensorConfiguration = CFG_Focus |CFG_FocusContinues|CFG_FocusZone; -static unsigned int SensorChipID[] = {SENSOR_ID}; -/* Sensor Driver Configuration End */ - - -#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) -#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) - -//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) -//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) -//#define sensor_write_array generic_sensor_write_array - - - -/* -* The follow setting need been filled. -* -* Must Filled: -* sensor_init_data : Sensor initial setting; -* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; -* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; -* sensor_softreset_data : Sensor software reset register; -* sensor_check_id_data : Sensir chip id register; -* -* Optional filled: -* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; -* sensor_720p: Sensor 720p setting, it is for video; -* sensor_1080p: Sensor 1080p setting, it is for video; -* -* :::::WARNING::::: -* The SensorEnd which is the setting end flag must be filled int the last of each setting; -*/ - -/* Sensor initial setting */ -static struct rk_sensor_reg sensor_init_data[] ={ - SensorStreamChk, - SensorEnd -}; -/* Senor full resolution setting: recommand for capture */ -static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ - SensorStreamChk, - SensorEnd - -}; - -/* Senor full resolution setting: recommand for video */ -static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ - SensorEnd -}; -/* Preview resolution setting*/ -static struct rk_sensor_reg sensor_preview_data[] = -{ - SensorStreamChk, - SensorEnd -}; -/* 1280x720 */ -static struct rk_sensor_reg sensor_720p[]={ - SensorStreamChk, - SensorEnd -}; - -/* 1920x1080 */ -static struct rk_sensor_reg sensor_1080p[]={ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_softreset_data[]={ - SensorEnd -}; - -static struct rk_sensor_reg sensor_check_id_data[]={ - SensorEnd -}; -/* -* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx -*/ -static struct rk_sensor_reg sensor_WhiteB_Auto[]= -{ - SensorEnd -}; -/* Cloudy Colour Temperature : 6500K - 8000K */ -static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= -{ - SensorEnd -}; -/* ClearDay Colour Temperature : 5000K - 6500K */ -static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= -{ - //Sunny - SensorEnd -}; -/* Office Colour Temperature : 3500K - 5000K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= -{ - //Office - SensorEnd - -}; -/* Home Colour Temperature : 2500K - 3500K */ -static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= -{ - //Home - SensorEnd -}; -static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, - sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, -}; - -static struct rk_sensor_reg sensor_Brightness0[]= -{ - // Brightness -2 - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness1[]= -{ - // Brightness -1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness2[]= -{ - // Brightness 0 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness3[]= -{ - // Brightness +1 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness4[]= -{ - // Brightness +2 - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Brightness5[]= -{ - // Brightness +3 - - SensorEnd -}; -static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, - sensor_Brightness4, sensor_Brightness5,NULL, -}; - -static struct rk_sensor_reg sensor_Effect_Normal[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_WandB[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Sepia[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Negative[] = -{ - //Negative - SensorEnd -}; -static struct rk_sensor_reg sensor_Effect_Bluish[] = -{ - // Bluish - SensorEnd -}; - -static struct rk_sensor_reg sensor_Effect_Green[] = -{ - // Greenish - SensorEnd -}; -static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, - sensor_Effect_Bluish, sensor_Effect_Green,NULL, -}; - -static struct rk_sensor_reg sensor_Exposure0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure2[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure3[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure4[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure5[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Exposure6[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, - sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, -}; - -static struct rk_sensor_reg sensor_Saturation0[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation1[]= -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Saturation2[]= -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; - -static struct rk_sensor_reg sensor_Contrast0[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast1[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast2[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast3[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast4[]= -{ - - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Contrast5[]= -{ - - SensorEnd -}; - -static struct rk_sensor_reg sensor_Contrast6[]= -{ - - SensorEnd -}; -static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, - sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, -}; -static struct rk_sensor_reg sensor_SceneAuto[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_SceneNight[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; - -static struct rk_sensor_reg sensor_Zoom0[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom1[] = -{ - SensorEnd -}; - -static struct rk_sensor_reg sensor_Zoom2[] = -{ - SensorEnd -}; - - -static struct rk_sensor_reg sensor_Zoom3[] = -{ - SensorEnd -}; -static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; - -/* -* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu -*/ -static struct v4l2_querymenu sensor_menus[] = -{ - //white balance - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), - new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), - - //speical effect - new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), - new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), - - //scence - new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), - new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), - new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), - new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), - new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), - new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), - new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), - new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), - - //antibanding - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), - new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), - - //ISO - new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), - new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), - new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), - new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), - new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), - new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), - new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), -}; -/* -* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl -*/ -static struct sensor_v4l2ctrl_usr_s sensor_controls[] = -{ - new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), - new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), - -// new_user_v4l2ctrl(V4L2_CID_FOCUSZONE,V4L2_CTRL_TYPE_BOOLEAN,"FocusZone Control", 0, 1, 1, 1,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_ABSOLUTE,V4L2_CTRL_TYPE_INTEGER,"Focus Control", 0, 0xff, 1, 0,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_AUTO,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), -// new_user_v4l2ctrl(V4L2_CID_FOCUS_CONTINUOUS,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), -}; - -//MUST define the current used format as the first item -static struct rk_sensor_datafmt sensor_colour_fmts[] = { - {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} -}; - - -/* -********************************************************** -* Following is local code: -* -* Please codeing your program here -********************************************************** -*/ -/* -********************************************************** -* Following is callback -* If necessary, you could coding these callback -********************************************************** -*/ -/* -* the function is called in open sensor -*/ -static int sensor_activate_cb(struct i2c_client *client) -{ - return icatch_sensor_init(client); -} -/* -* the function is called in close sensor -*/ -static int sensor_deactivate_cb(struct i2c_client *client) -{ - - return 0; -} -/* -* the function is called before sensor register setting in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return icatch_s_fmt(client, mf,capture); -} -/* -* the function is called after sensor register setting finished in VIDIOC_S_FMT -*/ -static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) -{ - return 0; -} -static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) -{ - return 0; -} - -static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - - return 0; -} -static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) -{ - struct generic_sensor *sensor = to_generic_sensor(client); - return sensor->info_priv.chip_id[0]; -} -static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) -{ - //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - if (pm_msg.event == PM_EVENT_SUSPEND) { - SENSOR_DG("Suspend"); - - } else { - SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); - return -EINVAL; - } - return 0; -} - -static int sensor_resume(struct soc_camera_device *icd) -{ - - SENSOR_DG("Resume"); - - return 0; - -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ -static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} - -/* -* the function is v4l2 control V4L2_CID_VFLIP callback -*/ -static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) -{ - return 0; -} -/* -* the function is v4l2 control V4L2_CID_HFLIP callback -*/ - -static int sensor_flip_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} -static int sensor_mirror_cb(struct i2c_client *client, int flip) -{ - int err = 0; - - return err; -} - -/* -* the functions are focus callbacks -*/ -static int sensor_focus_init_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ - return icatch_sensor_set_auto_focus(client, WqCmd_af_single,NULL); -} - -static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ - return 0; -} - -static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ - - return icatch_sensor_set_auto_focus(client, WqCmd_af_continues,NULL); -} -static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) -{ - return 0; -} -static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ - return 0; -} - -static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) -{ - return icatch_sensor_set_auto_focus(client, WqCmd_af_update_zone,zone_tm_pos); -} - -/* -face defect call back -*/ -static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ - return 0; -} - -/* -* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some -* initialization in the function. -*/ -static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) -{ - spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; - spsensor->isp_priv_info.focus_zone.lx = 256; - spsensor->isp_priv_info.focus_zone.rx = 768; - spsensor->isp_priv_info.focus_zone.ty = 256; - spsensor->isp_priv_info.focus_zone.dy = 768; - spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; - - spsensor->isp_priv_info.outputSize = OUTPUT_QUXGA|OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSizeNum = 2; - spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; - spsensor->isp_priv_info.supportedSize[1] = OUTPUT_QUXGA; - return; -} - -/* -* :::::WARNING::::: -* It is not allowed to modify the following code -*/ - -sensor_init_parameters_default_code(); - -sensor_v4l2_struct_initialization(); - -sensor_probe_default_code(); - -sensor_remove_default_code(); - -sensor_driver_default_module_code(); - - - - diff --git a/drivers/media/video/icatch7002/icatch_spi_host.c b/drivers/media/video/icatch7002/icatch_spi_host.c deleted file mode 100755 index 4d220a0b4b23..000000000000 --- a/drivers/media/video/icatch7002/icatch_spi_host.c +++ /dev/null @@ -1,82 +0,0 @@ -/*icatch host mode ,spi device - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "icatch_spi_host.h" -#include -struct spi_device* g_icatch_spi_dev = NULL; - -static int __devinit spi_icatch_probe(struct spi_device *spi) -{ - struct spi_test_data *spi_test_data; - int ret = 0; - - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - ret = spi_setup(spi); - if (ret < 0){ - dev_err(spi, "ERR: fail to setup spi\n"); - return -1; - } - - g_icatch_spi_dev = spi; - - printk("%s:bus_num=%d,ok\n",__func__,spi->master->bus_num); - - return ret; - -} - - -static struct spi_driver spi_icatch_driver = { - .driver = { - .name = "spi_icatch", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = spi_icatch_probe, -}; - -static struct miscdevice spi_test_icatch = { - .minor = MISC_DYNAMIC_MINOR, - .name = "spi_misc_icatch", -}; - -static int __init spi_icatch_init(void) -{ - spi_register_board_info(board_spi_icatch_devices, ARRAY_SIZE(board_spi_icatch_devices)); - - misc_register(&spi_test_icatch); - return spi_register_driver(&spi_icatch_driver); -} - -static void __exit spi_icatch_exit(void) -{ - - misc_deregister(&spi_test_icatch); - return spi_unregister_driver(&spi_icatch_driver); -} -module_init(spi_icatch_init); -module_exit(spi_icatch_exit); - - diff --git a/drivers/media/video/icatch7002/icatch_spi_host.h b/drivers/media/video/icatch7002/icatch_spi_host.h deleted file mode 100755 index 70a73c618f46..000000000000 --- a/drivers/media/video/icatch7002/icatch_spi_host.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ICATCH_SPI_HOST_H -#define ICATCH_SPI_HOST_H -#include "../../../spi/rk29_spim.h" -#include - -static struct rk29xx_spi_chip spi_icatch = { - //.poll_mode = 1, - .enable_dma = 0, -}; -//user must define this struct according to hardware config -static struct spi_board_info board_spi_icatch_devices[] = { - { - .modalias = "spi_icatch", - .bus_num = 0, //0 or 1 - .max_speed_hz = 24*1000*1000, - .chip_select = 0, - .mode = SPI_MODE_0, - .controller_data = &spi_icatch, - }, - -}; -#endif - From 11905fc1915214b771b56fa680ee977c0ff2e1bf Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Fri, 26 Jan 2018 17:02:03 +0800 Subject: [PATCH 160/427] drm/rockchip: fix hdmi kernel logo display error when have two connector, show_loader_logo() must free the unused connect resources. Change-Id: Ic0ad98988d7dbae8143087cf00e3c5914281188a Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++++++++------------ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index da9b8ae9d3e6..b61acb058745 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -66,6 +66,8 @@ struct rockchip_drm_mode_set { int vdisplay; int vrefresh; int flags; + int crtc_hsync_end; + int crtc_vsync_end; int left_margin; int right_margin; @@ -393,6 +395,12 @@ of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route) if (!of_property_read_u32(route, "video,vdisplay", &val)) set->vdisplay = val; + if (!of_property_read_u32(route, "video,crtc_hsync_end", &val)) + set->crtc_hsync_end = val; + + if (!of_property_read_u32(route, "video,crtc_vsync_end", &val)) + set->crtc_vsync_end = val; + if (!of_property_read_u32(route, "video,vrefresh", &val)) set->vrefresh = val; @@ -468,12 +476,14 @@ int setup_initial_state(struct drm_device *drm_dev, dev_err(drm_dev->dev, "connector[%s] can't found any modes\n", connector->name); ret = -EINVAL; - goto error; + goto error_conn; } list_for_each_entry(mode, &connector->modes, head) { if (mode->hdisplay == set->hdisplay && mode->vdisplay == set->vdisplay && + mode->crtc_hsync_end == set->crtc_hsync_end && + mode->crtc_vsync_end == set->crtc_vsync_end && drm_mode_vrefresh(mode) == set->vrefresh && mode->flags == set->flags) { found = 1; @@ -483,30 +493,15 @@ int setup_initial_state(struct drm_device *drm_dev, } if (!found) { - list_for_each_entry(mode, &connector->modes, head) { - if (mode->type & DRM_MODE_TYPE_PREFERRED) { - found = 1; - break; - } - } - - if (!found) { - mode = list_first_entry_or_null(&connector->modes, - struct drm_display_mode, - head); - if (!mode) { - pr_err("failed to find available modes\n"); - ret = -EINVAL; - goto error; - } - } + ret = -EINVAL; + goto error_conn; } set->mode = mode; crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) { ret = PTR_ERR(crtc_state); - goto error; + goto error_conn; } drm_mode_copy(&crtc_state->adjusted_mode, mode); @@ -515,11 +510,11 @@ int setup_initial_state(struct drm_device *drm_dev, } else { ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); if (ret) - goto error; + goto error_conn; ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); if (ret) - goto error; + goto error_conn; crtc_state->active = true; @@ -530,12 +525,12 @@ int setup_initial_state(struct drm_device *drm_dev, if (!set->fb) { ret = 0; - goto error; + goto error_crtc; } primary_state = drm_atomic_get_plane_state(state, crtc->primary); if (IS_ERR(primary_state)) { ret = PTR_ERR(primary_state); - goto error; + goto error_crtc; } hdisplay = mode->hdisplay; @@ -573,16 +568,16 @@ int setup_initial_state(struct drm_device *drm_dev, return 0; -error: +error_crtc: + if (priv->crtc_funcs[pipe] && priv->crtc_funcs[pipe]->loader_protect) + priv->crtc_funcs[pipe]->loader_protect(crtc, false); +error_conn: if (funcs->loader_protect) funcs->loader_protect(connector, false); connector->loader_protect = false; if (encoder_funcs->loader_protect) encoder_funcs->loader_protect(conn_state->best_encoder, false); conn_state->best_encoder->loader_protect = false; - if (priv->crtc_funcs[pipe] && - priv->crtc_funcs[pipe]->loader_protect) - priv->crtc_funcs[pipe]->loader_protect(crtc, false); return ret; } From 878bfd1fe68ff4322c96202743bf29d8fe83936c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 31 Jan 2018 20:31:07 +0800 Subject: [PATCH 161/427] sound/soc/codecs: remove unused rt5625.c.enc Change-Id: Id5ea219c9faae173096fb4532772f90238ea53b8 Signed-off-by: Tao Huang --- sound/soc/codecs/rt5625.c.enc | 2491 --------------------------------- 1 file changed, 2491 deletions(-) delete mode 100644 sound/soc/codecs/rt5625.c.enc diff --git a/sound/soc/codecs/rt5625.c.enc b/sound/soc/codecs/rt5625.c.enc deleted file mode 100644 index 78877c8eaa0b..000000000000 --- a/sound/soc/codecs/rt5625.c.enc +++ /dev/null @@ -1,2491 +0,0 @@ -/* -RK1 SPKOUT Mux -RK11 HP Mixer -RK12 SPK Mixer -RK13 MoNo Mixer -RK2 SPKOUT Playback Switch -RK3 SPKOUT Playback Volume -RK4 PCM Playback Volume -RK5 Left HP Mixer -RK6 Right HP Mixer -RK7 HPLOUT Mux -RK71 HPL Mixer -RK8 HPROUT Mux -RK81 HPR Mixer -RK9 HPOUT Playback Switch -RKA HPOUT Playback Volume -RKB AUXOUT Mux -RKC AUXOUT Playback Switch -RKD AUXOUT Playback Volume -RKE Left Rec Mixer -RKF Right Rec Mixer -RKG DAC Mixer Playback Switch -RKH HIFI DAC Playback Switch -RKI Mic1 Playback Switch -RKJ Phone Playback Switch -RKK Mic1 Capture Switch -RKL Phone Capture Switch -RKM Voice DAC Playback Switch -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rt5625.h" - -#if REALTEK_HWDEP - -#include -#include - -#endif - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) do { } while (0) -#endif - -#define AUDIO_NAME "rt5625" -#define RT5625_VERSION "0.03 alsa 1.0.21" -#define ALSA_SOC_VERSION "1.0.21" - -#define RT5625_EQ_FUNC_ENA 0 - -static void hp_depop_mode2(struct snd_soc_codec *codec); -static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute); - -struct rt5625_priv { - unsigned int stereo_sysclk; - unsigned int voice_sysclk; -}; - -struct rt5625_init_reg { - u8 reg_index; - u16 reg_value; -}; - -static struct rt5625_init_reg rt5625_init_list[] = { - - {RT5625_HP_OUT_VOL , 0x8888}, //default is -12db - {RT5625_SPK_OUT_VOL , 0x8080}, //default is 0db - {RT5625_DAC_AND_MIC_CTRL , 0xee03}, //DAC to hpmixer - {RT5625_OUTPUT_MIXER_CTRL , 0x0748}, //all output from hpmixer - {RT5625_MIC_CTRL , 0x0500}, //mic boost 20db - {RT5625_ADC_REC_MIXER , 0x3f3f}, //record source from mic1 - {RT5625_GEN_CTRL_REG1 , 0x0c0a}, //speaker vdd ratio is 1 - {RT5625_ADC_REC_GAIN , 0xd5d5}, //gain 15db of ADC by default - -}; - -#define RT5625_INIT_REG_NUM ARRAY_SIZE(rt5625_init_list) - -#if (RT5625_EQ_FUNC_ENA==1) -//************************************************************************************************* -//eq table -//************************************************************************************************* -enum -{ - NORMAL=0, - CLUB, - DANCE, - LIVE, - POP, - ROCK, - OPPO, - TREBLE, - BASS -}; - -typedef struct _HW_EQ_PRESET -{ - u16 HwEqType; - u16 EqValue[14]; - u16 HwEQCtrl; - -}HW_EQ_PRESET; - - -HW_EQ_PRESET HwEq_Preset[]={ -/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0x6e*/ - {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000}, - {CLUB ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000},0x800E}, - {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000},0x800F}, - {LIVE ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000},0x800F}, - {POP ,{0x1EB5,0xFCB6,0xC1D4,0x1E5D,0x0E23,0xD92E,0x16E6,0xFCB6,0x0000,0x0969,0xF988,0x0436,0x0000},0x800F}, - {ROCK ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000},0x800F}, - {OPPO ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x800F}, - {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699},0x8010}, - {BASS ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x8001}, - -}; - -#endif -//************************************************************************************************* -//************************************************************************************************* - -/* - * bit[0] for linein playback switch - * bit[1] phone - * bit[2] mic1 - * bit[3] mic2 - * bit[4] vopcm - * - */ -#define HPL_MIXER 0x80 -#define HPR_MIXER 0x82 -static unsigned int reg80 = 0, reg82 = 0; - -/* - * bit[0][1][2] use for aec control - * bit[3] for none - * bit[4] for SPKL pga - * bit[5] for SPKR pga - * bit[6] for hpl pga - * bit[7] for hpr pga - * bit[8] for dump dsp - * bit[12~15] for eq function - */ - #define VIRTUAL_REG_FOR_MISC_FUNC 0x84 -static unsigned int reg84 = 0; - - -static const u16 rt5625_reg[] = { - 0x59b4, 0x8080, 0x8080, 0x8080, /*reg00-reg06*/ - 0xc800, 0xe808, 0x1010, 0x0808, /*reg08-reg0e*/ - 0xe0ef, 0xcbcb, 0x7f7f, 0x0000, /*reg10-reg16*/ - 0xe010, 0x0000, 0x8008, 0x2007, /*reg18-reg1e*/ - 0x0000, 0x0000, 0x00c0, 0xef00, /*reg20-reg26*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*reg28-reg2e*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*reg30-reg36*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*reg38-reg3e*/ - 0x0c0a, 0x0000, 0x0000, 0x0000, /*reg40-reg46*/ - 0x0029, 0x0000, 0xbe3e, 0x3e3e, /*reg48-reg4e*/ - 0x0000, 0x0000, 0x803a, 0x0000, /*reg50-reg56*/ - 0x0000, 0x0009, 0x0000, 0x3000, /*reg58-reg5e*/ - 0x3075, 0x1010, 0x3110, 0x0000, /*reg60-reg66*/ - 0x0553, 0x0000, 0x0000, 0x0000, /*reg68-reg6e*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*reg70-reg76*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*reg78-reg7e*/ -}; - - -Voice_DSP_Reg VODSP_AEC_Init_Value[]= -{ - {0x232C, 0x0025}, - {0x230B, 0x0001}, - {0x2308, 0x007F}, - {0x23F8, 0x4003}, - {0x2301, 0x0002}, - {0x2328, 0x0001}, - {0x2304, 0x00FA}, - {0x2305, 0x0500}, - {0x2306, 0x4000}, - {0x230D, 0x0900}, - {0x230E, 0x0280}, - {0x2312, 0x00B1}, - {0x2314, 0xC000}, - {0x2316, 0x0041}, - {0x2317, 0x2200}, - {0x2318, 0x0C00}, - {0x231D, 0x0050}, - {0x231F, 0x4000}, - {0x2330, 0x0008}, - {0x2335, 0x000A}, - {0x2336, 0x0004}, - {0x2337, 0x5000}, - {0x233A, 0x0300}, - {0x233B, 0x0030}, - {0x2341, 0x0008}, - {0x2343, 0x0800}, - {0x2352, 0x7FFF}, - {0x237F, 0x0400}, - {0x23A7, 0x2800}, - {0x22CE, 0x0400}, - {0x22D3, 0x1500}, - {0x22D4, 0x2800}, - {0x22D5, 0x3000}, - {0x2399, 0x2800}, - {0x230C, 0x0000}, //to enable VODSP AEC function -}; - - -#define SET_VODSP_REG_INIT_NUM ARRAY_SIZE(VODSP_AEC_Init_Value) -static struct snd_soc_device *rt5625_socdev; - -static inline unsigned int rt5625_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - if (reg > 0x7e) - return 0; - return cache[reg / 2]; -} - - -static unsigned int rt5625_read_hw_reg(struct snd_soc_codec *codec, unsigned int reg) -{ - u8 data[2] = {0}; - unsigned int value = 0x0; - - data[0] = reg; - - i2c_master_reg8_recv(codec->control_data,reg,data,2,100 * 1000); - - value = (data[0]<<8) | data[1]; - - DBG(KERN_INFO "rt5625_read ok, reg = %x, value = %x\n", reg, value); - - return value; -} - - -static unsigned int rt5625_read(struct snd_soc_codec *codec, unsigned int reg) -{ - if ((reg == 0x80) - || (reg == 0x82) - || (reg == 0x84)) - return (reg == 0x80) ? reg80 : ((reg == 0x82) ? reg82 : reg84); - - return rt5625_read_hw_reg(codec, reg); -} - - -static inline void rt5625_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg > 0x7E) - return; - cache[reg / 2] = value; -} - -static int rt5625_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[3]; - unsigned int *regvalue = NULL; - - data[0] = reg; - data[1] = (value & 0xff00) >> 8; - data[2] = value & 0x00ff; - - if ((reg == 0x80) - || (reg == 0x82) - || (reg == 0x84)) - { - regvalue = ((reg == 0x80) ? ®80 : ((reg == 0x82) ? ®82 : ®84)); - *regvalue = value; - DBG("rt5625_write ok, reg = %x, value = %x\n", reg, value); - return 0; - } - rt5625_write_reg_cache(codec, reg, value); - - if (codec->hw_write(codec->control_data, data, 3) == 3) - { - DBG("rt5625_write ok, reg = %x, value = %x\n", reg, value); - return 0; - } - else - { - printk("rt5625_write fail\n"); - return -EIO; - } -} - -int rt5625_write_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask) -{ - - unsigned char RetVal=0; - unsigned int CodecData; - - DBG("rt5625_write_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask); - - if(!mask) - return 0; - - if(mask!=0xffff) - { - CodecData=rt5625_read(codec,reg); - CodecData&=~mask; - CodecData|=(value&mask); - RetVal=rt5625_write(codec,reg,CodecData); - } - else - { - RetVal=rt5625_write(codec,reg,value); - } - - return RetVal; -} - - -void rt5625_write_index(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - - rt5625_write(codec,0x6a,reg); - rt5625_write(codec,0x6c,value); -} - -unsigned int rt5625_read_index(struct snd_soc_codec *codec, unsigned int reg) -{ - unsigned int value = 0x0; - rt5625_write(codec,0x6a,reg); - value=rt5625_read(codec,0x6c); - - return value; -} - -void rt5625_write_index_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask) -{ - -// unsigned char RetVal=0; - unsigned int CodecData; - - DBG("rt5625_write_index_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask); - - if(!mask) - return; - - if(mask!=0xffff) - { - CodecData=rt5625_read_index(codec,reg); - CodecData&=~mask; - CodecData|=(value&mask); - rt5625_write_index(codec,reg,CodecData); - } - else - { - rt5625_write_index(codec,reg,value); - } -} - -//#define rt5625_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value) - -#define rt5625_reset(c) rt5625_write(c, RT5625_RESET, 0) - -/*read/write dsp reg*/ -static int rt5625_wait_vodsp_i2c_done(struct snd_soc_codec *codec) -{ - unsigned int checkcount = 0, vodsp_data; - - vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD); - while(vodsp_data & VODSP_BUSY) - { - if(checkcount > 10) - return -EBUSY; - vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD); - checkcount ++; - } - return 0; -} - -static int rt5625_write_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg, unsigned int value) -{ - int ret = 0; - - if(ret != rt5625_wait_vodsp_i2c_done(codec)) - return -EBUSY; - - rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg); - rt5625_write(codec, RT5625_VODSP_REG_DATA, value); - rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_WRITE_ENABLE | VODSP_CMD_MW); - mdelay(10); - return ret; - -} - -static unsigned int rt5625_read_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg) -{ - int ret = 0; - unsigned int nDataH, nDataL; - unsigned int value; - - if(ret != rt5625_wait_vodsp_i2c_done(codec)) - return -EBUSY; - - rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg); - rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_MR); - - if (ret != rt5625_wait_vodsp_i2c_done(codec)) - return -EBUSY; - rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x26); - rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR); - - if(ret != rt5625_wait_vodsp_i2c_done(codec)) - return -EBUSY; - nDataH = rt5625_read(codec, RT5625_VODSP_REG_DATA); - rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x25); - rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR); - - if(ret != rt5625_wait_vodsp_i2c_done(codec)) - return -EBUSY; - nDataL = rt5625_read(codec, RT5625_VODSP_REG_DATA); - value = ((nDataH & 0xff) << 8) |(nDataL & 0xff); - DBG("%s vodspreg=0x%x, value=0x%x\n", __func__, vodspreg, value); - return value; -} - -static int rt5625_reg_init(struct snd_soc_codec *codec) -{ - int i; - - for (i = 0; i < RT5625_INIT_REG_NUM; i++) - rt5625_write(codec, rt5625_init_list[i].reg_index, rt5625_init_list[i].reg_value); - - return 0; -} - -//************************************************************************************************* -//************************************************************************************************* -#if (RT5625_EQ_FUNC_ENA==1) -//eq function -static void rt5625_update_eqmode(struct snd_soc_codec *codec, int mode) -{ - u16 HwEqIndex=0; - - if(mode==NORMAL) - { - /*clear EQ parameter*/ - for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++) - { - rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]); - } - - rt5625_write_mask(codec, 0x6e,0x0,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF); /*disable EQ block*/ - } - else - { - /*Fill EQ parameter*/ - for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++) - { - rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]); - } - - //enable EQ block - rt5625_write_mask(codec, 0x6e,HwEq_Preset[mode].HwEQCtrl,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF); - - //update EQ parameter - rt5625_write_mask(codec, 0x6e,0x0080,0x0080); - } -} - - -static int rt5625_eq_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC); - int rt5625_mode=((Virtual_reg)&0xf000)>>12; - - if ( rt5625_mode == ucontrol->value.integer.value[0]) - return 0; - - rt5625_update_eqmode(codec, ucontrol->value.enumerated.item[0]); - - Virtual_reg &= 0x0fff; - Virtual_reg |= (ucontrol->value.integer.value[0])<<12; - rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg); - - return 0; -} -#endif -//************************************************************************************************* -//************************************************************************************************* -static const char *rt5625_aec_path_sel[] = {"aec func disable","aec func for pcm in/out", - "aec func for iis in/out","aec func for analog in/out"}; /*0*/ -static const char *rt5625_spk_out_sel[] = {"Class AB", "Class D"}; /*1*/ -static const char *rt5625_spk_l_source_sel[] = {"LPRN", "LPRP", "LPLN", "MM"}; /*2*/ -static const char *rt5625_spkmux_source_sel[] = {"VMID", "RK11", - "RK12", "RK13"}; /*3*/ -static const char *rt5625_hplmux_source_sel[] = {"VMID","RK71"}; /*4*/ -static const char *rt5625_hprmux_source_sel[] = {"VMID","RK81"}; /*5*/ -static const char *rt5625_auxmux_source_sel[] = {"VMID", "RK11", - "RK12", "RK13"}; /*6*/ -static const char *rt5625_spkamp_ratio_sel[] = {"2.25 Vdd", "2.00 Vdd", - "1.75 Vdd", "1.50 Vdd", "1.25 Vdd", "1.00 Vdd"}; /*7*/ -static const char *rt5625_mic1_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"}; /*8*/ -static const char *rt5625_mic2_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"}; /*9*/ -static const char *rt5625_dmic_boost_sel[] = {"Bypass", "+6db", "+12db", "+18db", - "+24db", "+30db", "+36db", "+42db"}; /*10*/ -static const char *rt5625_adcr_func_sel[] = {"Stereo ADC", "Voice ADC", - "VoDSP Interface", "PDM Slave Interface"}; /*11*/ -#if (RT5625_EQ_FUNC_ENA==1) -static const char *rt5625_eq_sel[] = {"NORMAL", "CLUB","DANCE", "LIVE","POP", /*12*/ - "ROCK", "OPPO", "TREBLE", "BASS"}; -#endif - -static const struct soc_enum rt5625_enum[] = { - -SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 0, 4, rt5625_aec_path_sel), /*0*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 13, 2, rt5625_spk_out_sel), /*1*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 14, 4, rt5625_spk_l_source_sel), /*2*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 10, 4, rt5625_spkmux_source_sel),/*3*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 9, 2, rt5625_hplmux_source_sel), /*4*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 8, 2, rt5625_hprmux_source_sel),/*5*/ -SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 6, 4, rt5625_auxmux_source_sel),/*6*/ -SOC_ENUM_SINGLE(RT5625_GEN_CTRL_REG1, 1, 6, rt5625_spkamp_ratio_sel), /*7*/ -SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 10, 4, rt5625_mic1_boost_sel), /*8*/ -SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 8, 4, rt5625_mic2_boost_sel), /*9*/ -SOC_ENUM_SINGLE(RT5625_DMIC_CTRL, 0, 8, rt5625_dmic_boost_sel), /*10*/ -SOC_ENUM_SINGLE(RT5625_DAC_ADC_VODAC_FUN_SEL, 4, 4, rt5625_adcr_func_sel), /*11*/ -#if (RT5625_EQ_FUNC_ENA==1) -SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 12, 9, rt5625_eq_sel), /*EQ mode select mode 12*/ -#endif -}; - - - -//***************************************************************************** -//function:Enable the Voice PCM interface Path -//***************************************************************************** -static int ConfigPcmVoicePath(struct snd_soc_codec *codec,unsigned int bEnableVoicePath,unsigned int mode) -{ - - if(bEnableVoicePath) - { - //Power on DAC reference - rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,PWR_DAC_REF|PWR_VOICE_DF2SE,PWR_DAC_REF|PWR_VOICE_DF2SE); - //Power on Voice DAC/ADC - rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,PWR_VOICE_CLOCK,PWR_VOICE_CLOCK); - //routing voice to HPMixer - rt5625_write_mask(codec,RT5625_VOICE_DAC_OUT_VOL,0,M_V_DAC_TO_HP_MIXER); - - switch(mode) - { - case PCM_SLAVE_MODE_B: //8kHz sampling rate,16 bits PCM mode and Slave mode,PCM mode is B,MCLK=24.576MHz from Oscillator. - //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00000,PSKEY_FORMAT=0x0060 - - //Enable GPIO 1,3,4,5 to voice interface - //Set I2S to Slave mode - //Voice I2S SYSCLK Source select Main SYSCLK - //Set voice I2S VBCLK Polarity to Invert - //Set Data length to 16 bit - //set Data Fomrat to PCM mode B - //the register 0x36 value's should is 0xC083 - rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC083); - - //Set LRCK voice select divide 32 - //set voice blck select divide 6 and 8 - //voice filter clock divide 3 and 16 - //the register 0x64 value's should is 0x5524 - rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524); - - break; - - case PCM_SLAVE_MODE_A: //8kHz sampling rate,16 bits PCM and Slave mode,PCM mode is A,MCLK=24.576MHz from Oscillator. - //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00004,PSKEY_FORMAT=0x0060 - - //Enable GPIO 1,3,4,5 to voice interface - //Set I2S to Slave mode - //Voice I2S SYSCLK Source select Main SYSCLK - //Set voice i2s VBCLK Polarity to Invert - //Set Data length to 16 bit - //set Data Fomrat to PCM mode A - //the register 0x36 value's should is 0xC082 - rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC082); - - //Set LRCK voice select divide 64 - //set voice blck select divide 6 and 8 - //voice filter clock divide 3 and 16 - //the register 0x64 value's should is 0x5524 - rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524); - - break; - - case PCM_MASTER_MODE_B: //8kHz sampling rate,16 bits PCM and Master mode,PCM mode is B,Clock from PLL OUT - //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08000002,PSKEY_FORMAT=0x0060 - - //Enable GPIO 1,3,4,5 to voice interface - //Set I2S to master mode - //Set voice i2s VBCLK Polarity to Invert - //Set Data length to 16 bit - //set Data Fomrat to PCM mode B - //the register 0x36 value's should is 0x8083 - rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0x8083); - - //Set LRCK voice select divide 64 - //set voice blck select divide 6 and 8 - //voice filter clock divide 3 and 16 - //the register 0x64 value's should is 0x5524 - rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524); - - break; - - default: - //do nothing - break; - - } - } - else - { - //Power down Voice Different to sing-end power - rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,0,PWR_VOICE_DF2SE); - //Power down Voice DAC/ADC - rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,0,PWR_VOICE_CLOCK); - //Disable Voice PCM interface - rt5625_write_mask(codec,RT5625_EXTEND_SDP_CTRL,0,EXT_I2S_FUNC_ENABLE); - } - - return 0; -} - -static int init_vodsp_aec(struct snd_soc_codec *codec) -{ - int i; - int ret = 0; - - /*disable LDO power*/ - rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE); - mdelay(20); - rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA); - /*enable LDO power and set output voltage to 1.2V*/ - rt5625_write_mask(codec, RT5625_LDO_CTRL,LDO_ENABLE|LDO_OUT_VOL_CTRL_1_20V,LDO_ENABLE|LDO_OUT_VOL_CTRL_MASK); - mdelay(20); - /*enable power of VODSP I2C interface*/ - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP); - mdelay(1); - rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_RST_MODE_ENA); /*Reset VODSP*/ - mdelay(1); - rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_RST_MODE_ENA,VODSP_NO_RST_MODE_ENA); /*set VODSP to non-reset status*/ - mdelay(20); - - /*initize AEC paramter*/ - for(i = 0; i < SET_VODSP_REG_INIT_NUM; i++) - { - ret = rt5625_write_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex,VODSP_AEC_Init_Value[i].VoiceDSPValue); - if(ret) - return -EIO; - } - - schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - - return 0; -} - -//*********************************************************************************************** -//function:Enable/Disable the vodsp interface Path -//For system clock only suport specific clock,realtek suggest customer to use 24.576Mhz or 22.5792Mhz -//clock fro MCLK(MCLK=48k*512 or 44.1k*512Mhz) -//*********************************************************************************************** -static int set_vodsp_aec_path(struct snd_soc_codec *codec, unsigned int mode) -{ - - switch(mode) - { - - case PCM_IN_PCM_OUT: - //set PCM format - ConfigPcmVoicePath(codec,1,PCM_MASTER_MODE_B); - //set AEC path - rt5625_write_mask(codec, 0x26,0x0300,0x0300); - rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_VOICE|VOICE_PCM_S_SEL_AEC_TXDP - ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK); - rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC - ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK); - rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_8K,VODSP_LRCK_SEL_MASK); - rt5625_write_mask(codec, 0x26,0x0000,0x0300); - //set input&output path and power - rt5625_write_mask(codec, 0x3a,0x0c8f,0x0c8f);//power on related bit - rt5625_write_mask(codec, 0x3c,0xa4cb,0xa4cb);//power on related bit - rt5625_write_mask(codec, 0x3e,0x3302,0xf302);//power on related bit - - rt5625_write(codec, 0x10, 0xee0f);//mute DAC to hpmixer - rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode - rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db - rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db - rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R - rt5625_write(codec, 0x18, 0xa010);//VoDAC to speakerMixer,0db - rt5625_write(codec, 0x1c, 0x8808);//speaker source from speakermixer - - rt5625_write_mask(codec, 0x02,0x0000,0x8080); //unmute speaker - - break; - - - case ANALOG_IN_ANALOG_OUT: - rt5625_write_mask(codec, 0x26,0x0300,0x0300); - rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_ADCL|VOICE_PCM_S_SEL_AEC_TXDP - ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK); - rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC|DAC_FUNC_SEL_VODSP_TXDP|ADCL_FUNC_SEL_VODSP - ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK|DAC_FUNC_SEL_MASK|ADCL_FUNC_SEL_MASK); - rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK); - rt5625_write_mask(codec, 0x26,0x0000,0x0300); - //set input&output path and power - rt5625_write_mask(codec, 0x3a,0xcc8f,0xcc8f);//power on related bit - rt5625_write_mask(codec, 0x3c,0xa7cf,0xa7cf);//power on related bit - rt5625_write_mask(codec, 0x3e,0xf312,0xf312);//power on related bit - - rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode - rt5625_write(codec, 0x08, 0xe800);//set phone in to differential mode - rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db - rt5625_write(codec, 0x14, 0x773f);//Mic1->ADCMixer_R,phone in-->ADCMixer_L - rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db - rt5625_write(codec, 0x1c, 0x88c8);//speaker from spkmixer,monoOut from monoMixer - rt5625_write(codec, 0x18, 0xA010);//unmute VoDAC to spkmixer - rt5625_write(codec, 0x10, 0xee0e);//unmute DAC to monoMixer - rt5625_write(codec, 0x62, 0x2222); - rt5625_write(codec, 0x64, 0x3122); - rt5625_write_mask(codec, 0x02,0x0000,0x8080); //unmute speaker - rt5625_write_mask(codec, 0x06,0x0000,0x8080); //unmute auxout - break; - - case DAC_IN_ADC_OUT: - rt5625_write_mask(codec, 0x26,0x0300,0x0300); - rt5625_write_mask(codec,RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|DAC_FUNC_SEL_VODSP_TXDC - ,ADCR_FUNC_SEL_MASK|DAC_FUNC_SEL_MASK); - rt5625_write_mask(codec,RT5625_VODSP_PDM_CTL,VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_SRC1|REC_S_SEL_SRC2, - VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|REC_S_SEL_MASK); - rt5625_write_mask(codec,RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK); - rt5625_write_mask(codec, 0x26,0x0000,0x0300); - //set input&output path and power - rt5625_write_mask(codec, 0x3a,0xcc0f,0xcc0f);//power on related bit - rt5625_write_mask(codec, 0x3c,0xa7cb,0xa7cb);//power on related bit - rt5625_write_mask(codec, 0x3e,0x3302,0x3302);//power on related bit - - rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode - rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db - rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R - rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db - rt5625_write(codec, 0x1c, 0x8808);//speaker out from spkMixer - rt5625_write(codec, 0x10, 0xee0d);//unmute DAC to spkMixer - rt5625_write(codec, 0x60, 0x3075); - rt5625_write(codec, 0x62, 0x1010); - rt5625_write_mask(codec, 0x02,0x0000,0x8080); //unmute speaker - - break; - - case VODSP_AEC_DISABLE: - default: - rt5625_write_mask(codec, 0x02,0x8080,0x8080);//mute speaker out - rt5625_write_mask(codec, 0x06,0x8080,0x8080);//mute auxout - rt5625_write(codec, 0x22, 0x0500);//Mic boost 20db by default - rt5625_write(codec, 0x14, 0x3f3f);//record from Mic1 by default - rt5625_write(codec, 0x12, 0xD5D5);//ADC_Mixer_R boost 15 db by default - rt5625_write(codec, 0x1c, 0x0748);//all output from HPmixer by default - rt5625_write(codec, 0x10, 0xee03);//DAC to HPmixer by default - rt5625_write(codec, 0x18, 0xe010);//mute VoDAC to mixer by default - rt5625_write_mask(codec, 0x26,0x0300,0x0300); - /*set stereo DAC&Voice DAC&Stereo ADC function select to default*/ - rt5625_write(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,0); - /*set VODSP&PDM Control to default*/ - rt5625_write(codec, RT5625_VODSP_PDM_CTL,0); - rt5625_write_mask(codec, 0x26,0x0000,0x0300); - rt5625_write_mask(codec, 0x3e,0x0000,0xf312);//power down related bit - rt5625_write_mask(codec, 0x3a,0x0000,0xcc8d);//power down related bit - rt5625_write_mask(codec, 0x3c,0x0000,0x07cf);//power down related bit - - - break; - } - - return 0; -} - -static int enable_vodsp_aec(struct snd_soc_codec *codec, unsigned int VodspAEC_En, unsigned int AEC_mode) -{ - int ret = 0; - - - if (VodspAEC_En != 0) - { - - //enable power of VODSP I2C interface & VODSP interface - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP); - //enable power of VODSP I2S interface - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1,PWR_I2S_INTERFACE,PWR_I2S_INTERFACE); - //select input/output of VODSP AEC - set_vodsp_aec_path(codec, AEC_mode); - - } - else - { - //disable VODSP AEC path - set_vodsp_aec_path(codec, VODSP_AEC_DISABLE); - //set VODSP AEC to power down mode - rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_PD_MODE_ENA); - //disable power of VODSP I2C interface & VODSP interface - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,0,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP); - } - - return ret; -} - -static void rt5625_aec_config(struct snd_soc_codec *codec, unsigned int mode) -{ - DBG("rt5625_aec_config %d\n",mode); - - if (mode == VODSP_AEC_DISABLE) - { - enable_vodsp_aec(codec,0, mode); - /*disable LDO power*/ - rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE); - } - else - { - init_vodsp_aec(codec); - - enable_vodsp_aec(codec,1, mode); - } -} -//**************************************************************************************************************** -//* -//*function:disable rt5625's function. -//* -//* -//**************************************************************************************************************** -static int rt5625_func_aec_disable(struct snd_soc_codec *codec,int mode) -{ - - switch(mode) - { - case RT5625_AEC_PCM_IN_OUT: - case RT5625_AEC_IIS_IN_OUT: - case RT5625_AEC_ANALOG_IN_OUT: - - rt5625_aec_config(codec,VODSP_AEC_DISABLE); //disable AEC function and path - - break; - - default: - - break; - } - - return 0; -} - - -static int rt5625_get_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - /*cause we choose bit[0][1] to store the mode type*/ - int mode = (rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC)) & 0x03; - - ucontrol->value.integer.value[0] = mode; - return 0; -} - - -static int rt5625_set_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC); - int rt5625_mode=(Virtual_reg)&0x03; - - DBG("rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg); - - if ( rt5625_mode == ucontrol->value.integer.value[0]) - return 0; - - switch(ucontrol->value.integer.value[0]) - { - case RT5625_AEC_PCM_IN_OUT: - - rt5625_aec_config(codec,PCM_IN_PCM_OUT);//enable AEC PCM in/out function and path - - break; - - case RT5625_AEC_IIS_IN_OUT: - - rt5625_aec_config(codec,DAC_IN_ADC_OUT);//enable AEC IIS in/out function and path - - break; - - case RT5625_AEC_ANALOG_IN_OUT: - - rt5625_aec_config(codec,ANALOG_IN_ANALOG_OUT);//enable AEC analog in/out function and path - - break; - - case RT5625_AEC_DISABLE: - - rt5625_func_aec_disable(codec,rt5625_mode); //disable previous select function. - - break; - - default: - - break; - } - - Virtual_reg &= 0xfffc; - Virtual_reg |= (ucontrol->value.integer.value[0]); - rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg); - - DBG("2rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg); - return 0; -} - -static int rt5625_dump_dsp_reg(struct snd_soc_codec *codec) -{ - int i; - - rt5625_write_mask(codec, RT5625_VODSP_CTL, VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA); - for (i = 0; i < SET_VODSP_REG_INIT_NUM; i++) { - rt5625_read_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex); - } - return 0; -} - - -static int rt5625_dump_dsp_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC); - - mode &= ~(0x01 << 8); - mode |= (ucontrol->value.integer.value[0] << 8); - rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, mode); - rt5625_dump_dsp_reg(codec); - - return 0; -} - -static const struct snd_kcontrol_new rt5625_snd_controls[] = { -SOC_ENUM_EXT("rt5625 aec mode sel", rt5625_enum[0], rt5625_get_dsp_mode, rt5625_set_dsp_mode), -SOC_ENUM("SPK Amp Type", rt5625_enum[1]), -SOC_ENUM("Left SPK Source", rt5625_enum[2]), -SOC_ENUM("SPK Amp Ratio", rt5625_enum[7]), -SOC_ENUM("Mic1 Boost", rt5625_enum[8]), -SOC_ENUM("Mic2 Boost", rt5625_enum[9]), -SOC_ENUM("Dmic Boost", rt5625_enum[10]), -SOC_ENUM("ADCR Func", rt5625_enum[11]), -SOC_DOUBLE("RK4", RT5625_STEREO_DAC_VOL, 8, 0, 63, 1), -SOC_DOUBLE("LineIn Playback Volume", RT5625_LINE_IN_VOL, 8, 0, 31, 1), -SOC_SINGLE("Phone Playback Volume", RT5625_PHONEIN_VOL, 8, 31, 1), -SOC_SINGLE("Mic1 Playback Volume", RT5625_MIC_VOL, 8, 31, 1), -SOC_SINGLE("Mic2 Playback Volume", RT5625_MIC_VOL, 0, 31, 1), -SOC_DOUBLE("PCM Capture Volume", RT5625_ADC_REC_GAIN, 8, 0, 31, 1), -SOC_DOUBLE("RK3", RT5625_SPK_OUT_VOL, 8, 0, 31, 1), -SOC_DOUBLE("RK2", RT5625_SPK_OUT_VOL, 15, 7, 1, 1), -SOC_DOUBLE("RKA", RT5625_HP_OUT_VOL, 8, 0, 31, 1), -SOC_DOUBLE("RK9", RT5625_HP_OUT_VOL, 15, 7, 1, 1), -SOC_DOUBLE("RKD", RT5625_AUX_OUT_VOL, 8, 0, 31, 1), -SOC_DOUBLE("RKC", RT5625_AUX_OUT_VOL, 15, 7, 1, 1), -SOC_DOUBLE("ADC Record Gain", RT5625_ADC_REC_GAIN, 8, 0, 31, 0), -SOC_SINGLE_EXT("VoDSP Dump", VIRTUAL_REG_FOR_MISC_FUNC, 8, 1, 0, - snd_soc_get_volsw, rt5625_dump_dsp_put), -#if (RT5625_EQ_FUNC_ENA==1) -SOC_ENUM_EXT("EQ Mode", rt5625_enum[12], snd_soc_get_enum_double, rt5625_eq_sel_put), -#endif -}; - -static int rt5625_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(rt5625_snd_controls); i++){ - err = snd_ctl_add(codec->card, - snd_soc_cnew(&rt5625_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - -static void hp_depop_mode2(struct snd_soc_codec *codec) -{ - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN); - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3, PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL, - PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL); - rt5625_write(codec, RT5625_MISC_CTRL,HP_DEPOP_MODE2_EN); - - DBG("delay 500 msec\n"); - - schedule_timeout_uninterruptible(msecs_to_jiffies(500)); - - - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP, - PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP); - //rt5625_write_mask(codec, RT5625_MISC_CTRL, 0, HP_DEPOP_MODE2_EN); - -} - -//enable depop function for mute/unmute -static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute) -{ - if(mute) - { - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN); - rt5625_write(codec, RT5625_MISC_CTRL,M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN); - //Mute headphone right/left channel - rt5625_write_mask(codec,RT5625_HP_OUT_VOL,RT_L_MUTE|RT_R_MUTE,RT_L_MUTE|RT_R_MUTE); - mdelay(50); - } - else - { - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN); - rt5625_write(codec, RT5625_MISC_CTRL, M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN); - //unMute headphone right/left channel - rt5625_write_mask(codec,RT5625_HP_OUT_VOL,0,RT_L_MUTE|RT_R_MUTE); - mdelay(50); - } - -} - - -/* - * _DAPM_ Controls - */ - /*Left ADC Rec mixer*/ - /*Left ADC Rec mixer*/ -static const struct snd_kcontrol_new rt5625_left_adc_rec_mixer_controls[] = { -SOC_DAPM_SINGLE("RKK", RT5625_ADC_REC_MIXER, 14, 1, 1), -SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 13, 1, 1), -SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 12, 1, 1), -SOC_DAPM_SINGLE("RKL", RT5625_ADC_REC_MIXER, 11, 1, 1), -SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 10, 1, 1), -SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 9, 1, 1), -SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 8, 1, 1), - -}; - -/*Left ADC Rec mixer*/ -static const struct snd_kcontrol_new rt5625_right_adc_rec_mixer_controls[] = { -SOC_DAPM_SINGLE("RKK", RT5625_ADC_REC_MIXER, 6, 1, 1), -SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 5, 1, 1), -SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 4, 1, 1), -SOC_DAPM_SINGLE("RKL", RT5625_ADC_REC_MIXER, 3, 1, 1), -SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 2, 1, 1), -SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 1, 1, 1), -SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 0, 1, 1), -}; - -/*Left hpmixer mixer*/ -static const struct snd_kcontrol_new rt5625_left_hp_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 15, 1, 1), -SOC_DAPM_SINGLE("LineIn Playback Switch", HPL_MIXER, 0, 1, 0), -SOC_DAPM_SINGLE("RKJ", HPL_MIXER, 1, 1, 0), -SOC_DAPM_SINGLE("RKI", HPL_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("Mic2 Playback Switch", HPL_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("RKM", HPL_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("RKH", RT5625_DAC_AND_MIC_CTRL, 3, 1, 1), - -}; - -/*Right hpmixer mixer*/ -static const struct snd_kcontrol_new rt5625_right_hp_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 7, 1, 1), -SOC_DAPM_SINGLE("LineIn Playback Switch", HPR_MIXER, 0, 1, 0), -SOC_DAPM_SINGLE("RKJ", HPR_MIXER, 1, 1, 0), -SOC_DAPM_SINGLE("RKI", HPR_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("Mic2 Playback Switch", HPR_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("RKM", HPR_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("RKH", RT5625_DAC_AND_MIC_CTRL, 2, 1, 1), - -}; - -/*mono mixer*/ -static const struct snd_kcontrol_new rt5625_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("ADCL Playback Switch", RT5625_ADC_REC_GAIN, 14, 1, 1), -SOC_DAPM_SINGLE("ADCR Playback Switch", RT5625_ADC_REC_GAIN, 6, 1, 1), -SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 13, 1, 1), -SOC_DAPM_SINGLE("RKI", RT5625_DAC_AND_MIC_CTRL, 13, 1, 1), -SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 9, 1, 1), -SOC_DAPM_SINGLE("RKG", RT5625_DAC_AND_MIC_CTRL, 0, 1, 1), -SOC_DAPM_SINGLE("RKM", RT5625_VOICE_DAC_OUT_VOL, 13, 1, 1), -}; - -/*speaker mixer*/ -static const struct snd_kcontrol_new rt5625_spk_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("RKJ", RT5625_PHONEIN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("RKI", RT5625_DAC_AND_MIC_CTRL, 14, 1, 1), -SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 10, 1, 1), -SOC_DAPM_SINGLE("RKG", RT5625_DAC_AND_MIC_CTRL, 1, 1, 1), -SOC_DAPM_SINGLE("RKM", RT5625_VOICE_DAC_OUT_VOL, 14, 1, 1), -}; - -static int mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int l, r; - - DBG("enter %s\n", __func__); - - l= rt5625_read(codec, HPL_MIXER); - r = rt5625_read(codec, HPR_MIXER); - - if ((l & 0x1) || (r & 0x1)) - rt5625_write_mask(codec, 0x0a, 0x0000, 0x8000); - else - rt5625_write_mask(codec, 0x0a, 0x8000, 0x8000); - - if ((l & 0x2) || (r & 0x2)) - rt5625_write_mask(codec, 0x08, 0x0000, 0x8000); - else - rt5625_write_mask(codec, 0x08, 0x8000, 0x8000); - - if ((l & 0x4) || (r & 0x4)) - rt5625_write_mask(codec, 0x10, 0x0000, 0x8000); - else - rt5625_write_mask(codec, 0x10, 0x8000, 0x8000); - - if ((l & 0x8) || (r & 0x8)) - rt5625_write_mask(codec, 0x10, 0x0000, 0x0800); - else - rt5625_write_mask(codec, 0x10, 0x0800, 0x0800); - - if ((l & 0x10) || (r & 0x10)) - rt5625_write_mask(codec, 0x18, 0x0000, 0x8000); - else - rt5625_write_mask(codec, 0x18, 0x8000, 0x8000); - - return 0; -} - - -/* - * bit[0][1] use for aec control - * bit[2][3] for ADCR func - * bit[4] for SPKL pga - * bit[5] for SPKR pga - * bit[6] for hpl pga - * bit[7] for hpr pga - */ -static int spk_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) - { - struct snd_soc_codec *codec = w->codec; - int reg; - - DBG("enter %s\n", __func__); - reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 4); - if ((reg >> 4) != 0x3 && reg != 0) - return 0; - - switch (event) - { - case SND_SOC_DAPM_POST_PMU: - DBG("after virtual spk power up!\n"); - rt5625_write_mask(codec, 0x3e, 0x3000, 0x3000); - rt5625_write_mask(codec, 0x02, 0x0000, 0x8080); - rt5625_write_mask(codec, 0x3a, 0x0400, 0x0400);//power on spk amp - break; - case SND_SOC_DAPM_POST_PMD: - DBG("aftet virtual spk power down!\n"); - rt5625_write_mask(codec, 0x3a, 0x0000, 0x0400);//power off spk amp - rt5625_write_mask(codec, 0x02, 0x8080, 0x8080); - rt5625_write_mask(codec, 0x3e, 0x0000, 0x3000); - break; - default: - return 0; - } - return 0; -} - - - - -static int hp_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = w->codec; - int reg; - - DBG("enter %s\n", __func__); - - reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 6); - if ((reg >> 6) != 0x3 && reg != 0) - return 0; - - switch (event) - { - case SND_SOC_DAPM_POST_PMD: - - DBG("aftet virtual hp power down!\n"); - - hp_mute_unmute_depop(codec,1);//mute hp - rt5625_write_mask(codec, 0x3a, 0x0000, 0x0300); - rt5625_write_mask(codec, 0x3e, 0x0000, 0x0c00); - break; - - case SND_SOC_DAPM_POST_PMU: - - DBG("after virtual hp power up!\n"); - hp_depop_mode2(codec); - hp_mute_unmute_depop(codec,0);//unmute hp - break; - - default: - return 0; - } - - return 0; -} - - - -static int aux_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) -{ - return 0; -} - -/*SPKOUT Mux*/ -static const struct snd_kcontrol_new rt5625_spkout_mux_out_controls = -SOC_DAPM_ENUM("Route", rt5625_enum[3]); - -/*HPLOUT MUX*/ -static const struct snd_kcontrol_new rt5625_hplout_mux_out_controls = -SOC_DAPM_ENUM("Route", rt5625_enum[4]); - -/*HPROUT MUX*/ -static const struct snd_kcontrol_new rt5625_hprout_mux_out_controls = -SOC_DAPM_ENUM("Route", rt5625_enum[5]); -/*AUXOUT MUX*/ -static const struct snd_kcontrol_new rt5625_auxout_mux_out_controls = -SOC_DAPM_ENUM("Route", rt5625_enum[6]); - -static const struct snd_soc_dapm_widget rt5625_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("Left LineIn"), -SND_SOC_DAPM_INPUT("Right LineIn"), -SND_SOC_DAPM_INPUT("Phone"), -SND_SOC_DAPM_INPUT("Mic1"), -SND_SOC_DAPM_INPUT("Mic2"), - -SND_SOC_DAPM_PGA("Mic1 Boost", RT5625_PWR_MANAG_ADD3, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mic2 Boost", RT5625_PWR_MANAG_ADD3, 0, 0, NULL, 0), - -SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 9, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 8, 0), -SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback DAC", RT5625_PWR_MANAG_ADD2, 10, 0), - -SND_SOC_DAPM_PGA("Left LineIn PGA", RT5625_PWR_MANAG_ADD3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right LineIn PGA", RT5625_PWR_MANAG_ADD3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Phone PGA", RT5625_PWR_MANAG_ADD3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mic1 PGA", RT5625_PWR_MANAG_ADD3, 3, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mic2 PGA", RT5625_PWR_MANAG_ADD3, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA("VoDAC PGA", RT5625_PWR_MANAG_ADD1, 7, 0, NULL, 0), -SND_SOC_DAPM_MIXER("RKE", RT5625_PWR_MANAG_ADD2, 1, 0, - &rt5625_left_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_left_adc_rec_mixer_controls)), -SND_SOC_DAPM_MIXER("RKF", RT5625_PWR_MANAG_ADD2, 0, 0, - &rt5625_right_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_right_adc_rec_mixer_controls)), -SND_SOC_DAPM_MIXER_E("RK5", RT5625_PWR_MANAG_ADD2, 5, 0, - &rt5625_left_hp_mixer_controls[0], ARRAY_SIZE(rt5625_left_hp_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER_E("RK6", RT5625_PWR_MANAG_ADD2, 4, 0, - &rt5625_right_hp_mixer_controls[0], ARRAY_SIZE(rt5625_right_hp_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER("RK13", RT5625_PWR_MANAG_ADD2, 2, 0, - &rt5625_mono_mixer_controls[0], ARRAY_SIZE(rt5625_mono_mixer_controls)), -SND_SOC_DAPM_MIXER("RK12", RT5625_PWR_MANAG_ADD2, 3, 0, - &rt5625_spk_mixer_controls[0], ARRAY_SIZE(rt5625_spk_mixer_controls)), -SND_SOC_DAPM_MIXER("RK11", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("DAC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("RK1", SND_SOC_NOPM, 0, 0, &rt5625_spkout_mux_out_controls), -SND_SOC_DAPM_MUX("RK7", SND_SOC_NOPM, 0, 0, &rt5625_hplout_mux_out_controls), -SND_SOC_DAPM_MUX("RK8", SND_SOC_NOPM, 0, 0, &rt5625_hprout_mux_out_controls), -SND_SOC_DAPM_MUX("RKB", SND_SOC_NOPM, 0, 0, &rt5625_auxout_mux_out_controls), - -SND_SOC_DAPM_PGA_E("SPKL Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 4, 0, NULL, 0, - spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_PGA_E("SPKR Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 5, 0, NULL, 0, - spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_PGA_E("HPL Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 6, 0, NULL, 0, - hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("HPR Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 7, 0, NULL, 0, - hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("AUX Out PGA",RT5625_PWR_MANAG_ADD3, 14, 0, NULL, 0, - aux_pga_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_ADC("Left ADC", "Left ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 7, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 6, 0), -SND_SOC_DAPM_OUTPUT("SPKL"), -SND_SOC_DAPM_OUTPUT("SPKR"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_OUTPUT("AUX"), -SND_SOC_DAPM_MICBIAS("Mic1 Bias", RT5625_PWR_MANAG_ADD1, 3, 0), -SND_SOC_DAPM_MICBIAS("Mic2 Bias", RT5625_PWR_MANAG_ADD1, 2, 0), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /*output*/ - {"SPKL", NULL, "SPKL Out PGA"}, - {"SPKR", NULL, "SPKR Out PGA"}, - {"HPL", NULL, "HPL Out PGA"}, - {"HPR", NULL, "HPR Out PGA"}, - {"AUX", NULL, "AUX Out PGA"}, - - /*Input PGA*/ - {"Left LineIn PGA", NULL, "Left LineIn"}, - {"Right LineIn PGA", NULL, "Right LineIn"}, - {"Phone PGA", NULL, "Phone"}, - {"Mic1 Boost", NULL, "Mic1"}, - {"Mic2 Boost", NULL, "Mic2"}, - {"Mic1 PGA", NULL, "Mic1"}, - {"Mic2 PGA", NULL, "Mic2"}, - {"VoDAC PGA", NULL, "Voice DAC"}, - - /*Left ADC mixer*/ - {"RKE", "LineIn Capture Switch", "Left LineIn"}, - {"RKE", "RKL", "Phone"}, - {"RKE", "RKK", "Mic1 Boost"}, - {"RKE", "Mic2 Capture Switch", "Mic2 Boost"}, - {"RKE", "HP Mixer Capture Switch", "RK5"}, - {"RKE", "SPK Mixer Capture Switch", "RK12"}, - {"RKE", "MoNo Mixer Capture Switch", "RK13"}, - - /*Right ADC Mixer*/ - {"RKF", "LineIn Capture Switch", "Right LineIn"}, - {"RKF", "RKL", "Phone"}, - {"RKF", "RKK", "Mic1 Boost"}, - {"RKF", "Mic2 Capture Switch", "Mic2 Boost"}, - {"RKF", "HP Mixer Capture Switch", "RK6"}, - {"RKF", "SPK Mixer Capture Switch", "RK12"}, - {"RKF", "MoNo Mixer Capture Switch", "RK13"}, - - /*HPL mixer*/ - {"RK5", "ADC Playback Switch", "RKE"}, - {"RK5", "LineIn Playback Switch", "Left LineIn PGA"}, - {"RK5", "RKJ", "Phone PGA"}, - {"RK5", "RKI", "Mic1 PGA"}, - {"RK5", "Mic2 Playback Switch", "Mic2 PGA"}, - {"RK5", "RKH", "Left DAC"}, - {"RK5", "RKM", "VoDAC PGA"}, - - /*DAC Mixer*/ - {"DAC Mixer", NULL, "Left DAC"}, - {"DAC Mixer", NULL, "Right DAC"}, - - /*line mixer*/ - {"Line Mixer", NULL, "Left LineIn PGA"}, - {"Line Mixer", NULL, "Right LineIn PGA"}, - - /*HPR mixer*/ - {"RK6", "ADC Playback Switch", "RKF"}, - {"RK6", "LineIn Playback Switch", "Right LineIn PGA"}, - {"RK6", "RKH", "Right DAC"}, - {"RK6", "RKJ", "Phone PGA"}, - {"RK6", "RKI", "Mic1 PGA"}, - {"RK6", "Mic2 Playback Switch", "Mic2 PGA"}, - {"RK6", "RKM", "VoDAC PGA"}, - - /*spk mixer*/ - {"RK12", "Line Mixer Playback Switch", "Line Mixer"}, - {"RK12", "RKJ", "Phone PGA"}, - {"RK12", "RKI", "Mic1 PGA"}, - {"RK12", "Mic2 Playback Switch", "Mic2 PGA"}, - {"RK12", "RKG", "DAC Mixer"}, - {"RK12", "RKM", "VoDAC PGA"}, - - /*mono mixer*/ - {"RK13", "Line Mixer Playback Switch", "Line Mixer"}, - {"RK13", "ADCL Playback Switch","RKE"}, - {"RK13", "ADCR Playback Switch","RKF"}, - {"RK13", "RKI", "Mic1 PGA"}, - {"RK13", "Mic2 Playback Switch", "Mic2 PGA"}, - {"RK13", "RKG", "DAC Mixer"}, - {"RK13", "RKM", "VoDAC PGA"}, - - /*hp mixer*/ - {"RK11", NULL, "RK5"}, - {"RK11", NULL, "RK6"}, - - /*spkout mux*/ - {"RK1", "RK11", "RK11"}, - {"RK1", "RK12", "RK12"}, - {"RK1", "RK13", "RK13"}, - - /*hpl out mux*/ - {"RK7", "RK71", "RK5"}, - - /*hpr out mux*/ - {"RK8", "RK81", "RK6"}, - - /*aux out mux*/ - {"RKB", "RK11", "RK11"}, - {"RKB", "RK12", "RK12"}, - {"RKB", "RK13", "RK13"}, - - /*spkl out pga*/ - {"SPKL Out PGA", NULL, "RK1"}, - - /*spkr out pga*/ - {"SPKR Out PGA", NULL, "RK1"}, - - /*hpl out pga*/ - {"HPL Out PGA", NULL, "RK7"}, - - /*hpr out pga*/ - {"HPR Out PGA", NULL, "RK8"}, - - /*aux out pga*/ - {"AUX Out PGA", NULL, "RKB"}, - - /*left adc*/ - {"Left ADC", NULL, "RKE"}, - - /*right adc*/ - {"Right ADC", NULL, "RKF"}, - - -}; - - -static int rt5625_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, rt5625_dapm_widgets, - ARRAY_SIZE(rt5625_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - snd_soc_dapm_new_widgets(codec); - - return 0; -} - -struct _pll_div{ - u32 pll_in; - u32 pll_out; - u16 regvalue; -}; - - -/************************************************************** - * watch out! - * our codec support you to select different source as pll input, but if you - * use both of the I2S audio interface and pcm interface instantially. - * The two DAI must have the same pll setting params, so you have to offer - * the same pll input, and set our codec's sysclk the same one, we suggest - * 24576000. - **************************************************************/ -static const struct _pll_div codec_master_pll1_div[] = { - - { 2048000, 8192000, 0x0ea0}, - { 3686400, 8192000, 0x4e27}, - { 12000000, 8192000, 0x456b}, - { 13000000, 8192000, 0x495f}, - { 13100000, 8192000, 0x0320}, - { 2048000, 11289600, 0xf637}, - { 3686400, 11289600, 0x2f22}, - { 12000000, 11289600, 0x3e2f}, - { 13000000, 11289600, 0x4d5b}, - { 13100000, 11289600, 0x363b}, - { 2048000, 16384000, 0x1ea0}, - { 3686400, 16384000, 0x9e27}, - { 12000000, 16384000, 0x452b}, - { 13000000, 16384000, 0x542f}, - { 13100000, 16384000, 0x03a0}, - { 2048000, 16934400, 0xe625}, - { 3686400, 16934400, 0x9126}, - { 12000000, 16934400, 0x4d2c}, - { 13000000, 16934400, 0x742f}, - { 13100000, 16934400, 0x3c27}, - { 2048000, 22579200, 0x2aa0}, - { 3686400, 22579200, 0x2f20}, - { 12000000, 22579200, 0x7e2f}, - { 13000000, 22579200, 0x742f}, - { 13100000, 22579200, 0x3c27}, - { 2048000, 24576000, 0x2ea0}, - { 3686400, 24576000, 0xee27}, - { 11289600, 24576000, 0x950F}, - { 12000000, 24576000, 0x2915}, - { 12288000, 24576000, 0x0600}, - { 13000000, 24576000, 0x772e}, - { 13100000, 24576000, 0x0d20}, - { 26000000, 24576000, 0x2027}, - { 26000000, 22579200, 0x392f}, - { 24576000, 22579200, 0x0921}, - { 24576000, 24576000, 0x02a0}, -}; - -static const struct _pll_div codec_bclk_pll1_div[] = { - - { 256000, 4096000, 0x3ea0}, - { 352800, 5644800, 0x3ea0}, - { 512000, 8192000, 0x3ea0}, - { 705600, 11289600, 0x3ea0}, - { 1024000, 16384000, 0x3ea0}, - { 1411200, 22579200, 0x3ea0}, - { 1536000, 24576000, 0x3ea0}, - { 2048000, 16384000, 0x1ea0}, - { 2822400, 22579200, 0x1ea0}, - { 3072000, 24576000, 0x1ea0}, - { 705600, 11289600, 0x3ea0}, - { 705600, 8467200, 0x3ab0}, - { 2822400, 11289600, 0x1ee0}, - { 3072000, 12288000, 0x1ee0}, -}; - -static const struct _pll_div codec_vbclk_pll1_div[] = { - - { 256000, 4096000, 0x3ea0}, - { 352800, 5644800, 0x3ea0}, - { 512000, 8192000, 0x3ea0}, - { 705600, 11289600, 0x3ea0}, - { 1024000, 16384000, 0x3ea0}, - { 1411200, 22579200, 0x3ea0}, - { 1536000, 24576000, 0x3ea0}, - { 2048000, 16384000, 0x1ea0}, - { 2822400, 22579200, 0x1ea0}, - { 3072000, 24576000, 0x1ea0}, - { 705600, 11289600, 0x3ea0}, - { 705600, 8467200, 0x3ab0}, -}; - - -struct _coeff_div_stereo { - unsigned int mclk; - unsigned int rate; - unsigned int reg60; - unsigned int reg62; -}; - -struct _coeff_div_voice { - unsigned int mclk; - unsigned int rate; - unsigned int reg64; -}; - -static const struct _coeff_div_stereo coeff_div_stereo[] = { - - /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */ - {24576000, 48000, 0x3174, 0x1010}, - {12288000, 48000, 0x1174, 0x0000}, - {18432000, 48000, 0x2174, 0x1111}, - {36864000, 48000, 0x2274, 0x2020}, - {49152000, 48000, 0xf074, 0x3030}, - {24576000, 48000, 0x3172, 0x1010}, - {24576000, 8000, 0xB274, 0x2424}, - {24576000, 16000, 0xB174, 0x2222}, - {24576000, 32000, 0xB074, 0x2121}, - {22579200, 11025, 0X3374, 0x1414}, - {22579200, 22050, 0X3274, 0x1212}, - {22579200, 44100, 0X3174, 0x1010}, - {0, 0, 0, 0}, -}; - -static const struct _coeff_div_voice coeff_div_voice[] = { - - /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */ - {24576000, 16000, 0x2622}, - {24576000, 8000, 0x2824}, - {0, 0, 0}, -}; - -static int get_coeff(unsigned int mclk, unsigned int rate, int mode) -{ - int i; - - DBG("get_coeff mclk = %d, rate = %d, mode = %d\n", mclk, rate, mode); - - if (!mode) { - for (i = 0; i < ARRAY_SIZE(coeff_div_stereo); i++) { - if ((coeff_div_stereo[i].rate == rate) && (coeff_div_stereo[i].mclk == mclk)) - return i; - } - } else { - for (i = 0; i< ARRAY_SIZE(coeff_div_voice); i++) { - if ((coeff_div_voice[i].rate == rate) && (coeff_div_voice[i].mclk == mclk)) - return i; - } - } - - printk("can't find a matched mclk and rate in %s\n", - (mode ? "coeff_div_voice[]" : "coeff_div_audio[]")); - - return -EINVAL; -} - - -static int rt5625_codec_set_dai_pll(struct snd_soc_dai *codec_dai, - int pll_id, unsigned int freq_in, unsigned int freq_out) -{ - int i; - int ret = -EINVAL; - struct snd_soc_codec *codec = codec_dai->codec; - - DBG("enter %s pll_id = %d freq_in = %d freq_out = %d\n", - __func__, pll_id, freq_in, freq_out); - - if (pll_id < RT5625_PLL1_FROM_MCLK || pll_id > RT5625_PLL1_FROM_VBCLK) - return -EINVAL; - - if (!freq_in || !freq_out) - return 0; - - if (RT5625_PLL1_FROM_MCLK == pll_id) { - - for (i = 0; i < ARRAY_SIZE(codec_master_pll1_div); i ++) - { - if ((freq_in == codec_master_pll1_div[i].pll_in) && (freq_out == codec_master_pll1_div[i].pll_out)) - { - rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x0000); /*PLL source from MCLK*/ - rt5625_write(codec, RT5625_PLL_CTRL, codec_master_pll1_div[i].regvalue); /*set pll code*/ - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000); /*enable pll1 power*/ - rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000); - ret = 0; - } - } - } else if (RT5625_PLL1_FROM_BCLK == pll_id) { - - for (i = 0; i < ARRAY_SIZE(codec_bclk_pll1_div); i ++) - { - if ((freq_in == codec_bclk_pll1_div[i].pll_in) && (freq_out == codec_bclk_pll1_div[i].pll_out)) - { - rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x2000); /*PLL source from BCLK*/ - rt5625_write(codec, RT5625_PLL_CTRL, codec_bclk_pll1_div[i].regvalue); /*set pll1 code*/ - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000); /*enable pll1 power*/ - rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000); - ret = 0; - } - } - } else if (RT5625_PLL1_FROM_VBCLK == pll_id) { - - for (i = 0; i < ARRAY_SIZE(codec_vbclk_pll1_div); i ++) - { - if ((freq_in == codec_vbclk_pll1_div[i].pll_in) && (freq_out == codec_vbclk_pll1_div[i].pll_out)) - { - rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x3000); /*PLL source from VBCLK*/ - rt5625_write(codec, RT5625_PLL_CTRL, codec_vbclk_pll1_div[i].regvalue); /*set pll1 code*/ - rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000); /*enable pll1 power*/ - rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000); - ret = 0; - } - } - } - return 0; -} - - -static int rt5625_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5625_priv * rt5625 = codec->private_data; - - DBG("sysclk freq %u for audio i2s\n", freq); - - if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { - rt5625->stereo_sysclk = freq; - return 0; - } - - printk("unsupported sysclk freq %u for audio i2s\n", freq); - rt5625->stereo_sysclk=24576000; - - return 0; -} - -static int rt5625_voice_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5625_priv * rt5625 = codec->private_data; - - DBG("sysclk freq %u for voice pcm\n", freq); - - if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { - rt5625->voice_sysclk = freq; - return 0; - } - - printk("unsupported sysclk freq %u for voice pcm\n", freq); - rt5625->voice_sysclk = 24576000; - - return 0; -} - - -static int rt5625_hifi_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct rt5625_priv *rt5625 = codec->private_data; - - unsigned int iface = rt5625_read(codec, RT5625_MAIN_SDP_CTRL) & 0xfff3; - int rate = params_rate(params); - int coeff = get_coeff(rt5625->stereo_sysclk, rate, 0); - - DBG("enter %s rate = %d \n", __func__, rate); - - switch (params_format(params)) - { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - case SNDRV_PCM_FORMAT_S8: - iface |= 0x000c; - } - - rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface); - rt5625_write_mask(codec, 0x3a, 0xc801, 0xc801); /*power i2s and dac ref*/ - if (coeff >= 0) { - rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL1, coeff_div_stereo[coeff].reg60); - rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL2, coeff_div_stereo[coeff].reg62); - } - - return 0; -} - -static int rt5625_voice_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct rt5625_priv *rt5625 = codec->private_data; - struct snd_soc_dapm_widget *w; - unsigned int iface = rt5625_read(codec, RT5625_EXTEND_SDP_CTRL) & 0xfff3; - int rate = params_rate(params); - int coeff = get_coeff(rt5625->voice_sysclk, rate, 1); - - DBG("enter %s rate = %d \n", __func__, rate); - - list_for_each_entry(w, &codec->dapm_widgets, list) - { - if (!w->sname) - continue; - if (!strcmp(w->name, "Right ADC")) - strcpy(w->sname, "Right ADC Voice Capture"); - } - - switch (params_format(params)) - { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - case SNDRV_PCM_FORMAT_S8: - iface |= 0x000c; - } - rt5625_write_mask(codec, 0x3a, 0x0801, 0x0801); /*power i2s and dac ref*/ - rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface); - if (coeff >= 0) - rt5625_write(codec, RT5625_VOICE_DAC_PCMCLK_CTRL1, coeff_div_voice[coeff].reg64); - - return 0; -} - - -static int rt5625_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - DBG("enter %s fmt = %d\n", __func__, fmt); - - /*set master/slave interface*/ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) - { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0000; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface = 0x8000; - break; - default: - return -EINVAL; - } - - /*interface format*/ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) - { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0000; - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0003; - break; - default: - return -EINVAL; - } - - /*clock inversion*/ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) - { - case SND_SOC_DAIFMT_NB_NF: - iface |= 0x0000; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - default: - return -EINVAL; - } - - rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface); - return 0; -} - -static int rt5625_voice_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int iface; - - DBG("enter %s\n", __func__); - /*set slave/master mode*/ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) - { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0000; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface = 0x4000; - break; - default: - return -EINVAL; - } - - switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK) - { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0000; - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0003; - break; - default: - return -EINVAL; - } - - /*clock inversion*/ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) - { - case SND_SOC_DAIFMT_NB_NF: - iface |= 0x0000; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - default: - return -EINVAL; - } - - iface |= 0x8000; /*enable vopcm*/ - rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface); - return 0; -} - - -static int rt5625_hifi_codec_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - if (mute) - rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x8080, 0x8080); - else - rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x0000, 0x8080); - return 0; -} - -static int rt5625_voice_codec_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - if (mute) - rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x1000, 0x1000); - else - rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x0000, 0x1000); - return 0; -} - - -static int rt5625_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch(level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - rt5625_write(codec, 0x26, 0x0000); - rt5625_write_mask(codec, 0x3c, 0x2000, 0x2000); - rt5625_write_mask(codec, 0x3a, 0x000e, 0x000e); - break; - case SND_SOC_BIAS_STANDBY: - break; - case SND_SOC_BIAS_OFF: - rt5625_write_mask(codec, 0x04, 0x8080, 0x8080); /*mute hp*/ - rt5625_write_mask(codec, 0x02, 0x8080, 0x8080); /*mute spk*/ - rt5625_write(codec, 0x3e, 0x0000); //power off all bit - rt5625_write(codec, 0x3a, 0x0000); //power off all bit - rt5625_write(codec, 0x3c, 0x0000); //power off all bit - - break; - } - codec->bias_level = level; - return 0; -} - - -#define RT5625_STEREO_RATES SNDRV_PCM_RATE_8000_48000 - -#define RT5626_VOICE_RATES SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000 - -#define RT5625_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S8) - -static struct snd_soc_dai_ops rt5625_dai_ops_hifi = { - - .hw_params = rt5625_hifi_pcm_hw_params, -// .digital_mute = rt5625_hifi_codec_mute, - .set_fmt = rt5625_hifi_codec_set_dai_fmt, - .set_pll = rt5625_codec_set_dai_pll, - .set_sysclk = rt5625_hifi_codec_set_dai_sysclk, - -}; - - -static struct snd_soc_dai_ops rt5625_dai_ops_voice = { - - .hw_params = rt5625_voice_pcm_hw_params, -// .digital_mute = rt5625_voice_codec_mute, - .set_fmt = rt5625_voice_codec_set_dai_fmt, - .set_pll = rt5625_codec_set_dai_pll, - .set_sysclk = rt5625_voice_codec_set_dai_sysclk, - -}; - - - -struct snd_soc_dai rt5625_dai[] = { - /*hifi codec dai*/ - { - .name = "RT5625 HiFi", - .id = 1, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = RT5625_STEREO_RATES, - .formats = RT5625_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT5625_STEREO_RATES, - .formats = RT5625_FORMATS, - }, - - .ops = &rt5625_dai_ops_hifi, - }, - - /*voice codec dai*/ - { - .name = "RT5625 Voice", - .id = 2, - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = RT5626_VOICE_RATES, - .formats = RT5625_FORMATS, - }, - .capture = { - .stream_name = "Voice Capture", - .channels_min = 1, - .channels_max = 1, - .rates = RT5626_VOICE_RATES, - .formats = RT5625_FORMATS, - }, - - .ops = &rt5625_dai_ops_voice, - - }, -}; - -EXPORT_SYMBOL_GPL(rt5625_dai); - - -static void rt5625_work(struct work_struct *work) -{ - struct snd_soc_codec *codec = - container_of(work, struct snd_soc_codec, delayed_work.work); - rt5625_set_bias_level(codec, codec->bias_level); -} - - -#if defined(CONFIG_SND_HWDEP) - -#if REALTEK_HWDEP - -#define RT_CE_CODEC_HWDEP_NAME "rt56xx hwdep " - - -static int rt56xx_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - DBG("enter %s\n", __func__); - return 0; -} - -static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - DBG("enter %s\n", __func__); - return 0; -} - - -static int rt56xx_hwdep_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct rt56xx_cmd rt56xx; - struct rt56xx_cmd __user *_rt56xx = arg; - struct rt56xx_reg_state *buf; - struct rt56xx_reg_state *p; - struct snd_soc_codec *codec = hw->private_data; - - if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) - return -EFAULT; - buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) { - goto err; - } - switch (cmd) { - case RT_READ_CODEC_REG_IOCTL: - for (p = buf; p < buf + rt56xx.number; p++) - { - p->reg_value = codec->read(codec, p->reg_index); - } - if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number)) - goto err; - - break; - case RT_WRITE_CODEC_REG_IOCTL: - for (p = buf; p < buf + rt56xx.number; p++) - codec->write(codec, p->reg_index, p->reg_value); - break; - } - - kfree(buf); - return 0; - -err: - kfree(buf); - return -EFAULT; - -} - -static int rt56xx_codec_dump_reg(struct snd_hwdep *hw, struct file *file, unsigned long arg) -{ - struct rt56xx_cmd rt56xx; - struct rt56xx_cmd __user *_rt56xx = arg; - struct rt56xx_reg_state *buf; - struct snd_soc_codec *codec = hw->private_data; - int number = codec->reg_cache_size; - int i; - - DBG("enter %s, number = %d\n", __func__, number); - if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) - return -EFAULT; - - buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - for (i = 0; i < number; i++) - { - buf[i].reg_index = i << 1; - buf[i].reg_value = codec->read(codec, buf[i].reg_index); - } - if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * i)) - goto err; - rt56xx.number = number; - if (copy_to_user(_rt56xx, &rt56xx, sizeof(rt56xx))) - goto err; - kfree(buf); - return 0; -err: - kfree(buf); - return -EFAULT; - -} - -static int rt56xx_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - if (cmd == RT_READ_ALL_CODEC_REG_IOCTL) - { - return rt56xx_codec_dump_reg(hw, file, arg); - } - else - { - return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg); - } -} - -int realtek_ce_init_hwdep(struct snd_soc_codec *codec) -{ - struct snd_hwdep *hw; - struct snd_card *card = codec->card; - int err; - - if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0) - return err; - - strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME); - hw->private_data = codec; - hw->ops.open = rt56xx_hwdep_open; - hw->ops.release = rt56xx_hwdep_release; - hw->ops.ioctl = rt56xx_hwdep_ioctl; - return 0; -} - -#endif - -#endif - -static int rt5625_init(struct snd_soc_device *socdev) -{ - - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; - - codec->name = "RT5625"; - codec->owner = THIS_MODULE; - codec->read = rt5625_read; - codec->write = rt5625_write; - codec->set_bias_level = rt5625_set_bias_level; - codec->dai= rt5625_dai; - codec->num_dai = 2; - codec->reg_cache_step = 2; - codec->reg_cache_size = ARRAY_SIZE(rt5625_reg)*2; - codec->reg_cache = kmemdup(rt5625_reg, sizeof(rt5625_reg), GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; - - rt5625_reset(codec); - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0 ) - { - printk(KERN_ERR "rt5625: failed to create pcms\n"); - goto pcm_err; - } - - rt5625_write(codec, RT5625_PD_CTRL_STAT, 0); - rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS); - rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF); - rt5625_reg_init(codec); - rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->bias_level = SND_SOC_BIAS_STANDBY; - schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(80)); - -#if (RT5625_EQ_FUNC_ENA==1) - rt5625_update_eqmode(codec,POP); -#endif - - rt5625_add_controls(codec); - rt5625_add_widgets(codec); - - #if defined(CONFIG_SND_HWDEP) - - #if REALTEK_HWDEP - - realtek_ce_init_hwdep(codec); - - #endif - - #endif - - ret = snd_soc_init_card(socdev); - - if (ret < 0) - { - printk(KERN_ERR "rt5625: failed to register card\n"); - goto card_err; - } - DBG("rt5625: initial ok\n"); - return 0; - - card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - pcm_err: - kfree(codec->reg_cache); - return ret; - - -} - - -static int rt5625_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -{ - struct snd_soc_device *socdev = rt5625_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; - - ret = rt5625_init(socdev); - if (ret < 0) - pr_err("failed to initialise rt5625\n"); - - return ret; -} - -static int rt5625_i2c_remove(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); - return 0; -} - -static const struct i2c_device_id rt5625_i2c_id[] = { - {"rt5625", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, rt5625_i2c_id); -static struct i2c_driver rt5625_i2c_driver = { - .driver = { - .name = "RT5625 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = rt5625_i2c_probe, - .remove = rt5625_i2c_remove, - .id_table = rt5625_i2c_id, -}; - - -static int rt5625_add_i2c_device(struct platform_device *pdev, - const struct rt5625_setup_data *setup) -{ -#if 0 - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; -#endif - int ret; - - ret = i2c_add_driver(&rt5625_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } -#if 0 - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "rt5625", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } -#endif - return 0; -#if 0 -err_driver: - i2c_del_driver(&rt5625_i2c_driver); - return -ENODEV; -#endif -} - - -static int rt5625_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct rt5625_setup_data *setup; - struct snd_soc_codec *codec; - struct rt5625_priv *rt5625; - int ret; - - pr_info("RT5625 Audio Codec %s", RT5625_VERSION); - - if(socdev->codec_data) - { - setup = socdev->codec_data; - } - - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - rt5625 = kzalloc(sizeof(struct rt5625_priv), GFP_KERNEL); - if (rt5625 == NULL) { - kfree(codec); - return -ENOMEM; - } - codec->private_data = rt5625; - socdev->card->codec = codec; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - rt5625_socdev = socdev; - INIT_DELAYED_WORK(&codec->delayed_work, rt5625_work); - - ret = -ENODEV; -// if (setup->i2c_address) - { - codec->hw_write = (hw_write_t)i2c_master_send; - //codec->hw_read = (hw_read_t)i2c_master_recv; - ret = rt5625_add_i2c_device(pdev, setup); - } - - if (ret != 0) { - kfree(codec->private_data); - kfree(codec); - socdev->card->codec = NULL; - } - return ret; -} - -static int run_delayed_work(struct delayed_work *dwork) -{ - int ret; - - /* cancel any work waiting to be queued. */ - ret = cancel_delayed_work(dwork); - - /* if there was any work waiting then we run it now and - * wait for it's completion */ - if (ret) { - schedule_delayed_work(dwork, 0); - flush_scheduled_work(); - } - return ret; -} - - -static int rt5625_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF); - run_delayed_work(&codec->delayed_work); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - i2c_unregister_device(codec->control_data); - i2c_del_driver(&rt5625_i2c_driver); - kfree(codec->private_data); - kfree(codec); - - return 0; -} - - -static int rt5625_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int rt5625_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - -// int i; -// u8 data[3]; -// u16 *cache = codec->reg_cache; - -#if 1 - rt5625_reset(codec); - rt5625_write(codec, RT5625_PD_CTRL_STAT, 0); - rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS); - rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF); - rt5625_reg_init(codec); -#else - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(rt5625_reg); i++) { - if (i == RT5625_RESET) - continue; - data[0] = i << 1; - data[1] = (0xff00 & cache[i]) >> 8; - data[2] = 0x00ff & cache[i]; - codec->hw_write(codec->control_data, data, 3); - } - - rt5625_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -#endif - - /* charge rt5625 caps */ - if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { - rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->bias_level = SND_SOC_BIAS_ON; - schedule_delayed_work(&codec->delayed_work, - msecs_to_jiffies(100)); - } - - return 0; -} - - -struct snd_soc_codec_device soc_codec_dev_rt5625 = { - .probe = rt5625_probe, - .remove = rt5625_remove, - .suspend = rt5625_suspend, - .resume = rt5625_resume, -}; - -EXPORT_SYMBOL_GPL(soc_codec_dev_rt5625); - -static int __init rt5625_modinit(void) -{ - return snd_soc_register_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai)); -} - -static void __exit rt5625_exit(void) -{ - snd_soc_unregister_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai)); -} - -module_init(rt5625_modinit); -module_exit(rt5625_exit); -MODULE_LICENSE("GPL"); - From 469e3ee54b84417dd5605ecee685518e8c069f9f Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 31 Jan 2018 19:50:34 +0800 Subject: [PATCH 162/427] MALI Utgard: RK: remove unused files with proprietary announcement Change-Id: Iffe6df7c406dff1efad10934fc09ca7fd2f101ec Signed-off-by: Zhen Chen --- drivers/gpu/arm/mali400/include/ump/ump.h | 262 ----------- .../gpu/arm/mali400/include/ump/ump_debug.h | 281 ------------ .../include/ump/ump_kernel_interface.h | 235 ---------- .../ump/ump_kernel_interface_ref_drv.h | 31 -- .../mali400/include/ump/ump_kernel_platform.h | 48 -- drivers/gpu/arm/mali400/include/ump/ump_osu.h | 423 ------------------ .../arm/mali400/include/ump/ump_platform.h | 62 --- .../gpu/arm/mali400/include/ump/ump_ref_drv.h | 106 ----- .../arm/mali400/include/ump/ump_uk_types.h | 194 -------- .../gpu/arm/mali400/mali/common/mali_dma.c | 202 --------- .../gpu/arm/mali400/mali/common/mali_dma.h | 190 -------- .../mali400/mali/common/mali_gp_scheduler.h | 101 ----- .../mali400/mali/common/mali_pp_scheduler.h | 130 ------ .../license/proprietary/mali_kernel_license.h | 30 -- .../mali400/mali/platform/tcc8900/tcc8900.c | 99 ---- .../ump/arch-pb-virtex5-m400-4/config.h | 17 - .../license/proprietary/ump_kernel_license.h | 30 -- 17 files changed, 2441 deletions(-) delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_debug.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_osu.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_platform.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h delete mode 100755 drivers/gpu/arm/mali400/include/ump/ump_uk_types.h delete mode 100755 drivers/gpu/arm/mali400/mali/common/mali_dma.c delete mode 100755 drivers/gpu/arm/mali400/mali/common/mali_dma.h delete mode 100755 drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h delete mode 100755 drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h delete mode 100755 drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h delete mode 100755 drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c delete mode 100755 drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h delete mode 100755 drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h diff --git a/drivers/gpu/arm/mali400/include/ump/ump.h b/drivers/gpu/arm/mali400/include/ump/ump.h deleted file mode 100755 index ce593c7d54c0..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump.h - * - * This file contains the user space part of the UMP API. - */ - -#ifndef _UNIFIED_MEMORY_PROVIDER_H_ -#define _UNIFIED_MEMORY_PROVIDER_H_ - - -/** @defgroup ump_user_space_api UMP User Space API - * @{ */ - - -#include "ump_platform.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * External representation of a UMP handle in user space. - */ -typedef void *ump_handle; - -/** - * Typedef for a secure ID, a system wide identificator for UMP memory buffers. - */ -typedef unsigned int ump_secure_id; - -/** - * Value to indicate an invalid UMP memory handle. - */ -#define UMP_INVALID_MEMORY_HANDLE ((ump_handle)0) - -/** - * Value to indicate an invalid secure Id. - */ -#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) - -/** - * UMP error codes for user space. - */ -typedef enum -{ - UMP_OK = 0, /**< indicates success */ - UMP_ERROR, /**< indicates failure */ -} ump_result; - - -/** - * Opens and initializes the UMP library. - * - * This function must be called at least once before calling any other UMP API functions. - * Each open is reference counted and must be matched with a call to @ref ump_close "ump_close". - * - * @see ump_close - * - * @return UMP_OK indicates success, UMP_ERROR indicates failure. - */ -UMP_API_EXPORT ump_result ump_open(void); - - -/** - * Terminate the UMP library. - * - * This must be called once for every successful @ref ump_open "ump_open". The UMP library is - * terminated when, and only when, the last open reference to the UMP interface is closed. - * - * @see ump_open - */ -UMP_API_EXPORT void ump_close(void); - - -/** - * Retrieves the secure ID for the specified UMP memory. - * - * This identificator is unique across the entire system, and uniquely identifies - * the specified UMP memory. This identificator can later be used through the - * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" or - * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" - * functions in order to access this UMP memory, for instance from another process. - * - * @note There is a kernel space equivalent function called @ref ump_dd_secure_id_get "ump_dd_secure_id_get" - * - * @see ump_handle_create_from_secure_id - * @see ump_dd_handle_create_from_secure_id - * @see ump_dd_secure_id_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the secure ID for the specified UMP memory. - */ -UMP_API_EXPORT ump_secure_id ump_secure_id_get(ump_handle mem); - - -/** - * Retrieves a handle to allocated UMP memory. - * - * The usage of UMP memory is reference counted, so this will increment the reference - * count by one for the specified UMP memory. - * Use @ref ump_reference_release "ump_reference_release" when there is no longer any - * use for the retrieved handle. - * - * @note There is a kernel space equivalent function called @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" - * - * @see ump_reference_release - * @see ump_dd_handle_create_from_secure_id - * - * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. - * - * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. - */ -UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id); - - -/** - * Retrieves the actual size of the specified UMP memory. - * - * The size is reported in bytes, and is typically page aligned. - * - * @note There is a kernel space equivalent function called @ref ump_dd_size_get "ump_dd_size_get" - * - * @see ump_dd_size_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the allocated size of the specified UMP memory, in bytes. - */ -UMP_API_EXPORT unsigned long ump_size_get(ump_handle mem); - - -/** - * Read from specified UMP memory. - * - * Another way of reading from (and writing to) UMP memory is to use the - * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve - * a CPU mapped pointer to the memory. - * - * @see ump_mapped_pointer_get - * - * @param dst Destination buffer. - * @param src Handle to UMP memory to read from. - * @param offset Where to start reading, given in bytes. - * @param length How much to read, given in bytes. - */ -UMP_API_EXPORT void ump_read(void *dst, ump_handle src, unsigned long offset, unsigned long length); - - -/** - * Write to specified UMP memory. - * - * Another way of writing to (and reading from) UMP memory is to use the - * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve - * a CPU mapped pointer to the memory. - * - * @see ump_mapped_pointer_get - * - * @param dst Handle to UMP memory to write to. - * @param offset Where to start writing, given in bytes. - * @param src Buffer to read from. - * @param length How much to write, given in bytes. - */ -UMP_API_EXPORT void ump_write(ump_handle dst, unsigned long offset, const void *src, unsigned long length); - - -/** - * Retrieves a memory mapped pointer to the specified UMP memory. - * - * This function retrieves a memory mapped pointer to the specified UMP memory, - * that can be used by the CPU. Every successful call to - * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" is reference counted, - * and must therefore be followed by a call to - * @ref ump_mapped_pointer_release "ump_mapped_pointer_release " when the - * memory mapping is no longer needed. - * - * @note Systems without a MMU for the CPU only return the physical address, because no mapping is required. - * - * @see ump_mapped_pointer_release - * - * @param mem Handle to UMP memory. - * - * @return NULL indicates failure, otherwise a CPU mapped pointer is returned. - */ -UMP_API_EXPORT void *ump_mapped_pointer_get(ump_handle mem); - - -/** - * Releases a previously mapped pointer to the specified UMP memory. - * - * The CPU mapping of the specified UMP memory memory is reference counted, - * so every call to @ref ump_mapped_pointer_get "ump_mapped_pointer_get" must - * be matched with a call to this function when the mapping is no longer needed. - * - * The CPU mapping is not removed before all references to the mapping is released. - * - * @note Systems without a MMU must still implement this function, even though no unmapping should be needed. - * - * @param mem Handle to UMP memory. - */ -UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle mem); - - -/** - * Adds an extra reference to the specified UMP memory. - * - * This function adds an extra reference to the specified UMP memory. This function should - * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_handle - * variable. The function @ref ump_reference_release "ump_reference_release" must then be used - * to release each copy of the UMP memory handle. - * - * @note You are not required to call @ref ump_reference_add "ump_reference_add" - * for UMP handles returned from - * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id", - * because these handles are already reference counted by this function. - * - * @note There is a kernel space equivalent function called @ref ump_dd_reference_add "ump_dd_reference_add" - * - * @see ump_dd_reference_add - * - * @param mem Handle to UMP memory. - */ -UMP_API_EXPORT void ump_reference_add(ump_handle mem); - - -/** - * Releases a reference from the specified UMP memory. - * - * This function should be called once for every reference to the UMP memory handle. - * When the last reference is released, all resources associated with this UMP memory - * handle are freed. - * - * @note There is a kernel space equivalent function called @ref ump_dd_reference_release "ump_dd_reference_release" - * - * @see ump_dd_reference_release - * - * @param mem Handle to UMP memory. - */ -UMP_API_EXPORT void ump_reference_release(ump_handle mem); - - -#ifdef __cplusplus -} -#endif - - -/** @} */ /* end group ump_user_space_api */ - - -#endif /*_UNIFIED_MEMORY_PROVIDER_H_ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_debug.h b/drivers/gpu/arm/mali400/include/ump/ump_debug.h deleted file mode 100755 index c9d129c975b7..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_debug.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2005-2011, 2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_debug.h - * - * The file include several useful macros for debugging and printing. - * - UMP_PRINTF(...) Do not use this function: Will be included in Release builds. - * - UMP_DEBUG_TRACE() Prints current location in code. - * - UMP_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * - UMP_DEBUG_TPRINT(nr, X ) Prints the source trace and second argument if nr<=UMP_DEBUG_LEVEL. - * - UMP_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message. - * - UMP_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit. - * - UMP_DEBUG_ASSERT_RANGE(x, min, max) Triggers if variable x is not between or equal to max and min. - * - UMP_DEBUG_ASSERT_LEQ(x, max) Triggers if variable x is not less than equal to max. - * - UMP_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer. - * - UMP_DEBUG_CODE( X ) The code inside the macro is only copiled in Debug builds. - * - * The (X) means that you must add an extra parantese around the argumentlist. - * - * The printf function: UMP_PRINTF(...) is routed to _ump_sys_printf - * - * Suggested range for the DEBUG-LEVEL is [1:6] where - * [1:2] Is messages with highest priority, indicate possible errors. - * [3:4] Is messages with medium priority, output important variables. - * [5:6] Is messages with low priority, used during extensive debugging. - * - */ -#ifndef _UMP_DEBUG_H_ -#define _UMP_DEBUG_H_ - -#include -#include - -/* START: Configuration */ -#ifndef UMP_PRINTF -#define UMP_PRINTF printf -#endif /* UMP_PRINTF */ - -#ifndef UMP_PRINT_FLUSH -#define UMP_PRINT_FLUSH do {} while (0) -#endif /* UMP_PRINT_FLUSH */ - -#ifndef UMP_DEBUG_LEVEL -#define UMP_DEBUG_LEVEL 1 -#endif /* UMP_DEBUG_LEVEL */ - -#ifndef UMP_DEBUG_ERROR_START_MSG -#define UMP_DEBUG_ERROR_START_MSG do {\ - UMP_PRINTF("*********************************************************************\n");\ - UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_ERROR_START_MSG */ - -#ifndef UMP_DEBUG_ERROR_STOP_MSG -#define UMP_DEBUG_ERROR_STOP_MSG do { UMP_PRINTF("\n"); UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_ERROR_STOP_MSG */ - -#ifndef UMP_ASSERT_QUIT_CMD -#define UMP_ASSERT_QUIT_CMD abort() -#endif /* UMP_ASSERT_QUIT_CMD */ -/* STOP: Configuration */ - -/** - * The macro UMP_FUNCTION evaluates to the name of the function enclosing - * this macro's usage, or "" if not supported. - */ -#if (defined(__SYMBIAN32__) && defined(__ARMCC__)) || defined(_MSC_VER) -# define UMP_FUNCTION __FUNCTION__ -#elif __STDC__ && __STDC_VERSION__ >= 199901L -# define UMP_FUNCTION __FUNCTION__ -#elif defined(__GNUC__) && __GNUC__ >= 2 -# define UMP_FUNCTION __FUNCTION__ -#elif defined(__func__) -# define UMP_FUNCTION __func__ -#else -# define UMP_FUNCTION "" -#endif - -/** - * Explicitly ignore a parameter passed into a function, to suppress compiler warnings. - * Should only be used with parameter names. - */ -#define UMP_IGNORE(x) (void)x - -/** - * @def UMP_DEBUG_TRACE() - * @brief Prints current location in code. - * Can be turned off by defining UMP_DEBUG_SKIP_TRACE - */ - -#ifndef UMP_DEBUG_SKIP_TRACE -#ifndef UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME -#define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ \ - " function: %s() line:%4d\n" , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0) -#else -#define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ " line:%4d\n" , __LINE__); UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME */ -#else -#define UMP_DEBUG_TRACE() -#endif /* UMP_DEBUG_SKIP_TRACE */ - -/** - * @def UMP_DEBUG_PRINT(nr, (X) ) - * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * Can be turned off by defining UMP_DEBUG_SKIP_PRINT - * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ -#ifndef UMP_DEBUG_SKIP_PRINT -#define UMP_DEBUG_PRINT(nr, X ) do { if ( nr<=UMP_DEBUG_LEVEL ) { UMP_PRINTF X ; UMP_PRINT_FLUSH; } } while (0) -#else -#define UMP_DEBUG_PRINT(nr, X ) -#endif /* UMP_DEBUG_SKIP_PRINT */ - -/** - * @def UMP_DEBUG_TPRINT(nr, (X) ) - * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * Can be turned off by defining UMP_DEBUG_SKIP_TPRINT. - * Can be shortened by defining UMP_DEBUG_TPRINT_SKIP_FUNCTION. - * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ - -/* helper to handle if the function name should be included or not */ -#ifndef UMP_DEBUG_TPRINT_SKIP_FUNCTION -#define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__" %s()%4d " , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0) -#else -#define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__ "%4d " , __LINE__); UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_TPRINT_SKIP_FUNCTION */ - -#ifndef UMP_DEBUG_SKIP_TPRINT -#define UMP_DEBUG_TPRINT(nr, X ) \ - do{\ - if ( nr<=UMP_DEBUG_LEVEL )\ - {\ - UMP_DEBUG_TPRINT_INTERN;\ - UMP_PRINTF X ;\ - UMP_PRINT_FLUSH;\ - }\ - } while (0) -#else -#define UMP_DEBUG_TPRINT(nr, X ) -#endif /* UMP_DEBUG_SKIP_TPRINT */ - -/** - * @def UMP_DEBUG_ERROR( (X) ) - * @brief Prints an errortext, a source Trace, and the given error message. - * Prints filename, function, linenr, and the given error message. - * The error message must be inside a second parantese. - * The error message is written on a separate line, and a NL char is added. - * Can be turned of by defining UMP_DEBUG_SKIP_ERROR; - * You do not need to type the words ERROR in the message, since it will - * be added anyway. - * - * @note You should not end the text with a newline, since it is added by the macro. - * @note You should not write "ERROR" in the text, since it is added by the macro. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ - -#ifndef UMP_DEBUG_SKIP_ERROR -#define UMP_DEBUG_ERROR( X ) \ - do{ \ - UMP_DEBUG_ERROR_START_MSG;\ - UMP_PRINTF("ERROR: ");\ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_TRACE(); \ - UMP_PRINTF X ; \ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_ERROR_STOP_MSG;\ - } while (0) -#else -#define UMP_DEBUG_ERROR( X ) do{ ; } while ( 0 ) -#endif /* UMP_DEBUG_SKIP_ERROR */ - -/** - * @def UMP_DEBUG_ASSERT(expr, (X) ) - * @brief If the asserted expr is false, the program will exit. - * Prints filename, function, linenr, and the given error message. - * The error message must be inside a second parantese. - * The error message is written on a separate line, and a NL char is added. - * Can be turned of by defining UMP_DEBUG_SKIP_ERROR; - * You do not need to type the words ASSERT in the message, since it will - * be added anyway. - * - * @param X A parantese with the contents to be sent to UMP_PRINTF - * Prints filename, function, linenr, and the error message - * on a separte line. A newline char is added at the end. - * Can be turned of by defining UMP_DEBUG_SKIP_ASSERT - * @param expr Will exit program if \a expr is false; - * @param (X) Text that will be written if the assertion toggles. - */ - -#ifndef UMP_DEBUG_SKIP_ASSERT -#define UMP_DEBUG_ASSERT(expr, X ) \ - do{\ - if ( !(expr) ) \ - { \ - UMP_DEBUG_ERROR_START_MSG;\ - UMP_PRINTF("ASSERT EXIT: ");\ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_TRACE(); \ - UMP_PRINTF X ; \ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_ERROR_STOP_MSG;\ - UMP_ASSERT_QUIT_CMD;\ - }\ - } while (0) -#else -#define UMP_DEBUG_ASSERT(expr, X) -#endif /* UMP_DEBUG_SKIP_ASSERT */ - - -/** - * @def UMP_DEBUG_ASSERT_POINTER(pointer) - * @brief If the asserted pointer is NULL, the program terminates and TRACE info is printed - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_POINTER(pointer) UMP_DEBUG_ASSERT(pointer, ("Null pointer " #pointer) ) - -/** - * @def UMP_DEBUG_ASSERT_HANDLE(handle) - * @brief If the asserted handle is not a valid handle, the program terminates and TRACE info is printed - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_HANDLE(handle) UMP_DEBUG_ASSERT(UMP_NO_HANDLE != (handle), ("Invalid handle" #handle) ) - -/** - * @def UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) - * @brief If the asserted pointer is not aligned to align, the program terminates with trace info printed. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#ifndef UMP_DEBUG_SKIP_ASSERT -#define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) do { \ - UMP_DEBUG_ASSERT(0 == (align & (align - 1)), ("align %d is not a power-of-two", align)); \ - UMP_DEBUG_ASSERT(0 == (((u32)(ptr)) & (align - 1)), ("ptr %p not aligned to %d bytes", (void*)ptr, align)); \ - } while (0) -#else -#define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) -#endif /* UMP_DEBUG_SKIP_ASSERT */ - -/** - * @def UMP_DEBUG_ASSERT_RANGE(x,min,max) - * @brief If variable x is not between or equal to max and min, the assertion triggers. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_RANGE(x, min, max) \ - UMP_DEBUG_ASSERT( (x) >= (min) && (x) <= (max), \ - (#x " out of range (%2.2f)", (double)x ) \ - ) - -/** - * @def UMP_DEBUG_ASSERT_LEQ(x,max) - * @brief If variable x is less than or equal to max, the assertion triggers. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_LEQ(x, max) \ - UMP_DEBUG_ASSERT( (x) <= (max), \ - (#x " out of range (%2.2f)", (double)x ) \ - ) - -/** - * @def UMP_DEBUG_CODE( X ) - * @brief Run the code X on debug builds. - * The code will not be used if UMP_DEBUG_SKIP_CODE is defined . - * - */ -#ifdef UMP_DEBUG_SKIP_CODE -#define UMP_DEBUG_CODE( X ) -#else -#define UMP_DEBUG_CODE( X ) X -#endif /* UMP_DEBUG_SKIP_CODE */ - -#endif /* _UMP_DEBUG_H_ */ - diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h deleted file mode 100755 index ad2e0fcee269..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2010, 2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_kernel_interface.h - * - * This file contains the kernel space part of the UMP API. - */ - -#ifndef __UMP_KERNEL_INTERFACE_H__ -#define __UMP_KERNEL_INTERFACE_H__ - - -/** @defgroup ump_kernel_space_api UMP Kernel Space API - * @{ */ - - -#include "ump_kernel_platform.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * External representation of a UMP handle in kernel space. - */ -typedef void *ump_dd_handle; - -/** - * Typedef for a secure ID, a system wide identificator for UMP memory buffers. - */ -typedef unsigned int ump_secure_id; - - -/** - * Value to indicate an invalid UMP memory handle. - */ -#define UMP_DD_HANDLE_INVALID ((ump_dd_handle)0) - - -/** - * Value to indicate an invalid secure Id. - */ -#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) - - -/** - * UMP error codes for kernel space. - */ -typedef enum -{ - UMP_DD_SUCCESS, /**< indicates success */ - UMP_DD_INVALID, /**< indicates failure */ -} ump_dd_status_code; - - -/** - * Struct used to describe a physical block used by UMP memory - */ -typedef struct ump_dd_physical_block -{ - unsigned long addr; /**< The physical address of the block */ - unsigned long size; /**< The length of the block, typically page aligned */ -} ump_dd_physical_block; - - -/** - * Retrieves the secure ID for the specified UMP memory. - * - * This identificator is unique across the entire system, and uniquely identifies - * the specified UMP memory. This identificator can later be used through the - * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" or - * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" - * functions in order to access this UMP memory, for instance from another process. - * - * @note There is a user space equivalent function called @ref ump_secure_id_get "ump_secure_id_get" - * - * @see ump_dd_handle_create_from_secure_id - * @see ump_handle_create_from_secure_id - * @see ump_secure_id_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the secure ID for the specified UMP memory. - */ -UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle mem); - - -/** - * Retrieves a handle to allocated UMP memory. - * - * The usage of UMP memory is reference counted, so this will increment the reference - * count by one for the specified UMP memory. - * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any - * use for the retrieved handle. - * - * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" - * - * @see ump_dd_reference_release - * @see ump_handle_create_from_secure_id - * - * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. - * - * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. - */ -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); - - -/** - * Retrieves the number of physical blocks used by the specified UMP memory. - * - * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed - * to describe the physical memory layout of the given UMP memory. This can later be used when calling - * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and - * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". - * - * @see ump_dd_phys_blocks_get - * @see ump_dd_phys_block_get - * - * @param mem Handle to UMP memory. - * - * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. - */ -UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); - - -/** - * Retrieves all physical memory block information for specified UMP memory. - * - * This function can be used by other device drivers in order to create MMU tables. - * - * @note This function will fail if the num_blocks parameter is either to large or to small. - * - * @see ump_dd_phys_block_get - * - * @param mem Handle to UMP memory. - * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. - * @param num_blocks The number of blocks to return in the blocks array. Use the function - * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. - * - * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. - */ -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block *blocks, unsigned long num_blocks); - - -/** - * Retrieves the physical memory block information for specified block for the specified UMP memory. - * - * This function can be used by other device drivers in order to create MMU tables. - * - * @note This function will return UMP_DD_INVALID if the specified index is out of range. - * - * @see ump_dd_phys_blocks_get - * - * @param mem Handle to UMP memory. - * @param index Which physical info block to retrieve. - * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. - * - * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. - */ -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block *block); - - -/** - * Retrieves the actual size of the specified UMP memory. - * - * The size is reported in bytes, and is typically page aligned. - * - * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" - * - * @see ump_size_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the allocated size of the specified UMP memory, in bytes. - */ -UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); - - -/** - * Adds an extra reference to the specified UMP memory. - * - * This function adds an extra reference to the specified UMP memory. This function should - * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle - * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used - * to release each copy of the UMP memory handle. - * - * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" - * for UMP handles returned from - * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", - * because these handles are already reference counted by this function. - * - * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" - * - * @see ump_reference_add - * - * @param mem Handle to UMP memory. - */ -UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); - - -/** - * Releases a reference from the specified UMP memory. - * - * This function should be called once for every reference to the UMP memory handle. - * When the last reference is released, all resources associated with this UMP memory - * handle are freed. - * - * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" - * - * @see ump_reference_release - * - * @param mem Handle to UMP memory. - */ -UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); - - -#ifdef __cplusplus -} -#endif - - -/** @} */ /* end group ump_kernel_space_api */ - - -#endif /* __UMP_KERNEL_INTERFACE_H__ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h deleted file mode 100755 index ca3f9acc6537..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2009-2010, 2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_kernel_interface.h - */ - -#ifndef __UMP_KERNEL_INTERFACE_REF_DRV_H__ -#define __UMP_KERNEL_INTERFACE_REF_DRV_H__ - -#include "ump_kernel_interface.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Turn specified physical memory into UMP memory. */ -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block *blocks, unsigned long num_blocks); - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_KERNEL_INTERFACE_REF_DRV_H__ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h deleted file mode 100755 index ed9ed33e5ba3..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2010 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_kernel_platform.h - * - * This file should define UMP_KERNEL_API_EXPORT, - * which dictates how the UMP kernel API should be exported/imported. - * Modify this file, if needed, to match your platform setup. - */ - -#ifndef __UMP_KERNEL_PLATFORM_H__ -#define __UMP_KERNEL_PLATFORM_H__ - -/** @addtogroup ump_kernel_space_api - * @{ */ - -/** - * A define which controls how UMP kernel space API functions are imported and exported. - * This define should be set by the implementor of the UMP API. - */ - -#if defined(_WIN32) - -#if defined(UMP_BUILDING_UMP_LIBRARY) -#define UMP_KERNEL_API_EXPORT __declspec(dllexport) -#else -#define UMP_KERNEL_API_EXPORT __declspec(dllimport) -#endif - -#else - -#define UMP_KERNEL_API_EXPORT - -#endif - - -/** @} */ /* end group ump_kernel_space_api */ - - -#endif /* __UMP_KERNEL_PLATFORM_H__ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_osu.h b/drivers/gpu/arm/mali400/include/ump/ump_osu.h deleted file mode 100755 index f656313e5afb..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_osu.h +++ /dev/null @@ -1,423 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_osu.h - * Defines the OS abstraction layer for the base driver - */ - -#ifndef __UMP_OSU_H__ -#define __UMP_OSU_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef unsigned int u32; -#ifdef _MSC_VER -typedef unsigned __int64 u64; -typedef signed __int64 s64; -#else -typedef unsigned long long u64; -typedef signed long long s64; -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef unsigned long ump_bool; - -#ifndef UMP_TRUE -#define UMP_TRUE ((ump_bool)1) -#endif - -#ifndef UMP_FALSE -#define UMP_FALSE ((ump_bool)0) -#endif - -#define UMP_STATIC static - -/** - * @addtogroup ump_user_space_api Unified Device Driver (UDD) APIs used by UMP - * - * @{ - */ - -/** - * @defgroup ump_osuapi UDD OS Abstraction for User-side (OSU) APIs for UMP - * - * @{ - */ - -/* The following is necessary to prevent the _ump_osk_errcode_t doxygen from - * becoming unreadable: */ -/** @cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */ - -/** - * @brief OSU/OSK Error codes. - * - * Each OS may use its own set of error codes, and may require that the - * User/Kernel interface take certain error code. This means that the common - * error codes need to be sufficiently rich to pass the correct error code - * through from the OSK/OSU to U/K layer, across all OSs. - * - * The result is that some error codes will appear redundant on some OSs. - * Under all OSs, the OSK/OSU layer must translate native OS error codes to - * _ump_osk/u_errcode_t codes. Similarly, the U/K layer must translate from - * _ump_osk/u_errcode_t codes to native OS error codes. - * - */ -typedef enum -{ - _UMP_OSK_ERR_OK = 0, /**< Success. */ - _UMP_OSK_ERR_FAULT = -1, /**< General non-success */ - _UMP_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */ - _UMP_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */ - _UMP_OSK_ERR_NOMEM = -4, /**< Insufficient memory */ - _UMP_OSK_ERR_TIMEOUT = -5, /**< Timeout occured */ - _UMP_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */ - _UMP_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */ - _UMP_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */ - _UMP_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */ -} _ump_osk_errcode_t; - -/** @endcond */ /* end cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */ - -/** - * @brief OSU Error codes. - * - * OSU error codes - enum values intentionally same as OSK - */ -typedef enum -{ - _UMP_OSU_ERR_OK = 0, /**< Success. */ - _UMP_OSU_ERR_FAULT = -1, /**< General non-success */ - _UMP_OSU_ERR_TIMEOUT = -2, /**< Timeout occured */ -} _ump_osu_errcode_t; - -/** @brief Translate OSU error code to base driver error code. - * - * The _UMP_OSU_TRANSLATE_ERROR macro translates an OSU error code to the - * error codes in use by the base driver. - */ -#define _UMP_OSU_TRANSLATE_ERROR(_ump_osu_errcode) ( ( _UMP_OSU_ERR_OK == (_ump_osu_errcode) ) ? UMP_ERR_NO_ERROR : UMP_ERR_FUNCTION_FAILED) - -/** @defgroup _ump_osu_lock OSU Mutual Exclusion Locks - * @{ */ - -/** @brief OSU Mutual Exclusion Lock flags type. - * - * This is made to look like and function identically to the OSK locks (refer - * to \ref _ump_osk_lock). However, please note the following \b important - * differences: - * - the OSU default lock is a Sleeping, non-interruptible mutex. - * - the OSU adds the ANYUNLOCK type of lock which allows a thread which doesn't - * own the lock to release the lock. - * - the order parameter when creating a lock is currently unused - * - * @note Pay careful attention to the difference in default locks for OSU and - * OSK locks; OSU locks are always non-interruptible, but OSK locks are by - * default, interruptible. This has implications for systems that do not - * distinguish between user and kernel mode. - */ -typedef enum -{ - _UMP_OSU_LOCKFLAG_DEFAULT = 0, /**< Default lock type. */ - /** @enum _ump_osu_lock_flags_t - * - * Flags from 0x0--0x8000 are RESERVED for Kernel-mode - */ - _UMP_OSU_LOCKFLAG_ANYUNLOCK = 0x10000, /**< Mutex that guarantees that any thread can unlock it when locked. Otherwise, this will not be possible. */ - /** @enum _ump_osu_lock_flags_t - * - * Flags from 0x10000 are RESERVED for User-mode - */ - _UMP_OSU_LOCKFLAG_STATIC = 0x20000, /* Flag in OSU reserved range to identify lock as a statically initialized lock */ - -} _ump_osu_lock_flags_t; - -typedef enum -{ - _UMP_OSU_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */ - _UMP_OSU_LOCKMODE_RW = 0x0, /**< Default. Lock is used to protect data that is read from and written to */ - /** @enum _ump_osu_lock_mode_t - * - * Lock modes 0x1--0x3F are RESERVED for Kernel-mode */ -} _ump_osu_lock_mode_t; - -/** @brief Private type for Mutual Exclusion lock objects. */ -typedef struct _ump_osu_lock_t_struct _ump_osu_lock_t; - -/** @brief The number of static locks supported in _ump_osu_lock_static(). */ -#define UMP_OSU_STATIC_LOCK_COUNT (sizeof(_ump_osu_static_locks) / sizeof(_ump_osu_lock_t)) - -/** @} */ /* end group _ump_osu_lock */ - -/** @defgroup _ump_osu_memory OSU Memory Allocation - * @{ */ - -/** @brief Allocate zero-initialized memory. - * - * Returns a buffer capable of containing at least \a n elements of \a size - * bytes each. The buffer is initialized to zero. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _ump_osu_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * @param n Number of elements to allocate - * @param size Size of each element - * @return On success, the zero-initialized buffer allocated. NULL on failure - */ -void *_ump_osu_calloc(u32 n, u32 size); - -/** @brief Allocate memory. - * - * Returns a buffer capable of containing at least \a size bytes. The - * contents of the buffer are undefined. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _ump_osu_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * Remember to free memory using _ump_osu_free(). - * @param size Number of bytes to allocate - * @return On success, the buffer allocated. NULL on failure. - */ -void *_ump_osu_malloc(u32 size); - -/** @brief Free memory. - * - * Reclaims the buffer pointed to by the parameter \a ptr for the system. - * All memory returned from _ump_osu_malloc(), _ump_osu_calloc() and - * _ump_osu_realloc() must be freed before the application exits. Otherwise, - * a memory leak will occur. - * - * Memory must be freed once. It is an error to free the same non-NULL pointer - * more than once. - * - * It is legal to free the NULL pointer. - * - * @param ptr Pointer to buffer to free - */ -void _ump_osu_free(void *ptr); - -/** @brief Copies memory. - * - * Copies the \a len bytes from the buffer pointed by the parameter \a src - * directly to the buffer pointed by \a dst. - * - * It is an error for \a src to overlap \a dst anywhere in \a len bytes. - * - * @param dst Pointer to the destination array where the content is to be - * copied. - * @param src Pointer to the source of data to be copied. - * @param len Number of bytes to copy. - * @return \a dst is always passed through unmodified. - */ -void *_ump_osu_memcpy(void *dst, const void *src, u32 len); - -/** @brief Fills memory. - * - * Sets the first \a size bytes of the block of memory pointed to by \a ptr to - * the specified value - * @param ptr Pointer to the block of memory to fill. - * @param chr Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB) - * are used. - * @param size Number of bytes to be set to the value. - * @return \a ptr is always passed through unmodified - */ -void *_ump_osu_memset(void *ptr, u32 chr, u32 size); - -/** @} */ /* end group _ump_osu_memory */ - - -/** @addtogroup _ump_osu_lock - * @{ */ - -/** @brief Initialize a Mutual Exclusion Lock. - * - * Locks are created in the signalled (unlocked) state. - * - * The parameter \a initial must be zero. - * - * At present, the parameter \a order must be zero. It remains for future - * expansion for mutex order checking. - * - * @param flags flags combined with bitwise OR ('|'), or zero. There are - * restrictions on which flags can be combined, see \ref _ump_osu_lock_flags_t. - * @param initial For future expansion into semaphores. SBZ. - * @param order The locking order of the mutex. SBZ. - * @return On success, a pointer to a \ref _ump_osu_lock_t object. NULL on failure. - */ -_ump_osu_lock_t *_ump_osu_lock_init(_ump_osu_lock_flags_t flags, u32 initial, u32 order); - -/** @brief Obtain a statically initialized Mutual Exclusion Lock. - * - * Retrieves a reference to a statically initialized lock. Up to - * _UMP_OSU_STATIC_LOCK_COUNT statically initialized locks are - * available. Only _ump_osu_lock_wait(), _ump_osu_lock_trywait(), - * _ump_osu_lock_signal() can be used with statically initialized locks. - * _UMP_OSU_LOCKMODE_RW mode should be used when waiting and signalling - * statically initialized locks. - * - * For the same \a nr a pointer to the same statically initialized lock is - * returned. That is, given the following code: - * @code - * extern u32 n; - * - * _ump_osu_lock_t *locka = _ump_osu_lock_static(n); - * _ump_osu_lock_t *lockb = _ump_osu_lock_static(n); - * @endcode - * Then (locka == lockb), for all 0 <= n < UMP_OSU_STATIC_LOCK_COUNT. - * - * @param nr index of a statically initialized lock [0..UMP_OSU_STATIC_LOCK_COUNT-1] - * @return On success, a pointer to a _ump_osu_lock_t object. NULL on failure. - */ -_ump_osu_lock_t *_ump_osu_lock_static(u32 nr); - -/** @brief Initialize a Mutual Exclusion Lock safely across multiple threads. - * - * The _ump_osu_lock_auto_init() function guarantees that the given lock will - * be initialized once and precisely once, even in a situation involving - * multiple threads. - * - * This is necessary because the first call to certain Public API functions must - * initialize the API. However, there can be a race involved to call the first - * library function in multi-threaded applications. To resolve this race, a - * mutex can be used. This mutex must be initialized, but initialized only once - * by any thread that might compete for its initialization. This function - * guarantees the initialization to happen correctly, even when there is an - * initialization race between multiple threads. - * - * Otherwise, the operation is identical to the _ump_osu_lock_init() function. - * For more details, refer to _ump_osu_lock_init(). - * - * @param pplock pointer to storage for a _ump_osu_lock_t pointer. This - * _ump_osu_lock_t pointer may point to a _ump_osu_lock_t that has been - * initialized already - * @param flags flags combined with bitwise OR ('|'), or zero. There are - * restrictions on which flags can be combined. Refer to - * \ref _ump_osu_lock_flags_t for more information. - * The absence of any flags (the value 0) results in a sleeping-mutex, - * which is non-interruptible. - * @param initial For future expansion into semaphores. SBZ. - * @param order The locking order of the mutex. SBZ. - * @return On success, _UMP_OSU_ERR_OK is returned and a pointer to an - * initialized \ref _ump_osu_lock_t object is written into \a *pplock. - * _UMP_OSU_ERR_FAULT is returned on failure. - */ -_ump_osu_errcode_t _ump_osu_lock_auto_init(_ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order); - -/** @brief Wait for a lock to be signalled (obtained). - * - * After a thread has successfully waited on the lock, the lock is obtained by - * the thread, and is marked as unsignalled. The thread releases the lock by - * signalling it. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @return On success, _UMP_OSU_ERR_OK, _UMP_OSU_ERR_FAULT on error. - */ -_ump_osu_errcode_t _ump_osu_lock_wait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode); - -/** @brief Wait for a lock to be signalled (obtained) with timeout - * - * After a thread has successfully waited on the lock, the lock is obtained by - * the thread, and is marked as unsignalled. The thread releases the lock by - * signalling it. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * This version can return early if it cannot obtain the lock within the given timeout. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @param timeout Relative time in microseconds for the timeout - * @return _UMP_OSU_ERR_OK if the lock was obtained, _UMP_OSU_ERR_TIMEOUT if the timeout expired or _UMP_OSU_ERR_FAULT on error. - */ -_ump_osu_errcode_t _ump_osu_lock_timed_wait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout); - -/** @brief Test for a lock to be signalled and obtains the lock when so. - * - * Obtains the lock only when it is in signalled state. The lock is then - * marked as unsignalled. The lock is released again by signalling - * it by _ump_osu_lock_signal(). - * - * If the lock could not be obtained immediately (that is, another thread - * currently holds the lock), then this function \b does \b not wait for the - * lock to be in a signalled state. Instead, an error code is immediately - * returned to indicate that the thread could not obtain the lock. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @return When the lock was obtained, _UMP_OSU_ERR_OK. If the lock could not - * be obtained, _UMP_OSU_ERR_FAULT. - */ -_ump_osu_errcode_t _ump_osu_lock_trywait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode); - -/** @brief Signal (release) a lock. - * - * Locks may only be signalled by the thread that originally waited upon the - * lock, unless the lock was created using the _UMP_OSU_LOCKFLAG_ANYUNLOCK flag. - * - * @param lock the lock to signal (release). - * @param mode the mode in which the lock should be obtained. This must match - * the mode in which the lock was waited upon. - */ -void _ump_osu_lock_signal(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode); - -/** @brief Terminate a lock. - * - * This terminates a lock and frees all associated resources. - * - * It is a programming error to terminate the lock when it is held (unsignalled) - * by a thread. - * - * @param lock the lock to terminate. - */ -void _ump_osu_lock_term(_ump_osu_lock_t *lock); -/** @} */ /* end group _ump_osu_lock */ - -/** @} */ /* end group osuapi */ - -/** @} */ /* end group uddapi */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_OSU_H__ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_platform.h b/drivers/gpu/arm/mali400/include/ump/ump_platform.h deleted file mode 100755 index 6560fb7cf3c1..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_platform.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2011, 2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_platform.h - * - * This file should define UMP_API_EXPORT, - * which dictates how the UMP user space API should be exported/imported. - * Modify this file, if needed, to match your platform setup. - */ - -#ifndef __UMP_PLATFORM_H__ -#define __UMP_PLATFORM_H__ - -/** @addtogroup ump_user_space_api - * @{ */ - -/** - * A define which controls how UMP user space API functions are imported and exported. - * This define should be set by the implementor of the UMP API. - */ -#if defined(_WIN32) - -#define UMP_API_EXPORT - -#elif defined(__SYMBIAN32__) - -#define UMP_API_EXPORT IMPORT_C - -#else - -#if defined(__GNUC__) -#if __GNUC__ >= 4 -# define MALI_VISIBLE __attribute__ ((visibility ("default"))) /**< Function should be visible from outside the dll */ -#else -# define MALI_VISIBLE -#endif - -#elif defined(__ARMCC_VERSION) -/* ARMCC specific */ -# define MALI_VISIBLE __declspec(dllexport) - -#else -# define MALI_VISIBLE - -#endif - -#define UMP_API_EXPORT MALI_VISIBLE - -#endif - -/** @} */ /* end group ump_user_space_api */ - - -#endif /* __UMP_PLATFORM_H__ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h b/drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h deleted file mode 100755 index c1c09650111d..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_ref_drv.h - * - * Reference driver extensions to the UMP user space API for allocating UMP memory - */ - -#ifndef _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ -#define _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ - -#include "ump.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum -{ - /* This enum must match with the IOCTL enum in ump_ioctl.h */ - UMP_REF_DRV_CONSTRAINT_NONE = 0, - UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, - UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4, - UMP_REF_DRV_CONSTRAINT_PRE_RESERVE = 8, -} ump_alloc_constraints; - -/** Allocate an UMP handle containing a memory buffer. - * Input: Size: The minimum size for the allocation. - * Usage: If this is UMP_REF_DRV_CONSTRAINT_USE_CACHE, the allocation is mapped as cached by the cpu. - * If it is UMP_REF_DRV_CONSTRAINT_NONE it is mapped as noncached. - * The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported.*/ -UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage); - -UMP_API_EXPORT int ump_phy_addr_get(ump_handle memh); - -typedef enum -{ - UMP_MSYNC_CLEAN = 0 , - UMP_MSYNC_CLEAN_AND_INVALIDATE = 1, - UMP_MSYNC_INVALIDATE = 2, - UMP_MSYNC_READOUT_CACHE_ENABLED = 128, -} ump_cpu_msync_op; - -typedef enum -{ - UMP_READ = 1, - UMP_READ_WRITE = 3, -} ump_lock_usage; - -/** Flushing cache for an ump_handle. - * The function will always CLEAN_AND_INVALIDATE as long as the \a op is not UMP_MSYNC_READOUT_CACHE_ENABLED. - * If so it will only report back if the given ump_handle is cacheable. - * At the momement the implementation does not use \a address or \a size. - * Return value is 1 if cache is enabled, and 0 if it is disabled for the given allocation.*/ -UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void *address, int size); - - -typedef enum -{ - UMP_USED_BY_CPU = 0, - UMP_USED_BY_MALI = 1, - UMP_USED_BY_UNKNOWN_DEVICE = 100, -} ump_hw_usage; - -typedef enum -{ - UMP_CACHE_OP_START = 0, - UMP_CACHE_OP_FINISH = 1, -} ump_cache_op_control; - -/** Cache operation control. Tell when cache maintenance operations start and end. -This will allow the kernel to merge cache operations togheter, thus making them faster */ -UMP_API_EXPORT int ump_cache_operations_control(ump_cache_op_control op); - -/** Memory synchronization - cache flushing if previous user was different hardware */ -UMP_API_EXPORT int ump_switch_hw_usage(ump_handle mem, ump_hw_usage new_user); - -/** Memory synchronization - cache flushing if previous user was different hardware */ -UMP_API_EXPORT int ump_switch_hw_usage_secure_id(ump_secure_id ump_id, ump_hw_usage new_user); - -/** Locking buffer. Blocking call if the buffer is already locked. */ -UMP_API_EXPORT int ump_lock(ump_handle mem, ump_lock_usage lock_usage); - -/** Locking buffer. Blocking call if the buffer is already locked. */ -UMP_API_EXPORT int ump_lock_secure_id(ump_secure_id ump_id, ump_lock_usage lock_usage); - -/** Unlocking buffer. Let other users lock the buffer for their usage */ -UMP_API_EXPORT int ump_unlock(ump_handle mem); - -/** Unlocking buffer. Let other users lock the buffer for their usage */ -UMP_API_EXPORT int ump_unlock_secure_id(ump_secure_id ump_id); - - -#ifdef __cplusplus -} -#endif - -#endif /*_UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ */ diff --git a/drivers/gpu/arm/mali400/include/ump/ump_uk_types.h b/drivers/gpu/arm/mali400/include/ump/ump_uk_types.h deleted file mode 100755 index 8db8d55030af..000000000000 --- a/drivers/gpu/arm/mali400/include/ump/ump_uk_types.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_uk_types.h - * Defines the types and constants used in the user-kernel interface - */ - -#ifndef __UMP_UK_TYPES_H__ -#define __UMP_UK_TYPES_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Helpers for API version handling */ -#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) -#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) -#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) -#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) - -/** - * API version define. - * Indicates the version of the kernel API - * The version is a 16bit integer incremented on each API change. - * The 16bit integer is stored twice in a 32bit integer - * So for version 1 the value would be 0x00010001 - */ -#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2) - -typedef enum -{ - _UMP_IOC_QUERY_API_VERSION = 1, - _UMP_IOC_ALLOCATE, - _UMP_IOC_RELEASE, - _UMP_IOC_SIZE_GET, - _UMP_IOC_MAP_MEM, /* not used in Linux */ - _UMP_IOC_UNMAP_MEM, /* not used in Linux */ - _UMP_IOC_MSYNC, - _UMP_IOC_CACHE_OPERATIONS_CONTROL, - _UMP_IOC_SWITCH_HW_USAGE, - _UMP_IOC_LOCK, - _UMP_IOC_UNLOCK, -}_ump_uk_functions; - -typedef enum -{ - UMP_REF_DRV_UK_CONSTRAINT_NONE = 0, - UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1, - UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 4, - UMP_REF_DRV_UK_CONSTRAINT_PRE_RESERVE = 8, - UMP_REF_DRV_UK_CONSTRAINT_MEM_SWITCH = 16, -} ump_uk_alloc_constraints; - -typedef enum -{ - _UMP_UK_MSYNC_CLEAN = 0, - _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1, - _UMP_UK_MSYNC_INVALIDATE = 2, - _UMP_UK_MSYNC_FLUSH_L1 = 3, - _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128, -} ump_uk_msync_op; - -typedef enum -{ - _UMP_UK_CACHE_OP_START = 0, - _UMP_UK_CACHE_OP_FINISH = 1, -} ump_uk_cache_op_control; - -typedef enum -{ - _UMP_UK_READ = 1, - _UMP_UK_READ_WRITE = 3, -} ump_uk_lock_usage; - -typedef enum -{ - _UMP_UK_USED_BY_CPU = 0, - _UMP_UK_USED_BY_MALI = 1, - _UMP_UK_USED_BY_UNKNOWN_DEVICE = 100, -} ump_uk_user; - -/** - * Get API version ([in,out] u32 api_version, [out] u32 compatible) - */ -typedef struct _ump_uk_api_version_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */ - u32 compatible; /**< Non-null if the device is compatible with the client */ -} _ump_uk_api_version_s; - -/** - * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints) - */ -typedef struct _ump_uk_allocate_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Return value from DD to Userdriver */ - u32 size; /**< Input and output. Requested size; input. Returned size; output */ - ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ -} _ump_uk_allocate_s; - -/** - * SIZE_GET ([in] u32 secure_id, [out]size ) - */ -typedef struct _ump_uk_size_get_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ - u32 size; /**< Returned size; output */ -} _ump_uk_size_get_s; - -/** - * Release ([in] u32 secure_id) - */ -typedef struct _ump_uk_release_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ -} _ump_uk_release_s; - -typedef struct _ump_uk_map_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [out] Returns user-space virtual address for the mapping */ - void *phys_addr; /**< [in] physical address */ - unsigned long size; /**< [in] size */ - u32 secure_id; /**< [in] secure_id to assign to mapping */ - void *_ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */ - u32 cookie; - u32 is_cached; /**< [in,out] caching of CPU mappings */ -} _ump_uk_map_mem_s; - -typedef struct _ump_uk_unmap_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; - u32 size; - void *_ukk_private; - u32 cookie; -} _ump_uk_unmap_mem_s; - -typedef struct _ump_uk_msync_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [in] mapping addr */ - void *address; /**< [in] flush start addr */ - u32 size; /**< [in] size to flush */ - ump_uk_msync_op op; /**< [in] flush operation */ - u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - u32 is_cached; /**< [out] caching of CPU mappings */ -} _ump_uk_msync_s; - -typedef struct _ump_uk_cache_operations_control_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - ump_uk_cache_op_control op; /**< [in] cache operations start/stop */ -} _ump_uk_cache_operations_control_s; - - -typedef struct _ump_uk_switch_hw_usage_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - ump_uk_user new_user; /**< [in] cookie stored with reference to the kernel mapping internals */ - -} _ump_uk_switch_hw_usage_s; - -typedef struct _ump_uk_lock_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - ump_uk_lock_usage lock_usage; -} _ump_uk_lock_s; - -typedef struct _ump_uk_unlock_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ -} _ump_uk_unlock_s; -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UK_TYPES_H__ */ diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dma.c b/drivers/gpu/arm/mali400/mali/common/mali_dma.c deleted file mode 100755 index b3529a317fa5..000000000000 --- a/drivers/gpu/arm/mali400/mali/common/mali_dma.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2012-2014 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_hw_core.h" -#include "mali_dma.h" - -/** - * Size of the Mali-450 DMA unit registers in bytes. - */ -#define MALI450_DMA_REG_SIZE 0x08 - -/** - * Value that appears in MEMSIZE if an error occurs when reading the command list. - */ -#define MALI450_DMA_BUS_ERR_VAL 0xffffffff - -/** - * Mali DMA registers - * Used in the register read/write routines. - * See the hardware documentation for more information about each register. - */ -typedef enum mali_dma_register { - - MALI450_DMA_REG_SOURCE_ADDRESS = 0x0000, - MALI450_DMA_REG_SOURCE_SIZE = 0x0004, -} mali_dma_register; - -struct mali_dma_core { - struct mali_hw_core hw_core; /**< Common for all HW cores */ - _mali_osk_spinlock_t *lock; /**< Lock protecting access to DMA core */ - mali_dma_pool pool; /**< Memory pool for command buffers */ -}; - -static struct mali_dma_core *mali_global_dma_core = NULL; - -struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource) -{ - struct mali_dma_core *dma; - _mali_osk_errcode_t err; - - MALI_DEBUG_ASSERT(NULL == mali_global_dma_core); - - dma = _mali_osk_malloc(sizeof(struct mali_dma_core)); - if (dma == NULL) goto alloc_failed; - - dma->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_DMA_COMMAND); - if (NULL == dma->lock) goto lock_init_failed; - - dma->pool = mali_dma_pool_create(MALI_DMA_CMD_BUF_SIZE, 4, 0); - if (NULL == dma->pool) goto dma_pool_failed; - - err = mali_hw_core_create(&dma->hw_core, resource, MALI450_DMA_REG_SIZE); - if (_MALI_OSK_ERR_OK != err) goto hw_core_failed; - - mali_global_dma_core = dma; - MALI_DEBUG_PRINT(2, ("Mali DMA: Created Mali APB DMA unit\n")); - return dma; - - /* Error handling */ - -hw_core_failed: - mali_dma_pool_destroy(dma->pool); -dma_pool_failed: - _mali_osk_spinlock_term(dma->lock); -lock_init_failed: - _mali_osk_free(dma); -alloc_failed: - MALI_DEBUG_PRINT(2, ("Mali DMA: Failed to create APB DMA unit\n")); - return NULL; -} - -void mali_dma_delete(struct mali_dma_core *dma) -{ - MALI_DEBUG_ASSERT_POINTER(dma); - - MALI_DEBUG_PRINT(2, ("Mali DMA: Deleted Mali APB DMA unit\n")); - - mali_hw_core_delete(&dma->hw_core); - _mali_osk_spinlock_term(dma->lock); - mali_dma_pool_destroy(dma->pool); - _mali_osk_free(dma); -} - -static void mali_dma_bus_error(struct mali_dma_core *dma) -{ - u32 addr = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS); - - MALI_PRINT_ERROR(("Mali DMA: Bus error when reading command list from 0x%lx\n", addr)); - MALI_IGNORE(addr); - - /* Clear the bus error */ - mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, 0); -} - -static mali_bool mali_dma_is_busy(struct mali_dma_core *dma) -{ - u32 val; - mali_bool dma_busy_flag = MALI_FALSE; - - MALI_DEBUG_ASSERT_POINTER(dma); - - val = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE); - - if (MALI450_DMA_BUS_ERR_VAL == val) { - /* Bus error reading command list */ - mali_dma_bus_error(dma); - return MALI_FALSE; - } - if (val > 0) { - dma_busy_flag = MALI_TRUE; - } - - return dma_busy_flag; -} - -static void mali_dma_start_transfer(struct mali_dma_core *dma, mali_dma_cmd_buf *buf) -{ - u32 memsize = buf->size * 4; - u32 addr = buf->phys_addr; - - MALI_DEBUG_ASSERT_POINTER(dma); - MALI_DEBUG_ASSERT(memsize < (1 << 16)); - MALI_DEBUG_ASSERT(0 == (memsize & 0x3)); /* 4 byte aligned */ - - MALI_DEBUG_ASSERT(!mali_dma_is_busy(dma)); - - /* Writes the physical source memory address of chunk containing command headers and data */ - mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS, addr); - - /* Writes the length of transfer */ - mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, memsize); -} - -_mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf) -{ - MALI_DEBUG_ASSERT_POINTER(buf); - - buf->virt_addr = (u32 *)mali_dma_pool_alloc(mali_global_dma_core->pool, &buf->phys_addr); - if (NULL == buf->virt_addr) { - return _MALI_OSK_ERR_NOMEM; - } - - /* size contains the number of words in the buffer and is incremented - * as commands are added to the buffer. */ - buf->size = 0; - - return _MALI_OSK_ERR_OK; -} - -void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf) -{ - MALI_DEBUG_ASSERT_POINTER(buf); - - if (NULL == buf->virt_addr) return; - - mali_dma_pool_free(mali_global_dma_core->pool, buf->virt_addr, buf->phys_addr); - - buf->virt_addr = NULL; -} - -_mali_osk_errcode_t mali_dma_start(struct mali_dma_core *dma, mali_dma_cmd_buf *buf) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - - _mali_osk_spinlock_lock(dma->lock); - - if (mali_dma_is_busy(dma)) { - err = _MALI_OSK_ERR_BUSY; - goto out; - } - - mali_dma_start_transfer(dma, buf); - -out: - _mali_osk_spinlock_unlock(dma->lock); - return err; -} - -void mali_dma_debug(struct mali_dma_core *dma) -{ - MALI_DEBUG_ASSERT_POINTER(dma); - MALI_DEBUG_PRINT(1, ("DMA unit registers:\n\t%08x, %08x\n", - mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS), - mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE) - )); - -} - -struct mali_dma_core *mali_dma_get_global_dma_core(void) -{ - /* Returns the global dma core object */ - return mali_global_dma_core; -} diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dma.h b/drivers/gpu/arm/mali400/mali/common/mali_dma.h deleted file mode 100755 index 16c57711a9d7..000000000000 --- a/drivers/gpu/arm/mali400/mali/common/mali_dma.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2012-2014 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -#ifndef __MALI_DMA_H__ -#define __MALI_DMA_H__ - -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_hw_core.h" - -#define MALI_DMA_CMD_BUF_SIZE 1024 - -typedef struct mali_dma_cmd_buf { - u32 *virt_addr; /**< CPU address of command buffer */ - mali_dma_addr phys_addr; /**< Physical address of command buffer */ - u32 size; /**< Number of prepared words in command buffer */ -} mali_dma_cmd_buf; - -/** @brief Create a new DMA unit - * - * This is called from entry point of the driver in order to create and - * intialize the DMA resource - * - * @param resource it will be a pointer to a DMA resource - * @return DMA object on success, NULL on failure - */ -struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource); - -/** @brief Delete DMA unit - * - * This is called on entry point of driver if the driver initialization fails - * after initialization of the DMA unit. It is also called on the exit of the - * driver to delete the DMA resource - * - * @param dma Pointer to DMA unit object - */ -void mali_dma_delete(struct mali_dma_core *dma); - -/** @brief Retrieves the MALI DMA core object (if there is) - * - * @return The Mali DMA object otherwise NULL - */ -struct mali_dma_core *mali_dma_get_global_dma_core(void); - -/** - * @brief Run a command buffer on the DMA unit - * - * @param dma Pointer to the DMA unit to use - * @param buf Pointer to the command buffer to use - * @return _MALI_OSK_ERR_OK if the buffer was started successfully, - * _MALI_OSK_ERR_BUSY if the DMA unit is busy. - */ -_mali_osk_errcode_t mali_dma_start(struct mali_dma_core *dma, mali_dma_cmd_buf *buf); - -/** - * @brief Create a DMA command - * - * @param core Mali core - * @param reg offset to register of core - * @param n number of registers to write - */ -MALI_STATIC_INLINE u32 mali_dma_command_write(struct mali_hw_core *core, u32 reg, u32 n) -{ - u32 core_offset = core->phys_offset; - - MALI_DEBUG_ASSERT(reg < 0x2000); - MALI_DEBUG_ASSERT(n < 0x800); - MALI_DEBUG_ASSERT(core_offset < 0x30000); - MALI_DEBUG_ASSERT(0 == ((core_offset + reg) & ~0x7FFFF)); - - return (n << 20) | (core_offset + reg); -} - -/** - * @brief Add a array write to DMA command buffer - * - * @param buf DMA command buffer to fill in - * @param core Core to do DMA to - * @param reg Register on core to start writing to - * @param data Pointer to data to write - * @param count Number of 4 byte words to write - */ -MALI_STATIC_INLINE void mali_dma_write_array(mali_dma_cmd_buf *buf, struct mali_hw_core *core, - u32 reg, u32 *data, u32 count) -{ - MALI_DEBUG_ASSERT((buf->size + 1 + count) < MALI_DMA_CMD_BUF_SIZE / 4); - - buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, count); - - _mali_osk_memcpy(buf->virt_addr + buf->size, data, count * sizeof(*buf->virt_addr)); - - buf->size += count; -} - -/** - * @brief Add a conditional array write to DMA command buffer - * - * @param buf DMA command buffer to fill in - * @param core Core to do DMA to - * @param reg Register on core to start writing to - * @param data Pointer to data to write - * @param count Number of 4 byte words to write - * @param ref Pointer to referance data that can be skipped if equal - */ -MALI_STATIC_INLINE void mali_dma_write_array_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core, - u32 reg, u32 *data, u32 count, const u32 *ref) -{ - /* Do conditional array writes are not yet implemented, fallback to a - * normal array write. */ - mali_dma_write_array(buf, core, reg, data, count); -} - -/** - * @brief Add a conditional register write to the DMA command buffer - * - * If the data matches the reference the command will be skipped. - * - * @param buf DMA command buffer to fill in - * @param core Core to do DMA to - * @param reg Register on core to start writing to - * @param data Pointer to data to write - * @param ref Pointer to referance data that can be skipped if equal - */ -MALI_STATIC_INLINE void mali_dma_write_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core, - u32 reg, u32 data, const u32 ref) -{ - /* Skip write if reference value is equal to data. */ - if (data == ref) return; - - buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1); - - buf->virt_addr[buf->size++] = data; - - MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4); -} - -/** - * @brief Add a register write to the DMA command buffer - * - * @param buf DMA command buffer to fill in - * @param core Core to do DMA to - * @param reg Register on core to start writing to - * @param data Pointer to data to write - */ -MALI_STATIC_INLINE void mali_dma_write(mali_dma_cmd_buf *buf, struct mali_hw_core *core, - u32 reg, u32 data) -{ - buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1); - - buf->virt_addr[buf->size++] = data; - - MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4); -} - -/** - * @brief Prepare DMA command buffer for use - * - * This function allocates the DMA buffer itself. - * - * @param buf The mali_dma_cmd_buf to prepare - * @return _MALI_OSK_ERR_OK if the \a buf is ready to use - */ -_mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf); - -/** - * @brief Check if a DMA command buffer is ready for use - * - * @param buf The mali_dma_cmd_buf to check - * @return MALI_TRUE if buffer is usable, MALI_FALSE otherwise - */ -MALI_STATIC_INLINE mali_bool mali_dma_cmd_buf_is_valid(mali_dma_cmd_buf *buf) -{ - return NULL != buf->virt_addr; -} - -/** - * @brief Return a DMA command buffer - * - * @param buf Pointer to DMA command buffer to return - */ -void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf); - -#endif /* __MALI_DMA_H__ */ diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h b/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h deleted file mode 100755 index 1cfbd7707b65..000000000000 --- a/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2012-2014 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -#ifndef __MALI_GP_SCHEDULER_H__ -#define __MALI_GP_SCHEDULER_H__ - -#include "mali_osk.h" -#include "mali_gp_job.h" -#include "mali_group.h" - -_mali_osk_errcode_t mali_gp_scheduler_initialize(void); -void mali_gp_scheduler_terminate(void); - -void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success); -void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job); -u32 mali_gp_scheduler_dump_state(char *buf, u32 size); - -void mali_gp_scheduler_suspend(void); -void mali_gp_scheduler_resume(void); - -/** - * @brief Abort all running and queued GP jobs from session. - * -* This functions aborts all GP jobs from the specified session. Queued jobs are removed from the -* queue and jobs currently running on a core will be aborted. - * - * @param session Session that is aborting. - */ -void mali_gp_scheduler_abort_session(struct mali_session_data *session); - -/** - * @brief Reset all groups - * - * This function resets all groups known by the GP scheuduler. This must be - * called after the Mali HW has been powered on in order to reset the HW. - */ -void mali_gp_scheduler_reset_all_groups(void); - -/** - * @brief Zap TLB on all groups with \a session active - * - * The scheculer will zap the session on all groups it owns. - */ -void mali_gp_scheduler_zap_all_active(struct mali_session_data *session); - -/** - * @brief Re-enable a group that has been disabled with mali_gp_scheduler_disable_group - * - * If a Mali PMU is present, the group will be powered back on and added back - * into the GP scheduler. - * - * @param group Pointer to the group to enable - */ -void mali_gp_scheduler_enable_group(struct mali_group *group); - -/** - * @brief Disable a group - * - * The group will be taken out of the GP scheduler and powered off, if a Mali - * PMU is present. - * - * @param group Pointer to the group to disable - */ -void mali_gp_scheduler_disable_group(struct mali_group *group); - -/** - * @brief Used by the Timeline system to queue a GP job. - * - * @note @ref mali_scheduler_schedule_from_mask() should be called if this function returns non-zero. - * - * @param job The GP job that is being activated. - * - * @return A scheduling bitmask that can be used to decide if scheduling is necessary after this - * call. - */ -mali_scheduler_mask mali_gp_scheduler_activate_job(struct mali_gp_job *job); - -/** - * @brief Schedule queued jobs on idle cores. - */ -void mali_gp_scheduler_schedule(void); - -/** - * @brief Submit a GP job to the GP scheduler. - * - * This will add the GP job to the Timeline system. - * - * @param session Session this job belongs to. - * @param job GP job that will be submitted - * @return Point on GP timeline for job. - */ -mali_timeline_point mali_gp_scheduler_submit_job(struct mali_session_data *session, struct mali_gp_job *job); - -#endif /* __MALI_GP_SCHEDULER_H__ */ diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h b/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h deleted file mode 100755 index 2f77e22f92ec..000000000000 --- a/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2012-2014 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -#ifndef __MALI_PP_SCHEDULER_H__ -#define __MALI_PP_SCHEDULER_H__ - -#include "mali_osk.h" -#include "mali_pp_job.h" -#include "mali_group.h" -#include "linux/mali/mali_utgard.h" - -/** Initalize the HW independent parts of the PP scheduler - */ -_mali_osk_errcode_t mali_pp_scheduler_initialize(void); -void mali_pp_scheduler_terminate(void); - -/** Poplulate the PP scheduler with groups - */ -void mali_pp_scheduler_populate(void); -void mali_pp_scheduler_depopulate(void); - -/** - * @brief Handle job completion. - * - * Will attempt to start a new job on the locked group. - * - * If all sub jobs have completed the job's tracker will be released, any other resources associated - * with the job will be freed. A notification will also be sent to user space. - * - * Releasing the tracker might activate other jobs, so if appropriate we also schedule them. - * - * @note Group must be locked when entering this function. Will be unlocked before exiting. - * - * @param group The group that completed the job. - * @param job The job that is done. - * @param sub_job Sub job of job. - * @param success MALI_TRUE if job completed successfully, MALI_FALSE if not. - * @param in_upper_half MALI_TRUE if called from upper half, MALI_FALSE if not. - */ -void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success, mali_bool in_upper_half); - -void mali_pp_scheduler_suspend(void); -void mali_pp_scheduler_resume(void); - -/** - * @brief Abort all running and queued PP jobs from session. - * - * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the - * queue and jobs currently running on a core will be aborted. - * - * @param session Session that is aborting. - */ -void mali_pp_scheduler_abort_session(struct mali_session_data *session); - -/** - * @brief Reset all groups - * - * This function resets all groups known by the PP scheuduler. This must be - * called after the Mali HW has been powered on in order to reset the HW. - * - * This function is intended for power on reset of all cores. - * No locking is done, which can only be safe if the scheduler is paused and - * all cores idle. That is always the case on init and power on. - */ -void mali_pp_scheduler_reset_all_groups(void); - -/** - * @brief Zap TLB on all groups with \a session active - * - * The scheculer will zap the session on all groups it owns. - */ -void mali_pp_scheduler_zap_all_active(struct mali_session_data *session); - -/** - * @brief Get the virtual PP core - * - * The returned PP core may only be used to prepare DMA command buffers for the - * PP core. Other actions must go through the PP scheduler, or the virtual - * group. - * - * @return Pointer to the virtual PP core, NULL if this doesn't exist - */ -struct mali_pp_core *mali_pp_scheduler_get_virtual_pp(void); - -u32 mali_pp_scheduler_dump_state(char *buf, u32 size); - -void mali_pp_scheduler_enable_group(struct mali_group *group); -void mali_pp_scheduler_disable_group(struct mali_group *group); - -/** - * @brief Used by the Timeline system to queue a PP job. - * - * @note @ref mali_scheduler_schedule_from_mask() should be called if this function returns non-zero. - * - * @param job The PP job that is being activated. - * - * @return A scheduling bitmask that can be used to decide if scheduling is necessary after this - * call. - */ -mali_scheduler_mask mali_pp_scheduler_activate_job(struct mali_pp_job *job); - -/** - * @brief Schedule queued jobs on idle cores. - */ -void mali_pp_scheduler_schedule(void); - -int mali_pp_scheduler_set_perf_level(u32 cores, mali_bool override); - -void mali_pp_scheduler_core_scaling_enable(void); -void mali_pp_scheduler_core_scaling_disable(void); -mali_bool mali_pp_scheduler_core_scaling_is_enabled(void); - -u32 mali_pp_scheduler_get_num_cores_total(void); -u32 mali_pp_scheduler_get_num_cores_enabled(void); - -/** - * @brief Returns the number of Pixel Processors in the system irrespective of the context - * - * @return number of physical Pixel Processor cores in the system - */ -u32 mali_pp_scheduler_get_num_cores_total(void); - -#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h b/drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h deleted file mode 100755 index b422bc3c21fa..000000000000 --- a/drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2010, 2013-2014 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file mali_kernel_license.h - * Defines for the macro MODULE_LICENSE. - */ - -#ifndef __MALI_KERNEL_LICENSE_H__ -#define __MALI_KERNEL_LICENSE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define MALI_KERNEL_LINUX_LICENSE "Proprietary" -#define MALI_LICENSE_IS_GPL 0 - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_KERNEL_LICENSE_H__ */ diff --git a/drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c b/drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c deleted file mode 100755 index d7d2d6fb9be7..000000000000 --- a/drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2009-2010, 2012 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file mali_platform.c - * Platform specific Mali driver functions for the TCC8900 platform - */ -#include -#include -#include -#ifdef CONFIG_PM_RUNTIME -#include -#endif -#include -#include "mali_kernel_common.h" - -static void mali_platform_device_release(struct device *device); - -#define MALI_GP_IRQ 25 -#define MALI_PP_IRQ 24 -#define MALI_MMU_IRQ 26 - -static struct resource mali_gpu_resources[] = -{ - MALI_GPU_RESOURCES_MALI200(0xF0000000, MALI_GP_IRQ, MALI_PP_IRQ, MALI_MMU_IRQ) -}; - -static struct platform_device mali_gpu_device = -{ - .name = MALI_GPU_NAME_UTGARD, - .id = 0, - .dev.release = mali_platform_device_release, -}; - -static struct mali_gpu_device_data mali_gpu_data = -{ -#if 0 - /* Dedicated memory setup (not sure if this is actually reserved on the platforms any more) */ - .dedicated_mem_start = 0x48A00000, /* Physical start address */ - .dedicated_mem_size = 0x07800000, /* 120MB */ -#endif - .shared_mem_size = 96 * 1024 * 1024, /* 96MB */ - .fb_start = 0x48200000, - .fb_size = 0x00800000, -}; - -int mali_platform_device_register(void) -{ - int err; - - MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n")); - - /* Connect resources to the device */ - err = platform_device_add_resources(&mali_gpu_device, mali_gpu_resources, sizeof(mali_gpu_resources) / sizeof(mali_gpu_resources[0])); - if (0 == err) - { - err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data)); - if (0 == err) - { - /* Register the platform device */ - err = platform_device_register(&mali_gpu_device); - if (0 == err) - { -#ifdef CONFIG_PM_RUNTIME -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) - pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000); - pm_runtime_use_autosuspend(&(mali_gpu_device.dev)); -#endif - pm_runtime_enable(&(mali_gpu_device.dev)); -#endif - - return 0; - } - } - - platform_device_unregister(&mali_gpu_device); - } - - return err; -} - -void mali_platform_device_unregister(void) -{ - MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n")); - - platform_device_unregister(&mali_gpu_device); -} - -static void mali_platform_device_release(struct device *device) -{ - MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n")); -} diff --git a/drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h b/drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h deleted file mode 100755 index e45e31d92bf0..000000000000 --- a/drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2008-2011 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -#define ARCH_UMP_BACKEND_DEFAULT 1 -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0//0xC8000000 -#define ARCH_UMP_MEMORY_SIZE_DEFAULT 512UL * 1024UL * 1024UL -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h b/drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h deleted file mode 100755 index 93ac8082bf13..000000000000 --- a/drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2010-2011, 2013 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - */ - -/** - * @file ump_kernel_license.h - * Defines for the macro MODULE_LICENSE. - */ - -#ifndef __UMP_KERNEL_LICENSE_H__ -#define __UMP_KERNEL_LICENSE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define UMP_KERNEL_LINUX_LICENSE "Proprietary" -#define UMP_LICENSE_IS_GPL 0 - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_KERNEL_LICENSE_H__ */ From cc941b22d4f366491dd7311451b10667a885d57c Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 31 Jan 2018 19:59:13 +0800 Subject: [PATCH 163/427] MALI Utgard: rk.c: change licence announcement to use GPLv2 Change-Id: I1230425dd33b48b7dc3d8b49d8912713ebb97ca5 Signed-off-by: Zhen Chen --- drivers/gpu/arm/mali400/mali/platform/rk/rk.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index 3c0d1cc7e4d6..46a8ba8901bb 100644 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -1,11 +1,10 @@ /* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2009-2010, 2012 ARM Limited - * ALL RIGHTS RESERVED - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. + * (C) COPYRIGHT RockChip Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. */ /** From f9eefeeaa7d2e0cd8926f7a32c037d8d8a3b412e Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 31 Jan 2018 20:51:17 +0800 Subject: [PATCH 164/427] rk: add SPDX license identifier to files with no license Change-Id: I754250669891307b0deab2bdab1bd01512713f79 Signed-off-by: Tao Huang --- arch/arm/boot/dts/act8846.dtsi | 1 + arch/arm/boot/dts/act8931.dtsi | 1 + arch/arm/boot/dts/rk3036-fpga.dts | 1 + arch/arm/boot/dts/rk3036-new.dts | 1 + arch/arm/boot/dts/rk3036-pinctrl.dtsi | 1 + arch/arm/boot/dts/rk3036-rk88.dts | 1 + arch/arm/boot/dts/rk3036-sdk.dts | 1 + arch/arm/boot/dts/rk3126-86v.dts | 1 + arch/arm/boot/dts/rk3126-cif-sensor.dtsi | 1 + arch/arm/boot/dts/rk3126-fpga.dts | 1 + arch/arm/boot/dts/rk3126-m708-cif-sensor.dtsi | 1 + arch/arm/boot/dts/rk3126-sdk.dts | 1 + arch/arm/boot/dts/rk3128-86v.dts | 1 + arch/arm/boot/dts/rk3128-box-ns.dts | 1 + arch/arm/boot/dts/rk3128-box-rk88.dts | 1 + arch/arm/boot/dts/rk3128-box.dts | 1 + arch/arm/boot/dts/rk3128-cif-sensor.dtsi | 1 + arch/arm/boot/dts/rk3128-sdk.dts | 1 + arch/arm/boot/dts/rk312x-pinctrl.dtsi | 1 + arch/arm/boot/dts/rk312x-sdk.dtsi | 1 + arch/arm/boot/dts/rk3188-lr097.dts | 1 + arch/arm/boot/dts/rk3188-pinctrl.dtsi | 1 + arch/arm/boot/dts/rk3188-tb.dts | 1 + arch/arm/boot/dts/rk3288-box.dts | 1 + arch/arm/boot/dts/rk3288-chrome.dts | 1 + arch/arm/boot/dts/rk3288-cif-sensor.dtsi | 1 + arch/arm/boot/dts/rk3288-fpga.dts | 1 + arch/arm/boot/dts/rk3288-p977.dts | 1 + arch/arm/boot/dts/rk3288-p977_8846.dts | 1 + arch/arm/boot/dts/rk3288-pinctrl.dtsi | 1 + arch/arm/boot/dts/rk3288-tb.dts | 1 + arch/arm/boot/dts/rk3288-tb_8846.dts | 1 + arch/arm/boot/dts/rk3288-tb_sec.dts | 1 + arch/arm/boot/dts/rk3288-tesco.dts | 1 + arch/arm/boot/dts/rk616.dtsi | 1 + arch/arm/boot/dts/rk808.dtsi | 1 + arch/arm/boot/dts/rk818.dtsi | 1 + arch/arm/boot/dts/vtl_ts_p977.dtsi | 1 + arch/arm/boot/dts/vtl_ts_sdk8846.dtsi | 1 + arch/arm/mach-rockchip/embedded/Makefile | 1 + arch/arm/mach-rockchip/embedded/rk3288_resume.lds.S | 1 + arch/arm64/boot/dts/rockchip/rk3368-cif-sensor.dtsi | 1 + arch/arm64/include/asm/system_info.h | 1 + block/partitions/rk.c | 1 + block/partitions/rk.h | 1 + drivers/adc/Kconfig | 1 + drivers/adc/Makefile | 1 + drivers/adc/plat/Kconfig | 1 + drivers/adc/plat/Makefile | 1 + drivers/bluetooth/vflash.c | 1 + drivers/cir/Kconfig | 1 + drivers/cir/Makefile | 1 + drivers/cmmb/Kconfig | 1 + drivers/cmmb/Makefile | 1 + drivers/cmmb/cmmb_class.c | 1 + drivers/cmmb/cmmb_class.h | 1 + drivers/cmmb/cmmb_memory.c | 1 + drivers/cmmb/cmmb_memory.h | 1 + drivers/cmmb/siano/Kconfig | 1 + drivers/cmmb/siano/compat.h | 1 + drivers/gpu/arm/mali400/Kbuild | 1 + drivers/gpu/arm/mali400/mali/Kconfig | 1 + drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h | 1 + drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h | 1 + drivers/gpu/arm/mali400/ump/Kconfig | 1 + drivers/gpu/arm/midgard/platform/rk/custom_log.h | 1 + drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h | 1 + drivers/gpu/drm/bridge/analogix/Kconfig | 1 + drivers/gpu/drm/bridge/analogix/Makefile | 1 + drivers/gpu/drm/bridge/synopsys/Kconfig | 1 + drivers/gpu/drm/bridge/synopsys/Makefile | 1 + drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 1 + drivers/gpu/rogue/Kconfig | 1 + drivers/gpu/rogue/Makefile | 1 + .../rogue/build/linux/config/compilers/aarch64-linux-android.mk | 1 + drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk | 1 + .../rogue/build/linux/config/compilers/arm-linux-androideabi.mk | 1 + drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk | 1 + .../gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk | 1 + drivers/gpu/rogue/config_kernel.h | 1 + drivers/gpu/rogue/config_kernel.mk | 1 + drivers/gpu/rogue/system/rk3368/rk_init.c | 1 + drivers/gpu/rogue/system/rk3368/rk_init.h | 1 + drivers/gpu/rogue_m/Kconfig | 1 + drivers/gpu/rogue_m/Makefile | 1 + .../build/linux/config/compilers/aarch64-linux-android.mk | 1 + drivers/gpu/rogue_m/build/linux/config/compilers/arm-eabi.mk | 1 + .../build/linux/config/compilers/arm-linux-androideabi.mk | 1 + .../gpu/rogue_m/build/linux/config/compilers/i386-linux-gnu.mk | 1 + .../gpu/rogue_m/build/linux/config/compilers/x86_64-linux-gnu.mk | 1 + drivers/gpu/rogue_m/config_kernel.h | 1 + drivers/gpu/rogue_m/config_kernel.mk | 1 + drivers/gpu/rogue_m/system/rk3368/rk_init.c | 1 + drivers/gpu/rogue_m/system/rk3368/rk_init.h | 1 + drivers/headset_observe/Kconfig | 1 + drivers/headset_observe/Makefile | 1 + drivers/headset_observe/rk_headset.h | 1 + drivers/input/gsensor/Kconfig | 1 + drivers/input/gsensor/Makefile | 1 + drivers/input/gsensor/lis3dh.c | 1 + drivers/input/gsensor/lis3dh.h | 1 + drivers/input/gyroscope/Kconfig | 1 + drivers/input/gyroscope/Makefile | 1 + drivers/input/jogball/Kconfig | 1 + drivers/input/jogball/Makefile | 1 + drivers/input/keyboard/synaptics_so340010.c | 1 + drivers/input/lightsensor/Kconfig | 1 + drivers/input/lightsensor/Makefile | 1 + drivers/input/lightsensor/cm3202.c | 1 + drivers/input/lightsensor/cm3217.c | 1 + drivers/input/lightsensor/rk29_lightsensor.c | 1 + drivers/input/lightsensor/us5151.c | 1 + drivers/input/magnetometer/Kconfig | 1 + drivers/input/magnetometer/Makefile | 1 + drivers/input/magnetometer/ak8973.h | 1 + drivers/input/magnetometer/ak8975.h | 1 + drivers/input/magnetometer/magnet.h | 1 + drivers/input/misc/rk_board_id.c | 1 + drivers/input/remotectl/Kconfig | 1 + drivers/input/remotectl/Makefile | 1 + drivers/input/remotectl/rockchip_pwm_remotectl.c | 1 + drivers/input/remotectl/rockchip_pwm_remotectl.h | 1 + drivers/input/sensors/Kconfig | 1 + drivers/input/sensors/Makefile | 1 + drivers/input/sensors/accel/Kconfig | 1 + drivers/input/sensors/accel/Makefile | 1 + drivers/input/sensors/angle/Kconfig | 1 + drivers/input/sensors/angle/Makefile | 1 + drivers/input/sensors/compass/Kconfig | 1 + drivers/input/sensors/compass/Makefile | 1 + drivers/input/sensors/gyro/Kconfig | 1 + drivers/input/sensors/gyro/Makefile | 1 + drivers/input/sensors/hall/Kconfig | 1 + drivers/input/sensors/hall/Makefile | 1 + drivers/input/sensors/lsensor/Kconfig | 1 + drivers/input/sensors/lsensor/Makefile | 1 + drivers/input/sensors/lsensor/ls_us5152.c | 1 + drivers/input/sensors/pressure/Kconfig | 1 + drivers/input/sensors/pressure/Makefile | 1 + drivers/input/sensors/psensor/Kconfig | 1 + drivers/input/sensors/psensor/Makefile | 1 + drivers/input/sensors/temperature/Kconfig | 1 + drivers/input/sensors/temperature/Makefile | 1 + drivers/input/touchscreen/IT7260_ts.h | 1 + drivers/input/touchscreen/atmel_mxt224.c | 1 + drivers/input/touchscreen/byd693x_ts.c | 1 + drivers/input/touchscreen/byd693x_ts.h | 1 + drivers/input/touchscreen/calib_iface_ts.c | 1 + drivers/input/touchscreen/ct360_calib.h | 1 + drivers/input/touchscreen/ct360_ch.h | 1 + drivers/input/touchscreen/ct36x/Kconfig | 1 + drivers/input/touchscreen/ct36x/Makefile | 1 + drivers/input/touchscreen/ct36x/core.c | 1 + drivers/input/touchscreen/ct36x/ct360.c | 1 + drivers/input/touchscreen/ct36x/ct363.c | 1 + drivers/input/touchscreen/ct36x/ct36x_priv.h | 1 + drivers/input/touchscreen/ct36x/ct36x_ts.c | 1 + drivers/input/touchscreen/ct36x_ts/Kconfig | 1 + drivers/input/touchscreen/ct36x_ts/Makefile | 1 + drivers/input/touchscreen/ct36x_ts/allwinner.c | 1 + drivers/input/touchscreen/ct36x_ts/chip.h | 1 + drivers/input/touchscreen/ct36x_ts/ct360.c | 1 + drivers/input/touchscreen/ct36x_ts/ct360.h | 1 + drivers/input/touchscreen/ct36x_ts/ct365.c | 1 + drivers/input/touchscreen/ct36x_ts/ct365.h | 1 + drivers/input/touchscreen/ct36x_ts/generic.c | 1 + drivers/input/touchscreen/ct36x_ts/generic.h | 1 + drivers/input/touchscreen/ct36x_ts/platform.h | 1 + drivers/input/touchscreen/ct36x_ts/rockchip.c | 1 + drivers/input/touchscreen/ct36x_ts/rockchip.h | 1 + drivers/input/touchscreen/ct36x_ts/tscore.h | 1 + drivers/input/touchscreen/ctp_it7250.c | 1 + drivers/input/touchscreen/ft5506_wgj.h | 1 + drivers/input/touchscreen/ft5x0x.c | 1 + drivers/input/touchscreen/ft5x0x_i2c_ts.h | 1 + drivers/input/touchscreen/goodix_touch.c | 1 + drivers/input/touchscreen/goodix_touch_82x.c | 1 + drivers/input/touchscreen/goodix_touch_82x_760.c | 1 + drivers/input/touchscreen/gslx680_d708/Makefile | 1 + drivers/input/touchscreen/gslx680_pad.h | 1 + drivers/input/touchscreen/gt9xx/Makefile | 1 + drivers/input/touchscreen/hannstar_p1003.c | 1 + drivers/input/touchscreen/ili2102_ts.c | 1 + drivers/input/touchscreen/it7260_ts.c | 1 + drivers/input/touchscreen/nas_ts.c | 1 + drivers/input/touchscreen/pixcir_i2c_ts.h | 1 + drivers/input/touchscreen/rk3028_gslX680_86v.h | 1 + drivers/input/touchscreen/rk_tp.c | 1 + drivers/input/touchscreen/rmi4/Kconfig | 1 + drivers/input/touchscreen/rmi4/Makefile | 1 + drivers/input/touchscreen/rmi4/rmi_reflash.h | 1 + drivers/input/touchscreen/rockchip_gslX680.h | 1 + drivers/input/touchscreen/rockchip_gslX680_rk3128.h | 1 + drivers/input/touchscreen/rockchip_gslX680_rk3168.h | 1 + drivers/input/touchscreen/sintek_3FA16.c | 1 + drivers/input/touchscreen/tp_suspend.h | 1 + drivers/input/touchscreen/ts_lib/Makefile | 1 + drivers/input/touchscreen/vtl_ts/Makefile | 1 + drivers/input/touchscreen/vtl_ts/apk.c | 1 + drivers/input/touchscreen/vtl_ts/apk.h | 1 + drivers/input/touchscreen/vtl_ts/chip.c | 1 + drivers/input/touchscreen/vtl_ts/chip.h | 1 + drivers/input/touchscreen/vtl_ts/tp_fw.h | 1 + drivers/input/touchscreen/vtl_ts/vtl_ts.h | 1 + drivers/input/touchscreen/zet62xx/Makefile | 1 + drivers/input/touchscreen/zet62xx/zet6221_fw.h | 1 + drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h | 1 + drivers/input/touchscreen/zet62xx/zet6223_fw.h | 1 + drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h | 1 + drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h | 1 + drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h | 1 + drivers/input/touchscreen/zet62xx/zet6231_fw.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h | 1 + drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h | 1 + drivers/input/ts/Kconfig | 1 + drivers/input/ts/Makefile | 1 + drivers/input/ts/chips/Kconfig | 1 + drivers/input/ts/chips/Makefile | 1 + drivers/input/ts/chips/ct360_firmware.h | 1 + drivers/input/ts/ts-serial.c | 1 + drivers/input/ts/ts-spi.c | 1 + drivers/media/cec/Kconfig | 1 + drivers/media/cec/Makefile | 1 + drivers/media/i2c/soc_camera/rockchip/Kconfig | 1 + drivers/media/i2c/soc_camera/rockchip/Makefile | 1 + drivers/media/platform/rk-isp10/Kconfig | 1 + drivers/media/platform/rk-isp10/Makefile | 1 + drivers/media/platform/rockchip-vpu/Makefile | 1 + drivers/media/platform/rockchip/isp1/Makefile | 1 + drivers/media/platform/rockchip/rga/Makefile | 1 + drivers/media/video/Kconfig | 1 + drivers/media/video/Makefile | 1 + drivers/media/video/gc0308_user_series.c | 1 + drivers/media/video/gt2005_user_series.c | 1 + drivers/media/video/hm5065.h | 1 + drivers/media/video/mv9335/Kconfig | 1 + drivers/media/video/mv9335/Makefile | 1 + drivers/media/video/mv9335/mv9335.c | 1 + drivers/media/video/nt99252_3way.c | 1 + drivers/media/video/nt99340_2way.c | 1 + drivers/media/video/ov2640_rk.c | 1 + drivers/media/video/ov5640.h | 1 + drivers/media/video/rk2928_camera.c | 1 + drivers/media/video/rk29_camera.c | 1 + drivers/media/video/rk29xx/Kconfig | 1 + drivers/media/video/rk29xx/Makefile | 1 + drivers/media/video/rk_camsys/Kconfig | 1 + drivers/media/video/rk_camsys/Makefile | 1 + drivers/media/video/rk_camsys/camsys_cif.c | 1 + drivers/media/video/rk_camsys/camsys_cif.h | 1 + drivers/media/video/rk_camsys/camsys_drv.c | 1 + drivers/media/video/rk_camsys/camsys_gpio.h | 1 + drivers/media/video/rk_camsys/camsys_internal.h | 1 + drivers/media/video/rk_camsys/camsys_marvin.c | 1 + drivers/media/video/rk_camsys/camsys_marvin.h | 1 + drivers/media/video/rk_camsys/camsys_mipicsi_phy.c | 1 + drivers/media/video/rk_camsys/camsys_mipicsi_phy.h | 1 + drivers/media/video/rk_camsys/camsys_soc_priv.c | 1 + drivers/media/video/rk_camsys/camsys_soc_priv.h | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3288.c | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3288.h | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3366.c | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3366.h | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3368.c | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3368.h | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3399.c | 1 + drivers/media/video/rk_camsys/camsys_soc_rk3399.h | 1 + drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig | 1 + drivers/media/video/rk_camsys/ext_flashled_drv/Makefile | 1 + .../media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c | 1 + .../media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h | 1 + drivers/media/video/s5k5ca.h | 1 + drivers/media/video/s5k6aa.h | 1 + drivers/mfd/rk610-core.c | 1 + drivers/mfd/rk616-core.c | 1 + drivers/mfd/rk616-vif.c | 1 + drivers/mfd/tlv320aic3262-core.c | 1 + drivers/mfd/tlv320aic3262-irq.c | 1 + drivers/misc/3g_module/Kconfig | 1 + drivers/misc/3g_module/Makefile | 1 + drivers/misc/5v_en.c | 1 + drivers/misc/ac_usb_switch.c | 1 + drivers/misc/bp/Kconfig | 1 + drivers/misc/bp/Makefile | 1 + drivers/misc/bp/bp-auto.c | 1 + drivers/misc/bp/chips/Kconfig | 1 + drivers/misc/bp/chips/Makefile | 1 + drivers/misc/fm580x.h | 1 + drivers/misc/gps/Kconfig | 1 + drivers/misc/gps/Makefile | 1 + drivers/misc/gps/rk29_gps.c | 1 + drivers/misc/gps/rk29_gps.h | 1 + drivers/misc/gps/rk_gps/Kconfig | 1 + drivers/misc/gps/rk_gps/Makefile | 1 + drivers/misc/gps/rk_gps/rk_gps.h | 1 + drivers/misc/gps/rk_gps/rk_gps_null.c | 1 + drivers/misc/inv_mpu/Kconfig | 1 + drivers/misc/inv_mpu/Makefile | 1 + drivers/misc/inv_mpu/accel/Kconfig | 1 + drivers/misc/inv_mpu/accel/Makefile | 1 + drivers/misc/inv_mpu/compass/Kconfig | 1 + drivers/misc/inv_mpu/compass/Makefile | 1 + drivers/misc/inv_mpu/pressure/Kconfig | 1 + drivers/misc/inv_mpu/pressure/Makefile | 1 + drivers/misc/modem_sound.c | 1 + drivers/misc/modem_sound.h | 1 + drivers/misc/rk2928_callpad_misc/Kconfig | 1 + drivers/misc/rk2928_callpad_misc/Makefile | 1 + drivers/misc/rk2928_callpad_misc/audio_switch.h | 1 + drivers/misc/rk29_modem/Kconfig | 1 + drivers/misc/rk29_modem/Makefile | 1 + drivers/misc/rk29_modem/modem_longcheer_u6300v.c | 1 + drivers/misc/rk29_modem/modem_rockchip_demo.c | 1 + drivers/misc/rk29_modem/modem_thinkwill_mw100g.c | 1 + drivers/misc/rk29_modem/rk29_modem.c | 1 + drivers/misc/rk29_modem/rk29_modem.h | 1 + drivers/misc/sc8800.c | 1 + drivers/misc/scaler/Kconfig | 1 + drivers/misc/scaler/Makefile | 1 + drivers/misc/scaler/chips/Kconfig | 1 + drivers/misc/scaler/chips/Makefile | 1 + drivers/misc/scaler/chips/test.c | 1 + drivers/misc/scaler/chips/tv5735.c | 1 + drivers/misc/scaler/chips/tv_setting.h | 1 + drivers/misc/scaler/scaler-core.c | 1 + drivers/misc/scaler/scaler-edid.c | 1 + drivers/misc/scaler/scaler-sysfs.c | 1 + drivers/misc/tcc_bt_dev.c | 1 + drivers/mtd/rknand/Kconfig | 1 + drivers/mtd/rknand/Makefile | 1 + drivers/mtd/rknand/api_flash.h | 1 + drivers/mtd/rknand/rknand_base.h | 1 + drivers/mtd/rknand/rknand_base_ko.c | 1 + drivers/net/ethernet/rockchip/Kconfig | 1 + drivers/net/ethernet/rockchip/Makefile | 1 + drivers/net/ethernet/rockchip/eth_mac.c | 1 + drivers/net/ethernet/rockchip/gmac/Kconfig | 1 + drivers/net/ethernet/rockchip/gmac/Makefile | 1 + drivers/net/ethernet/rockchip/vmac/Kconfig | 1 + drivers/net/ethernet/rockchip/vmac/Makefile | 1 + drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c | 1 + drivers/net/irda/bu92725guw.c | 1 + drivers/net/irda/bu92725guw.h | 1 + drivers/net/irda/ir_serial.h | 1 + drivers/net/irda/rk29_ir.h | 1 + drivers/net/wireless/rockchip_wlan/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/Makefile | 1 + drivers/net/wireless/rockchip_wlan/esp8089/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/esp8089/Makefile | 1 + drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h | 1 + .../net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c | 1 + .../net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c | 1 + .../net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h | 1 + drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8188eu/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8188eu/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.h | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.c | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.h | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.c | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.h | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.c | 1 + .../rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtcoutsrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/hal/efuse/efuse_mask.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/hal_btcoex_wifionly.c | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.c | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.h | 1 + .../rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.c | 1 + .../rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.h | 1 + .../rtl8188eu/hal/phydm/rtl8188e/version_rtl8188e.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8188eu/hal/phydm/txbf/phydm_hal_txbf_api.c | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8723BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8723DPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/include/custom_gpio.h | 1 + .../rockchip_wlan/rtl8188eu/include/hal_btcoex_wifionly.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8188eu/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8188fu/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8188fu/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.h | 1 + .../rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.c | 1 + .../rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtcOutSrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/hal/efuse/efuse_mask.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/hal8188freg.h | 1 + .../rtl8188fu/hal/phydm/rtl8188f/version_rtl8188f.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8188fu/hal/rtl8188f/Hal8188FPwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8188fu/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8189es/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8189es/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.h | 1 + .../rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.c | 1 + .../rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtcOutSrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/hal/efuse/efuse_mask.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.h | 1 + .../rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.c | 1 + .../rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189es/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8189es/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8189es/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8189fs/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8189fs/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.h | 1 + .../rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.c | 1 + .../rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtcOutSrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/hal/efuse/efuse_mask.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/hal8188freg.h | 1 + .../rtl8189fs/hal/phydm/rtl8188f/version_rtl8188f.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8189fs/hal/rtl8188f/Hal8188FPwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8189fs/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile | 1 + .../net/wireless/rockchip_wlan/rtl8192cu/include/rtw_version.h | 1 + .../wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8192du/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8192du/Makefile | 1 + .../net/wireless/rockchip_wlan/rtl8192du/include/rtw_version.h | 1 + .../net/wireless/rockchip_wlan/rtl8192du/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_regd.c | 1 + .../wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c | 1 + .../rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c | 1 + .../rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h | 1 + .../rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c | 1 + .../rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h | 1 + .../rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h | 1 + .../rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h | 1 + .../rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c | 1 + .../net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h | 1 + .../wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c | 1 + .../wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h | 1 + .../rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h | 1 + .../rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c | 1 + .../rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h | 1 + .../rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h | 1 + .../rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h | 1 + .../rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h | 1 + .../wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h | 1 + .../wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h | 1 + .../rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c | 1 + .../rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.h | 1 + .../rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.c | 1 + .../rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtcOutSrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/hal/efuse/efuse_mask.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/hal8723breg.h | 1 + .../rtl8723bs/hal/phydm/rtl8723b/version_rtl8723b.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8723bs/hal/rtl8723b/Hal8723BPwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8723bs/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.h | 1 + .../rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.c | 1 + .../rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtcOutSrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/hal8723breg.h | 1 + .../rtl8723bu/hal/phydm/rtl8723b/version_rtl8723b.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8723cs/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723cs/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.h | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.c | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.h | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.c | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.h | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.c | 1 + .../rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtcoutsrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/hal/efuse/efuse_mask.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/hal_btcoex_wifionly.c | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.c | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.h | 1 + .../rtl8723cs/hal/phydm/rtl8703b/version_rtl8703b.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8723cs/hal/phydm/txbf/phydm_hal_txbf_api.c | 1 + .../rockchip_wlan/rtl8723cs/hal/rtl8703b/Hal8703BPwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8723BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8723DPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/include/custom_gpio.h | 1 + .../rockchip_wlan/rtl8723cs/include/hal_btcoex_wifionly.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8723cs/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/rtl8723ds/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8723ds/Makefile | 1 + .../wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.h | 1 + .../wireless/rockchip_wlan/rtl8723ds/hal/phydm/ap_makefile.mk | 1 + .../rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.c | 1 + .../rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/phydm.mk | 1 + .../rtl8723ds/hal/phydm/rtl8723d/version_rtl8723d.h | 1 + .../net/wireless/rockchip_wlan/rtl8723ds/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c | 1 + .../rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h | 1 + .../rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h | 1 + .../rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c | 1 + .../wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c | 1 + .../wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8822be/Kconfig | 1 + drivers/net/wireless/rockchip_wlan/rtl8822be/Makefile | 1 + drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi.c | 1 + .../net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi_sms4.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.h | 1 + .../rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.c | 1 + .../rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtcoutsrc.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/efuse/efuse_mask.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_cfg.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_pwr_seq.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_pcie.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_sdio.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_usb.h | 1 + .../hal/halmac/halmac_88xx/halmac_8197f/halmac_func_8197f.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_8821c_pwr_seq.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_pcie.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_sdio.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_usb.h | 1 + .../hal/halmac/halmac_88xx/halmac_8821c/halmac_func_8821c.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c | 1 + .../hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_88xx_cfg.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.c | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.c | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.c | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.c | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.h | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.c | 1 + .../rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.c | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit2.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8821c.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8822b.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_info.h | 1 + .../rtl8822be/hal/halmac/halmac_fw_offload_c2h_ap.h | 1 + .../rtl8822be/hal/halmac/halmac_fw_offload_c2h_nic.h | 1 + .../rtl8822be/hal/halmac/halmac_fw_offload_h2c_ap.h | 1 + .../rtl8822be/hal/halmac/halmac_fw_offload_h2c_nic.h | 1 + .../rtl8822be/hal/halmac/halmac_h2c_extra_info_ap.h | 1 + .../rtl8822be/hal/halmac/halmac_h2c_extra_info_nic.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_hw_cfg.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_nic.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_nic.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_pcie_reg.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_pwr_seq_cmd.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg2.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8821c.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8822b.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_chip.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_nic.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_chip.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_nic.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_sdio_reg.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_chip.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_nic.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_ap.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_chip.h | 1 + .../rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_nic.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_type.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_usb_reg.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/phydm/halhwimg.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.c | 1 + .../net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.h | 1 + .../rtl8822be/hal/phydm/rtl8822b/version_rtl8822b.h | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.c | 1 + .../wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.c | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.h | 1 + .../rockchip_wlan/rtl8822be/hal/phydm/txbf/phydm_hal_txbf_api.c | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8188FPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8192EPhyReg.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8192EPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8703BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8723BPwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8723DPwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/include/Hal8723PwrSeq.h | 1 + .../wireless/rockchip_wlan/rtl8822be/include/Hal8821APwrSeq.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/include/custom_gpio.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/include/rtw_version.h | 1 + drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wapi.h | 1 + .../net/wireless/rockchip_wlan/rtl8822be/include/rtw_wifi_regd.h | 1 + .../wireless/rockchip_wlan/rtl8822be/os_dep/linux/wifi_regd.c | 1 + drivers/net/wireless/rockchip_wlan/wifi_launcher/Makefile | 1 + drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h | 1 + drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c | 1 + drivers/net/wireless/rtl8723as/Kconfig | 1 + drivers/phy/rockchip/Kconfig | 1 + drivers/phy/rockchip/Makefile | 1 + drivers/power/reset/reboot-mode.h | 1 + drivers/power/rk29_charger_display.c | 1 + drivers/regulator/rockchip_io_vol_domain.c | 1 + drivers/rk_nand/Kconfig | 1 + drivers/rk_nand/Makefile | 1 + drivers/rtc/auto-wake.c | 1 + drivers/smc/Kconfig | 1 + drivers/smc/Makefile | 1 + drivers/smc/rk29_smc.c | 1 + drivers/staging/android/ion/rockchip/Makefile | 1 + drivers/staging/android/trace/ion.h | 1 + drivers/staging/iio/imu/inv_mpu/Kconfig | 1 + drivers/staging/iio/imu/inv_mpu/Makefile | 1 + drivers/staging/iio/imu/inv_mpu/inv_counters.c | 1 + drivers/staging/iio/imu/inv_mpu/inv_counters.h | 1 + drivers/staging/imgtec/Kconfig | 1 + drivers/staging/imgtec/Makefile | 1 + drivers/staging/imgtec/apollo/Kconfig | 1 + drivers/staging/imgtec/apollo/Makefile | 1 + drivers/staging/imgtec/config_kernel.h | 1 + drivers/staging/imgtec/rogue/Kconfig | 1 + drivers/staging/imgtec/rogue/Makefile | 1 + drivers/staging/rk29/ipp/Kconfig | 1 + drivers/staging/rk29/ipp/Makefile | 1 + drivers/switch/Kconfig | 1 + drivers/switch/Makefile | 1 + drivers/testcode/Kconfig | 1 + drivers/testcode/Makefile | 1 + drivers/testcode/gpio_wave.c | 1 + drivers/testcode/gpio_wave.h | 1 + drivers/usb/dwc_otg_310/Kconfig | 1 + drivers/usb/dwc_otg_310/Makefile | 1 + drivers/usb/dwc_otg_310/Makefile-original | 1 + drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c | 1 + drivers/usb/dwc_otg_310/common_port/dwc_mem.c | 1 + drivers/usb/dwc_otg_310/common_port/dwc_notifier.c | 1 + drivers/usb/dwc_otg_310/common_port/dwc_notifier.h | 1 + drivers/usb/dwc_otg_310/dwc_otg_os_dep.h | 1 + drivers/usb/dwc_otg_310/dwc_otg_rk_common_if.h | 1 + drivers/usb/dwc_otg_310/gadget_supplement.c | 1 + drivers/usb/dwc_otg_310/usbdev_bc.h | 1 + drivers/usb/dwc_otg_310/usbdev_grf_regs.h | 1 + drivers/usb/dwc_otg_310/usbdev_rk.h | 1 + drivers/usb/dwc_otg_310/usbdev_rk30.c | 1 + drivers/usb/dwc_otg_310/usbdev_rk3036.c | 1 + drivers/usb/dwc_otg_310/usbdev_rk3126.c | 1 + drivers/usb/dwc_otg_310/usbdev_rk3190_grf_regs.h | 1 + drivers/usb/dwc_otg_310/usbdev_rk32.c | 1 + drivers/usb/dwc_otg_310/usbdev_rk3368.c | 1 + drivers/usb/dwc_otg_310/usbdev_rkuoc.h | 1 + drivers/video/backlight/aw9364_bl.h | 1 + drivers/video/rockchip/Kconfig | 1 + drivers/video/rockchip/Makefile | 1 + drivers/video/rockchip/display-sys.c | 1 + drivers/video/rockchip/dp/Kconfig | 1 + drivers/video/rockchip/dp/Makefile | 1 + drivers/video/rockchip/dp/rockchip_dp.c | 1 + drivers/video/rockchip/dp/rockchip_dp.h | 1 + drivers/video/rockchip/dp/rockchip_dp_core.h | 1 + drivers/video/rockchip/hdmi/Kconfig | 1 + drivers/video/rockchip/hdmi/Makefile | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-cec.h | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-core.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmi.h | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/Makefile | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.h | 1 + .../video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_cec.c | 1 + .../video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.c | 1 + .../video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.h | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.h | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/Makefile | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h | 1 + .../video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c | 1 + .../video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hdcp.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c | 1 + drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.h | 1 + drivers/video/rockchip/iep/Kconfig | 1 + drivers/video/rockchip/iep/Makefile | 1 + drivers/video/rockchip/iep/hw_iep_config_addr.h | 1 + drivers/video/rockchip/iep/hw_iep_reg.h | 1 + drivers/video/rockchip/iep/iep.h | 1 + drivers/video/rockchip/iep/iep_drv.h | 1 + drivers/video/rockchip/iep/iep_mmu.h | 1 + drivers/video/rockchip/lcdc/Kconfig | 1 + drivers/video/rockchip/lcdc/Makefile | 1 + drivers/video/rockchip/lcdc/rk2928_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk3036_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk30_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk312x_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk3188_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk322x_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk3288_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk3368_lcdc.h | 1 + drivers/video/rockchip/lcdc/rk_vop_lite.h | 1 + drivers/video/rockchip/rga/Kconfig | 1 + drivers/video/rockchip/rga/Makefile | 1 + drivers/video/rockchip/rga/RGA_API.c | 1 + drivers/video/rockchip/rga/RGA_API.h | 1 + drivers/video/rockchip/rga/rga.h | 1 + drivers/video/rockchip/rga/rga_mmu_info.c | 1 + drivers/video/rockchip/rga/rga_mmu_info.h | 1 + drivers/video/rockchip/rga/rga_reg_info.c | 1 + drivers/video/rockchip/rga/rga_reg_info.h | 1 + drivers/video/rockchip/rga/rga_rop.h | 1 + drivers/video/rockchip/rga/rga_type.h | 1 + drivers/video/rockchip/rga2/Kconfig | 1 + drivers/video/rockchip/rga2/Makefile | 1 + drivers/video/rockchip/rga2/RGA2_API.c | 1 + drivers/video/rockchip/rga2/RGA2_API.h | 1 + drivers/video/rockchip/rga2/rga2.h | 1 + drivers/video/rockchip/rga2/rga2_mmu_info.c | 1 + drivers/video/rockchip/rga2/rga2_mmu_info.h | 1 + drivers/video/rockchip/rga2/rga2_reg_info.c | 1 + drivers/video/rockchip/rga2/rga2_reg_info.h | 1 + drivers/video/rockchip/rga2/rga2_rop.h | 1 + drivers/video/rockchip/rga2/rga2_type.h | 1 + drivers/video/rockchip/screen/Kconfig | 1 + drivers/video/rockchip/screen/Makefile | 1 + drivers/video/rockchip/screen/lcd_general.c | 1 + drivers/video/rockchip/screen/rk_screen.c | 1 + drivers/video/rockchip/transmitter/Kconfig | 1 + drivers/video/rockchip/transmitter/Makefile | 1 + drivers/video/rockchip/transmitter/anx6345.h | 1 + drivers/video/rockchip/transmitter/anx9805.h | 1 + drivers/video/rockchip/transmitter/dp501.c | 1 + drivers/video/rockchip/transmitter/dp_anx6345.c | 1 + drivers/video/rockchip/transmitter/dpcd_edid.h | 1 + drivers/video/rockchip/transmitter/mipi_dsi.h | 1 + drivers/video/rockchip/transmitter/rk2928_lvds.c | 1 + drivers/video/rockchip/transmitter/rk2928_lvds.h | 1 + drivers/video/rockchip/transmitter/rk3026_lvds.c | 1 + drivers/video/rockchip/transmitter/rk3026_lvds.h | 1 + drivers/video/rockchip/transmitter/rk31xx_lvds.h | 1 + drivers/video/rockchip/transmitter/rk32_dp.h | 1 + drivers/video/rockchip/transmitter/rk32_lvds.c | 1 + drivers/video/rockchip/transmitter/rk32_lvds.h | 1 + drivers/video/rockchip/transmitter/rk32_mipi_dsi.h | 1 + drivers/video/rockchip/transmitter/rk610_lcd.c | 1 + drivers/video/rockchip/transmitter/rk610_lcd.h | 1 + drivers/video/rockchip/transmitter/rk616_lvds.c | 1 + drivers/video/rockchip/transmitter/rk616_lvds.h | 1 + drivers/video/rockchip/transmitter/rk616_mipi_dsi.h | 1 + drivers/video/rockchip/transmitter/vga.c | 1 + drivers/video/rockchip/tve/Kconfig | 1 + drivers/video/rockchip/tve/Makefile | 1 + drivers/video/rockchip/tve/gm7122/Kconfig | 1 + drivers/video/rockchip/tve/gm7122/Makefile | 1 + drivers/video/rockchip/tve/gm7122/gm7122_tve.h | 1 + drivers/video/rockchip/tve/rk1000/Kconfig | 1 + drivers/video/rockchip/tve/rk1000/Makefile | 1 + drivers/video/rockchip/tve/rk1000/rk1000_tve.h | 1 + drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c | 1 + drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c | 1 + drivers/video/rockchip/tve/rk3036/Kconfig | 1 + drivers/video/rockchip/tve/rk3036/Makefile | 1 + drivers/video/rockchip/tve/rk3036/rk3036_tve.h | 1 + drivers/video/rockchip/tve/rk610/Kconfig | 1 + drivers/video/rockchip/tve/rk610/Makefile | 1 + drivers/video/rockchip/tve/rk610/rk610_tv.h | 1 + drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c | 1 + drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c | 1 + drivers/video/rockchip/vcodec/Kconfig | 1 + drivers/video/rockchip/vcodec/Makefile | 1 + drivers/video/rockchip/vpu/Kconfig | 1 + drivers/video/rockchip/vpu/Makefile | 1 + include/dt-bindings/clock/rockchip,rk3368.h | 1 + include/dt-bindings/clock/rockchip.h | 1 + include/dt-bindings/display/mipi_dsi.h | 1 + include/dt-bindings/display/rk_fb.h | 1 + .../dt-bindings/display/screen-timing/lcd-86v-rgb1024x600.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-F402.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-LP097Qx1.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-b101ew05.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-box.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-ld089wu1-mipi.dtsi | 1 + .../dt-bindings/display/screen-timing/lcd-lq070m1sx01-mipi.dtsi | 1 + .../display/screen-timing/lcd-rk3128-86v-LVDS1024x600.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-td043mgeal.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-tv080wum-mipi.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-vga.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-wqxga-mipi.dtsi | 1 + include/dt-bindings/display/screen-timing/lcd-y81349.dtsi | 1 + include/dt-bindings/input/rk-input.h | 1 + include/dt-bindings/pinctrl/rockchip-rk3036.h | 1 + include/dt-bindings/pinctrl/rockchip-rk312x.h | 1 + include/dt-bindings/power/rk3328-power.h | 1 + include/dt-bindings/power/rk3366-power.h | 1 + include/dt-bindings/power/rk3368-power.h | 1 + include/dt-bindings/power/rk3399-power.h | 1 + include/dt-bindings/sensor-dev.h | 1 + include/dt-bindings/soc/rockchip,boot-mode.h | 1 + include/linux/akm8963.h | 1 + include/linux/board-id-hw.h | 1 + include/linux/board-id-operator.h | 1 + include/linux/board-id.h | 1 + include/linux/bp-auto.h | 1 + include/linux/ct36x.h | 1 + include/linux/display-sys.h | 1 + include/linux/dp501.h | 1 + include/linux/goodix_queue.h | 1 + include/linux/goodix_touch.h | 1 + include/linux/goodix_touch_82x.h | 1 + include/linux/gps.h | 1 + include/linux/hdmi-notifier.h | 1 + include/linux/kxtik.h | 1 + include/linux/mfd/rk610_core.h | 1 + include/linux/mfd/rk616.h | 1 + include/linux/mfd/tlv320aic3262-core.h | 1 + include/linux/mfd/tlv320aic3262-registers.h | 1 + include/linux/mi700.h | 1 + include/linux/mma7660.h | 1 + include/linux/mma8452.h | 1 + include/linux/mpu6500.h | 1 + include/linux/mpu6880.h | 1 + include/linux/mt6229.h | 1 + include/linux/mtk23d.h | 1 + include/linux/mu509.h | 1 + include/linux/mw100.h | 1 + include/linux/platform_data/sram.h | 1 + include/linux/power/bq24296_charger.h | 1 + include/linux/power/rk_usbbc.h | 1 + include/linux/power/rockchip-6200ma-bat.h | 1 + include/linux/power/rockchip-general-bat.h | 1 + include/linux/rfkill-wlan.h | 1 + include/linux/rk_board_id.h | 1 + include/linux/rk_screen.h | 1 + include/linux/rockchip/grf.h | 1 + include/linux/rockchip/pmu.h | 1 + include/linux/rockchip/psci.h | 1 + include/linux/sc6610.h | 1 + include/linux/scaler-core.h | 1 + include/linux/sew868.h | 1 + include/linux/soc/rockchip/pvtm.h | 1 + include/linux/soc/rockchip/rk_fiq_debugger.h | 1 + include/linux/ste.h | 1 + include/linux/ts-auto.h | 1 + include/media/camsys_head.h | 1 + include/soc/rockchip/rkfb_dmc.h | 1 + include/trace/events/sync.h | 1 + security/optee_linuxdriver/Makefile | 1 + security/optee_linuxdriver/armtz/Makefile | 1 + security/optee_linuxdriver/core/Makefile | 1 + security/tlk_driver/Kconfig | 1 + sound/soc/codecs/aic3262_codec_ops.c | 1 + sound/soc/codecs/aic3262_codec_ops.h | 1 + sound/soc/codecs/aic3xxx_cfw.h | 1 + sound/soc/codecs/aic3xxx_cfw_ops.h | 1 + sound/soc/codecs/cxpump.h | 1 + sound/soc/codecs/pickle.h | 1 + sound/soc/codecs/rk3026_codec.c | 1 + sound/soc/codecs/rk3026_codec.h | 1 + sound/soc/codecs/rk312x_codec.h | 1 + sound/soc/codecs/rk3190_codec.c | 1 + sound/soc/codecs/rk3190_codec.h | 1 + sound/soc/codecs/rk616_codec.c | 1 + sound/soc/codecs/rk616_codec.h | 1 + sound/soc/codecs/rt5512.c | 1 + sound/soc/codecs/rt5512.h | 1 + sound/soc/codecs/tlv320aic3262_default_fw.h | 1 + 1416 files changed, 1416 insertions(+) mode change 100755 => 100644 arch/arm/boot/dts/rk3036-new.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3036-rk88.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3036-sdk.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3126-86v.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3126-cif-sensor.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3126-fpga.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3126-sdk.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3128-86v.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3128-box-ns.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3128-box-rk88.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3128-box.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3128-cif-sensor.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3128-sdk.dts mode change 100755 => 100644 arch/arm/boot/dts/rk312x-pinctrl.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk312x-sdk.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3188-pinctrl.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3288-chrome.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-cif-sensor.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3288-fpga.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-p977.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-p977_8846.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-pinctrl.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3288-tb.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-tb_8846.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-tb_sec.dts mode change 100755 => 100644 arch/arm/boot/dts/rk3288-tesco.dts mode change 100755 => 100644 arch/arm/boot/dts/rk808.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk818.dtsi mode change 100755 => 100644 block/partitions/rk.c mode change 100755 => 100644 block/partitions/rk.h mode change 100755 => 100644 drivers/bluetooth/vflash.c mode change 100755 => 100644 drivers/cir/Kconfig mode change 100755 => 100644 drivers/cir/Makefile mode change 100755 => 100644 drivers/cmmb/Kconfig mode change 100755 => 100644 drivers/cmmb/Makefile mode change 100755 => 100644 drivers/cmmb/cmmb_class.c mode change 100755 => 100644 drivers/cmmb/cmmb_class.h mode change 100755 => 100644 drivers/cmmb/cmmb_memory.c mode change 100755 => 100644 drivers/cmmb/cmmb_memory.h mode change 100755 => 100644 drivers/cmmb/siano/Kconfig mode change 100755 => 100644 drivers/cmmb/siano/compat.h mode change 100755 => 100644 drivers/gpu/arm/mali400/mali/Kconfig mode change 100755 => 100644 drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h mode change 100755 => 100644 drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h mode change 100755 => 100644 drivers/gpu/arm/mali400/ump/Kconfig mode change 100755 => 100644 drivers/gpu/arm/midgard/platform/rk/custom_log.h mode change 100755 => 100644 drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h mode change 100755 => 100644 drivers/gpu/rogue/Kconfig mode change 100755 => 100644 drivers/gpu/rogue/Makefile mode change 100755 => 100644 drivers/gpu/rogue/system/rk3368/rk_init.c mode change 100755 => 100644 drivers/gpu/rogue/system/rk3368/rk_init.h mode change 100755 => 100644 drivers/headset_observe/Kconfig mode change 100755 => 100644 drivers/headset_observe/Makefile mode change 100755 => 100644 drivers/headset_observe/rk_headset.h mode change 100755 => 100644 drivers/input/gsensor/Kconfig mode change 100755 => 100644 drivers/input/gsensor/Makefile mode change 100755 => 100644 drivers/input/gsensor/lis3dh.c mode change 100755 => 100644 drivers/input/gyroscope/Kconfig mode change 100755 => 100644 drivers/input/gyroscope/Makefile mode change 100755 => 100644 drivers/input/keyboard/synaptics_so340010.c mode change 100755 => 100644 drivers/input/lightsensor/cm3217.c mode change 100755 => 100644 drivers/input/magnetometer/Kconfig mode change 100755 => 100644 drivers/input/magnetometer/Makefile mode change 100755 => 100644 drivers/input/magnetometer/ak8973.h mode change 100755 => 100644 drivers/input/magnetometer/ak8975.h mode change 100755 => 100644 drivers/input/magnetometer/magnet.h mode change 100755 => 100644 drivers/input/misc/rk_board_id.c mode change 100755 => 100644 drivers/input/sensors/Kconfig mode change 100755 => 100644 drivers/input/sensors/Makefile mode change 100755 => 100644 drivers/input/sensors/accel/Kconfig mode change 100755 => 100644 drivers/input/sensors/accel/Makefile mode change 100755 => 100644 drivers/input/sensors/angle/Kconfig mode change 100755 => 100644 drivers/input/sensors/angle/Makefile mode change 100755 => 100644 drivers/input/sensors/compass/Kconfig mode change 100755 => 100644 drivers/input/sensors/compass/Makefile mode change 100755 => 100644 drivers/input/sensors/gyro/Kconfig mode change 100755 => 100644 drivers/input/sensors/gyro/Makefile mode change 100755 => 100644 drivers/input/sensors/lsensor/Kconfig mode change 100755 => 100644 drivers/input/sensors/lsensor/Makefile mode change 100755 => 100644 drivers/input/sensors/pressure/Kconfig mode change 100755 => 100644 drivers/input/sensors/pressure/Makefile mode change 100755 => 100644 drivers/input/sensors/psensor/Kconfig mode change 100755 => 100644 drivers/input/sensors/psensor/Makefile mode change 100755 => 100644 drivers/input/sensors/temperature/Kconfig mode change 100755 => 100644 drivers/input/sensors/temperature/Makefile mode change 100755 => 100644 drivers/input/touchscreen/IT7260_ts.h mode change 100755 => 100644 drivers/input/touchscreen/calib_iface_ts.c mode change 100755 => 100644 drivers/input/touchscreen/ct36x/core.c mode change 100755 => 100644 drivers/input/touchscreen/ct36x/ct363.c mode change 100755 => 100644 drivers/input/touchscreen/ct36x/ct36x_priv.h mode change 100755 => 100644 drivers/input/touchscreen/ct36x/ct36x_ts.c mode change 100755 => 100644 drivers/input/touchscreen/ctp_it7250.c mode change 100755 => 100644 drivers/input/touchscreen/ft5x0x.c mode change 100755 => 100644 drivers/input/touchscreen/ft5x0x_i2c_ts.h mode change 100755 => 100644 drivers/input/touchscreen/goodix_touch.c mode change 100755 => 100644 drivers/input/touchscreen/goodix_touch_82x.c mode change 100755 => 100644 drivers/input/touchscreen/goodix_touch_82x_760.c mode change 100755 => 100644 drivers/input/touchscreen/hannstar_p1003.c mode change 100755 => 100644 drivers/input/touchscreen/ili2102_ts.c mode change 100755 => 100644 drivers/input/touchscreen/nas_ts.c mode change 100755 => 100644 drivers/input/touchscreen/rk3028_gslX680_86v.h mode change 100755 => 100644 drivers/input/touchscreen/rk_tp.c mode change 100755 => 100644 drivers/input/touchscreen/rmi4/Kconfig mode change 100755 => 100644 drivers/input/touchscreen/rmi4/Makefile mode change 100755 => 100644 drivers/input/touchscreen/rockchip_gslX680_rk3128.h mode change 100755 => 100644 drivers/input/touchscreen/rockchip_gslX680_rk3168.h mode change 100755 => 100644 drivers/input/touchscreen/sintek_3FA16.c mode change 100755 => 100644 drivers/input/touchscreen/ts_lib/Makefile mode change 100755 => 100644 drivers/input/touchscreen/vtl_ts/Makefile mode change 100755 => 100644 drivers/input/touchscreen/vtl_ts/apk.h mode change 100755 => 100644 drivers/input/touchscreen/vtl_ts/chip.h mode change 100755 => 100644 drivers/input/touchscreen/vtl_ts/vtl_ts.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/Makefile mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6221_fw.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6223_fw.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6231_fw.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h mode change 100755 => 100644 drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h mode change 100755 => 100644 drivers/input/ts/Kconfig mode change 100755 => 100644 drivers/input/ts/Makefile mode change 100755 => 100644 drivers/input/ts/chips/Kconfig mode change 100755 => 100644 drivers/input/ts/chips/Makefile mode change 100755 => 100644 drivers/input/ts/chips/ct360_firmware.h mode change 100755 => 100644 drivers/input/ts/ts-serial.c mode change 100755 => 100644 drivers/input/ts/ts-spi.c mode change 100755 => 100644 drivers/media/video/hm5065.h mode change 100755 => 100644 drivers/media/video/mv9335/Kconfig mode change 100755 => 100644 drivers/media/video/mv9335/Makefile mode change 100755 => 100644 drivers/media/video/mv9335/mv9335.c mode change 100755 => 100644 drivers/media/video/nt99252_3way.c mode change 100755 => 100644 drivers/media/video/nt99340_2way.c mode change 100755 => 100644 drivers/media/video/ov2640_rk.c mode change 100755 => 100644 drivers/media/video/ov5640.h mode change 100755 => 100644 drivers/media/video/rk2928_camera.c mode change 100755 => 100644 drivers/media/video/rk29_camera.c mode change 100755 => 100644 drivers/media/video/rk_camsys/Kconfig mode change 100755 => 100644 drivers/media/video/rk_camsys/Makefile mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_cif.c mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_cif.h mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_marvin.h mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_mipicsi_phy.h mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_soc_priv.h mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_soc_rk3288.c mode change 100755 => 100644 drivers/media/video/rk_camsys/camsys_soc_rk3288.h mode change 100755 => 100644 drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig mode change 100755 => 100644 drivers/media/video/rk_camsys/ext_flashled_drv/Makefile mode change 100755 => 100644 drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h mode change 100755 => 100644 drivers/media/video/s5k5ca.h mode change 100755 => 100644 drivers/mfd/rk610-core.c mode change 100755 => 100644 drivers/mfd/rk616-core.c mode change 100755 => 100644 drivers/mfd/rk616-vif.c mode change 100755 => 100644 drivers/misc/3g_module/Kconfig mode change 100755 => 100644 drivers/misc/3g_module/Makefile mode change 100755 => 100644 drivers/misc/ac_usb_switch.c mode change 100755 => 100644 drivers/misc/bp/Kconfig mode change 100755 => 100644 drivers/misc/bp/Makefile mode change 100755 => 100644 drivers/misc/bp/bp-auto.c mode change 100755 => 100644 drivers/misc/bp/chips/Kconfig mode change 100755 => 100644 drivers/misc/bp/chips/Makefile mode change 100755 => 100644 drivers/misc/fm580x.h mode change 100755 => 100644 drivers/misc/gps/Kconfig mode change 100755 => 100644 drivers/misc/gps/Makefile mode change 100755 => 100644 drivers/misc/gps/rk29_gps.c mode change 100755 => 100644 drivers/misc/gps/rk_gps/Kconfig mode change 100755 => 100644 drivers/misc/gps/rk_gps/Makefile mode change 100755 => 100644 drivers/misc/gps/rk_gps/rk_gps.h mode change 100755 => 100644 drivers/misc/inv_mpu/Kconfig mode change 100755 => 100644 drivers/misc/inv_mpu/Makefile mode change 100755 => 100644 drivers/misc/inv_mpu/accel/Kconfig mode change 100755 => 100644 drivers/misc/inv_mpu/accel/Makefile mode change 100755 => 100644 drivers/misc/inv_mpu/compass/Kconfig mode change 100755 => 100644 drivers/misc/inv_mpu/compass/Makefile mode change 100755 => 100644 drivers/misc/inv_mpu/pressure/Kconfig mode change 100755 => 100644 drivers/misc/inv_mpu/pressure/Makefile mode change 100755 => 100644 drivers/misc/modem_sound.c mode change 100755 => 100644 drivers/misc/modem_sound.h mode change 100755 => 100644 drivers/misc/rk2928_callpad_misc/Kconfig mode change 100755 => 100644 drivers/misc/rk2928_callpad_misc/Makefile mode change 100755 => 100644 drivers/misc/rk2928_callpad_misc/audio_switch.h mode change 100755 => 100644 drivers/misc/sc8800.c mode change 100755 => 100644 drivers/misc/scaler/Kconfig mode change 100755 => 100644 drivers/misc/tcc_bt_dev.c mode change 100755 => 100644 drivers/mtd/rknand/Kconfig mode change 100755 => 100644 drivers/mtd/rknand/Makefile mode change 100755 => 100644 drivers/mtd/rknand/api_flash.h mode change 100755 => 100644 drivers/mtd/rknand/rknand_base.h mode change 100755 => 100644 drivers/mtd/rknand/rknand_base_ko.c mode change 100755 => 100644 drivers/net/ethernet/rockchip/Kconfig mode change 100755 => 100644 drivers/net/ethernet/rockchip/Makefile mode change 100755 => 100644 drivers/net/ethernet/rockchip/eth_mac.c mode change 100755 => 100644 drivers/net/ethernet/rockchip/gmac/Kconfig mode change 100755 => 100644 drivers/net/ethernet/rockchip/gmac/Makefile mode change 100755 => 100644 drivers/net/ethernet/rockchip/vmac/Kconfig mode change 100755 => 100644 drivers/net/ethernet/rockchip/vmac/Makefile mode change 100755 => 100644 drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c mode change 100755 => 100644 drivers/net/irda/bu92725guw.c mode change 100755 => 100644 drivers/net/irda/bu92725guw.h mode change 100755 => 100644 drivers/net/irda/ir_serial.h mode change 100755 => 100644 drivers/net/irda/rk29_ir.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h mode change 100755 => 100644 drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h mode change 100755 => 100644 drivers/net/wireless/rtl8723as/Kconfig mode change 100755 => 100644 drivers/power/rk29_charger_display.c mode change 100755 => 100644 drivers/regulator/rockchip_io_vol_domain.c mode change 100755 => 100644 drivers/rtc/auto-wake.c mode change 100755 => 100644 drivers/smc/Kconfig mode change 100755 => 100644 drivers/smc/Makefile mode change 100755 => 100644 drivers/smc/rk29_smc.c mode change 100755 => 100644 drivers/staging/rk29/ipp/Kconfig mode change 100755 => 100644 drivers/testcode/Kconfig mode change 100755 => 100644 drivers/testcode/Makefile mode change 100755 => 100644 drivers/testcode/gpio_wave.c mode change 100755 => 100644 drivers/testcode/gpio_wave.h mode change 100755 => 100644 drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c mode change 100755 => 100644 drivers/usb/dwc_otg_310/common_port/dwc_mem.c mode change 100755 => 100644 drivers/usb/dwc_otg_310/common_port/dwc_notifier.c mode change 100755 => 100644 drivers/usb/dwc_otg_310/common_port/dwc_notifier.h mode change 100755 => 100644 drivers/video/rockchip/Kconfig mode change 100755 => 100644 drivers/video/rockchip/Makefile mode change 100755 => 100644 drivers/video/rockchip/iep/Kconfig mode change 100755 => 100644 drivers/video/rockchip/iep/Makefile mode change 100755 => 100644 drivers/video/rockchip/iep/iep_mmu.h mode change 100755 => 100644 drivers/video/rockchip/lcdc/rk3036_lcdc.h mode change 100755 => 100644 drivers/video/rockchip/lcdc/rk312x_lcdc.h mode change 100755 => 100644 drivers/video/rockchip/lcdc/rk3188_lcdc.h mode change 100755 => 100644 drivers/video/rockchip/lcdc/rk3288_lcdc.h mode change 100755 => 100644 drivers/video/rockchip/lcdc/rk3368_lcdc.h mode change 100755 => 100644 drivers/video/rockchip/rga/Kconfig mode change 100755 => 100644 drivers/video/rockchip/rga/Makefile mode change 100755 => 100644 drivers/video/rockchip/rga/RGA_API.c mode change 100755 => 100644 drivers/video/rockchip/rga/RGA_API.h mode change 100755 => 100644 drivers/video/rockchip/rga/rga.h mode change 100755 => 100644 drivers/video/rockchip/rga/rga_mmu_info.c mode change 100755 => 100644 drivers/video/rockchip/rga/rga_mmu_info.h mode change 100755 => 100644 drivers/video/rockchip/rga/rga_reg_info.c mode change 100755 => 100644 drivers/video/rockchip/rga/rga_reg_info.h mode change 100755 => 100644 drivers/video/rockchip/rga/rga_rop.h mode change 100755 => 100644 drivers/video/rockchip/rga/rga_type.h mode change 100755 => 100644 drivers/video/rockchip/rga2/rga2.h mode change 100755 => 100644 drivers/video/rockchip/rga2/rga2_reg_info.c mode change 100755 => 100644 drivers/video/rockchip/rga2/rga2_reg_info.h mode change 100755 => 100644 drivers/video/rockchip/screen/Kconfig mode change 100755 => 100644 drivers/video/rockchip/transmitter/Kconfig mode change 100755 => 100644 drivers/video/rockchip/transmitter/Makefile mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk3026_lvds.c mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk3026_lvds.h mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk31xx_lvds.h mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk32_dp.h mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk32_lvds.c mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk32_lvds.h mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk616_lvds.c mode change 100755 => 100644 drivers/video/rockchip/transmitter/rk616_mipi_dsi.h mode change 100755 => 100644 drivers/video/rockchip/tve/rk1000/Kconfig mode change 100755 => 100644 drivers/video/rockchip/tve/rk1000/Makefile mode change 100755 => 100644 drivers/video/rockchip/tve/rk1000/rk1000_tve.h mode change 100755 => 100644 drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c mode change 100755 => 100644 drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c mode change 100755 => 100644 include/dt-bindings/display/mipi_dsi.h mode change 100755 => 100644 include/dt-bindings/display/rk_fb.h mode change 100755 => 100644 include/dt-bindings/pinctrl/rockchip-rk312x.h mode change 100755 => 100644 include/dt-bindings/sensor-dev.h mode change 100755 => 100644 include/linux/board-id-hw.h mode change 100755 => 100644 include/linux/board-id-operator.h mode change 100755 => 100644 include/linux/board-id.h mode change 100755 => 100644 include/linux/bp-auto.h mode change 100755 => 100644 include/linux/goodix_queue.h mode change 100755 => 100644 include/linux/goodix_touch.h mode change 100755 => 100644 include/linux/goodix_touch_82x.h mode change 100755 => 100644 include/linux/gps.h mode change 100755 => 100644 include/linux/kxtik.h mode change 100755 => 100644 include/linux/mfd/rk610_core.h mode change 100755 => 100644 include/linux/mfd/rk616.h mode change 100755 => 100644 include/linux/mma8452.h mode change 100755 => 100644 include/linux/mtk23d.h mode change 100755 => 100644 include/linux/mu509.h mode change 100755 => 100644 include/linux/power/bq24296_charger.h mode change 100755 => 100644 include/linux/power/rockchip-6200ma-bat.h mode change 100755 => 100644 include/linux/power/rockchip-general-bat.h mode change 100755 => 100644 include/linux/rk_board_id.h mode change 100755 => 100644 include/linux/rockchip/grf.h mode change 100755 => 100644 include/linux/sc6610.h mode change 100755 => 100644 include/linux/sew868.h mode change 100755 => 100644 include/linux/ts-auto.h mode change 100755 => 100644 sound/soc/codecs/rk3026_codec.c mode change 100755 => 100644 sound/soc/codecs/rk312x_codec.h mode change 100755 => 100644 sound/soc/codecs/rk3190_codec.c mode change 100755 => 100644 sound/soc/codecs/rk3190_codec.h mode change 100755 => 100644 sound/soc/codecs/rk616_codec.c mode change 100755 => 100644 sound/soc/codecs/rk616_codec.h mode change 100755 => 100644 sound/soc/codecs/rt5512.c mode change 100755 => 100644 sound/soc/codecs/rt5512.h diff --git a/arch/arm/boot/dts/act8846.dtsi b/arch/arm/boot/dts/act8846.dtsi index c8ba4b5bdc58..3f4a70a8e242 100644 --- a/arch/arm/boot/dts/act8846.dtsi +++ b/arch/arm/boot/dts/act8846.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) &act8846{ diff --git a/arch/arm/boot/dts/act8931.dtsi b/arch/arm/boot/dts/act8931.dtsi index 238ef95f58f4..f132bb2eeb45 100644 --- a/arch/arm/boot/dts/act8931.dtsi +++ b/arch/arm/boot/dts/act8931.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) &act8931{ diff --git a/arch/arm/boot/dts/rk3036-fpga.dts b/arch/arm/boot/dts/rk3036-fpga.dts index c8ae65af314e..d0127a377c03 100644 --- a/arch/arm/boot/dts/rk3036-fpga.dts +++ b/arch/arm/boot/dts/rk3036-fpga.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include #include "rk3036.dtsi" diff --git a/arch/arm/boot/dts/rk3036-new.dts b/arch/arm/boot/dts/rk3036-new.dts old mode 100755 new mode 100644 index 30ea4737b58b..1f3b609ee144 --- a/arch/arm/boot/dts/rk3036-new.dts +++ b/arch/arm/boot/dts/rk3036-new.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include #include "rk3036.dtsi" diff --git a/arch/arm/boot/dts/rk3036-pinctrl.dtsi b/arch/arm/boot/dts/rk3036-pinctrl.dtsi index 6297a05d4bb1..24e503d23cd8 100644 --- a/arch/arm/boot/dts/rk3036-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3036-pinctrl.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include #include #include diff --git a/arch/arm/boot/dts/rk3036-rk88.dts b/arch/arm/boot/dts/rk3036-rk88.dts old mode 100755 new mode 100644 index e997bcc1f608..0aaa55c768e5 --- a/arch/arm/boot/dts/rk3036-rk88.dts +++ b/arch/arm/boot/dts/rk3036-rk88.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include #include "rk3036.dtsi" diff --git a/arch/arm/boot/dts/rk3036-sdk.dts b/arch/arm/boot/dts/rk3036-sdk.dts old mode 100755 new mode 100644 index 52ecd752509e..0739b892eff8 --- a/arch/arm/boot/dts/rk3036-sdk.dts +++ b/arch/arm/boot/dts/rk3036-sdk.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include #include "rk3036.dtsi" diff --git a/arch/arm/boot/dts/rk3126-86v.dts b/arch/arm/boot/dts/rk3126-86v.dts old mode 100755 new mode 100644 index 633dc603fc4a..1a103fe8c7ca --- a/arch/arm/boot/dts/rk3126-86v.dts +++ b/arch/arm/boot/dts/rk3126-86v.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3126.dtsi" diff --git a/arch/arm/boot/dts/rk3126-cif-sensor.dtsi b/arch/arm/boot/dts/rk3126-cif-sensor.dtsi old mode 100755 new mode 100644 index 9aef52e22d14..28c1bec52cb3 --- a/arch/arm/boot/dts/rk3126-cif-sensor.dtsi +++ b/arch/arm/boot/dts/rk3126-cif-sensor.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "../../mach-rockchip/rk_camera_sensor_info.h" /{ rk3126_cif_sensor: rk3126_cif_sensor{ diff --git a/arch/arm/boot/dts/rk3126-fpga.dts b/arch/arm/boot/dts/rk3126-fpga.dts old mode 100755 new mode 100644 index b889ffde524e..55bf6e49f77b --- a/arch/arm/boot/dts/rk3126-fpga.dts +++ b/arch/arm/boot/dts/rk3126-fpga.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk312x.dtsi" #include "rk312x-pinctrl.dtsi" diff --git a/arch/arm/boot/dts/rk3126-m708-cif-sensor.dtsi b/arch/arm/boot/dts/rk3126-m708-cif-sensor.dtsi index cf61c1dcbbbd..267ff93c34d8 100644 --- a/arch/arm/boot/dts/rk3126-m708-cif-sensor.dtsi +++ b/arch/arm/boot/dts/rk3126-m708-cif-sensor.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "../../../../drivers/soc/rockchip/rk_camera_sensor_info.h" /{ cif_sensor: cif_sensor { diff --git a/arch/arm/boot/dts/rk3126-sdk.dts b/arch/arm/boot/dts/rk3126-sdk.dts old mode 100755 new mode 100644 index 5173e4b44e1c..7769ba75b600 --- a/arch/arm/boot/dts/rk3126-sdk.dts +++ b/arch/arm/boot/dts/rk3126-sdk.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3126.dtsi" diff --git a/arch/arm/boot/dts/rk3128-86v.dts b/arch/arm/boot/dts/rk3128-86v.dts old mode 100755 new mode 100644 index 112f5ddf8bf4..46b39971afe3 --- a/arch/arm/boot/dts/rk3128-86v.dts +++ b/arch/arm/boot/dts/rk3128-86v.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3128.dtsi" diff --git a/arch/arm/boot/dts/rk3128-box-ns.dts b/arch/arm/boot/dts/rk3128-box-ns.dts old mode 100755 new mode 100644 index 3346ee70a7a9..5ff15e7949ff --- a/arch/arm/boot/dts/rk3128-box-ns.dts +++ b/arch/arm/boot/dts/rk3128-box-ns.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "rk3128-box.dts" / { diff --git a/arch/arm/boot/dts/rk3128-box-rk88.dts b/arch/arm/boot/dts/rk3128-box-rk88.dts old mode 100755 new mode 100644 index 3158daa638e4..862275417b88 --- a/arch/arm/boot/dts/rk3128-box-rk88.dts +++ b/arch/arm/boot/dts/rk3128-box-rk88.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3128.dtsi" diff --git a/arch/arm/boot/dts/rk3128-box.dts b/arch/arm/boot/dts/rk3128-box.dts old mode 100755 new mode 100644 index bcc676e9a6e8..c25628f943d4 --- a/arch/arm/boot/dts/rk3128-box.dts +++ b/arch/arm/boot/dts/rk3128-box.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3128.dtsi" diff --git a/arch/arm/boot/dts/rk3128-cif-sensor.dtsi b/arch/arm/boot/dts/rk3128-cif-sensor.dtsi old mode 100755 new mode 100644 index 1b5816ddd7bd..7f6b5cbecd95 --- a/arch/arm/boot/dts/rk3128-cif-sensor.dtsi +++ b/arch/arm/boot/dts/rk3128-cif-sensor.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "../../mach-rockchip/rk_camera_sensor_info.h" /{ rk3128_cif_sensor: rk3128_cif_sensor{ diff --git a/arch/arm/boot/dts/rk3128-sdk.dts b/arch/arm/boot/dts/rk3128-sdk.dts old mode 100755 new mode 100644 index b570b7612a32..77c3778a1dd6 --- a/arch/arm/boot/dts/rk3128-sdk.dts +++ b/arch/arm/boot/dts/rk3128-sdk.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3128.dtsi" diff --git a/arch/arm/boot/dts/rk312x-pinctrl.dtsi b/arch/arm/boot/dts/rk312x-pinctrl.dtsi old mode 100755 new mode 100644 index 197fe6640d34..6a8ca01dfab7 --- a/arch/arm/boot/dts/rk312x-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk312x-pinctrl.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include #include #include diff --git a/arch/arm/boot/dts/rk312x-sdk.dtsi b/arch/arm/boot/dts/rk312x-sdk.dtsi old mode 100755 new mode 100644 index 8d042fcee83f..880c71bd4f0f --- a/arch/arm/boot/dts/rk312x-sdk.dtsi +++ b/arch/arm/boot/dts/rk312x-sdk.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) / { fiq-debugger { diff --git a/arch/arm/boot/dts/rk3188-lr097.dts b/arch/arm/boot/dts/rk3188-lr097.dts index 9ca13b42739d..f426dddff7bc 100644 --- a/arch/arm/boot/dts/rk3188-lr097.dts +++ b/arch/arm/boot/dts/rk3188-lr097.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3188.dtsi" diff --git a/arch/arm/boot/dts/rk3188-pinctrl.dtsi b/arch/arm/boot/dts/rk3188-pinctrl.dtsi old mode 100755 new mode 100644 index 7deedbd8f577..e2422da47e53 --- a/arch/arm/boot/dts/rk3188-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3188-pinctrl.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include #include #include diff --git a/arch/arm/boot/dts/rk3188-tb.dts b/arch/arm/boot/dts/rk3188-tb.dts index d091770f6b48..799695b8cd4a 100644 --- a/arch/arm/boot/dts/rk3188-tb.dts +++ b/arch/arm/boot/dts/rk3188-tb.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3188.dtsi" diff --git a/arch/arm/boot/dts/rk3288-box.dts b/arch/arm/boot/dts/rk3288-box.dts index 529f72f56d57..c699e19a9dcb 100644 --- a/arch/arm/boot/dts/rk3288-box.dts +++ b/arch/arm/boot/dts/rk3288-box.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-chrome.dts b/arch/arm/boot/dts/rk3288-chrome.dts old mode 100755 new mode 100644 index 5b6723f2c958..bb80437e18ad --- a/arch/arm/boot/dts/rk3288-chrome.dts +++ b/arch/arm/boot/dts/rk3288-chrome.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-cif-sensor.dtsi b/arch/arm/boot/dts/rk3288-cif-sensor.dtsi old mode 100755 new mode 100644 index 70bbc142b0d4..05bd4da9de4e --- a/arch/arm/boot/dts/rk3288-cif-sensor.dtsi +++ b/arch/arm/boot/dts/rk3288-cif-sensor.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "rk3288.dtsi" #include "rk3288-pinctrl.dtsi" #include "../../mach-rockchip/rk_camera_sensor_info.h" diff --git a/arch/arm/boot/dts/rk3288-fpga.dts b/arch/arm/boot/dts/rk3288-fpga.dts old mode 100755 new mode 100644 index 52a05a137d2a..3a1adb851743 --- a/arch/arm/boot/dts/rk3288-fpga.dts +++ b/arch/arm/boot/dts/rk3288-fpga.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include diff --git a/arch/arm/boot/dts/rk3288-p977.dts b/arch/arm/boot/dts/rk3288-p977.dts old mode 100755 new mode 100644 index 9818d9dcd536..15718de360c2 --- a/arch/arm/boot/dts/rk3288-p977.dts +++ b/arch/arm/boot/dts/rk3288-p977.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-p977_8846.dts b/arch/arm/boot/dts/rk3288-p977_8846.dts old mode 100755 new mode 100644 index d40aac95e161..efb12c97f7a6 --- a/arch/arm/boot/dts/rk3288-p977_8846.dts +++ b/arch/arm/boot/dts/rk3288-p977_8846.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-pinctrl.dtsi b/arch/arm/boot/dts/rk3288-pinctrl.dtsi old mode 100755 new mode 100644 index 8046018785ad..e71d6b8e469d --- a/arch/arm/boot/dts/rk3288-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3288-pinctrl.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include #include #include diff --git a/arch/arm/boot/dts/rk3288-tb.dts b/arch/arm/boot/dts/rk3288-tb.dts old mode 100755 new mode 100644 index c8cc6c30a6a4..e9de1d435ae4 --- a/arch/arm/boot/dts/rk3288-tb.dts +++ b/arch/arm/boot/dts/rk3288-tb.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-tb_8846.dts b/arch/arm/boot/dts/rk3288-tb_8846.dts old mode 100755 new mode 100644 index 230a75d66890..65e96c4acd51 --- a/arch/arm/boot/dts/rk3288-tb_8846.dts +++ b/arch/arm/boot/dts/rk3288-tb_8846.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk3288-tb_sec.dts b/arch/arm/boot/dts/rk3288-tb_sec.dts old mode 100755 new mode 100644 index b9cb31328b41..3c9c7c805fcc --- a/arch/arm/boot/dts/rk3288-tb_sec.dts +++ b/arch/arm/boot/dts/rk3288-tb_sec.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "rk3288-tb_8846.dts" diff --git a/arch/arm/boot/dts/rk3288-tesco.dts b/arch/arm/boot/dts/rk3288-tesco.dts old mode 100755 new mode 100644 index 235962b0b0b7..2fa6066b08af --- a/arch/arm/boot/dts/rk3288-tesco.dts +++ b/arch/arm/boot/dts/rk3288-tesco.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /dts-v1/; #include "rk3288.dtsi" diff --git a/arch/arm/boot/dts/rk616.dtsi b/arch/arm/boot/dts/rk616.dtsi index 0c1b91435959..f27ab4ec3252 100644 --- a/arch/arm/boot/dts/rk616.dtsi +++ b/arch/arm/boot/dts/rk616.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) &rk616 { diff --git a/arch/arm/boot/dts/rk808.dtsi b/arch/arm/boot/dts/rk808.dtsi old mode 100755 new mode 100644 index 54cd24d703d9..2d3179c185d8 --- a/arch/arm/boot/dts/rk808.dtsi +++ b/arch/arm/boot/dts/rk808.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) &rk808 { compatible = "rockchip,rk808"; diff --git a/arch/arm/boot/dts/rk818.dtsi b/arch/arm/boot/dts/rk818.dtsi old mode 100755 new mode 100644 index eacd03b8f7e8..e174558ce5b9 --- a/arch/arm/boot/dts/rk818.dtsi +++ b/arch/arm/boot/dts/rk818.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) &rk818 { compatible = "rockchip,rk818"; diff --git a/arch/arm/boot/dts/vtl_ts_p977.dtsi b/arch/arm/boot/dts/vtl_ts_p977.dtsi index 1c04244b603e..9b8538a35703 100644 --- a/arch/arm/boot/dts/vtl_ts_p977.dtsi +++ b/arch/arm/boot/dts/vtl_ts_p977.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /{ tp-fw{ diff --git a/arch/arm/boot/dts/vtl_ts_sdk8846.dtsi b/arch/arm/boot/dts/vtl_ts_sdk8846.dtsi index 267aa137a062..700460525de7 100644 --- a/arch/arm/boot/dts/vtl_ts_sdk8846.dtsi +++ b/arch/arm/boot/dts/vtl_ts_sdk8846.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /{ tp-fw{ diff --git a/arch/arm/mach-rockchip/embedded/Makefile b/arch/arm/mach-rockchip/embedded/Makefile index a8d8f4700b32..46b5043d65e6 100644 --- a/arch/arm/mach-rockchip/embedded/Makefile +++ b/arch/arm/mach-rockchip/embedded/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # Makefile for embedded code blobs for Rockchip SoCs # # These code blobs are emedded into vmlinux and copied into SRAM diff --git a/arch/arm/mach-rockchip/embedded/rk3288_resume.lds.S b/arch/arm/mach-rockchip/embedded/rk3288_resume.lds.S index 0643169d496f..74ec884b29e8 100644 --- a/arch/arm/mach-rockchip/embedded/rk3288_resume.lds.S +++ b/arch/arm/mach-rockchip/embedded/rk3288_resume.lds.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ MEMORY { pmu_sram_code : ORIGIN = 0xff720000, LENGTH = 0xf00 pmu_sram_stack : ORIGIN = 0xff720f00, LENGTH = 0x100 diff --git a/arch/arm64/boot/dts/rockchip/rk3368-cif-sensor.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-cif-sensor.dtsi index bf0be36c0788..7d2aac22c020 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-cif-sensor.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-cif-sensor.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include "../../../../../drivers/soc/rockchip/rk_camera_sensor_info.h" /{ diff --git a/arch/arm64/include/asm/system_info.h b/arch/arm64/include/asm/system_info.h index 7f4d9c7566ac..a82fe791b2f6 100644 --- a/arch/arm64/include/asm/system_info.h +++ b/arch/arm64/include/asm/system_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ASM_ARM_SYSTEM_INFO_H #define __ASM_ARM_SYSTEM_INFO_H diff --git a/block/partitions/rk.c b/block/partitions/rk.c old mode 100755 new mode 100644 index 73a8f8db3be4..9af428681663 --- a/block/partitions/rk.c +++ b/block/partitions/rk.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/block/partitions/rk.h b/block/partitions/rk.h old mode 100755 new mode 100644 index 25085e716df5..ffe0715f66e5 --- a/block/partitions/rk.h +++ b/block/partitions/rk.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * block/partitions/rk.h */ diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 6914a8f6c4a4..7a874af0c448 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # ADC subsystem configuration # diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index 3352b9167fcd..46eb85783ba5 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the adc core. # diff --git a/drivers/adc/plat/Kconfig b/drivers/adc/plat/Kconfig index 915d50c0bd6d..d720f98e634c 100644 --- a/drivers/adc/plat/Kconfig +++ b/drivers/adc/plat/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Adc hardware configuration # diff --git a/drivers/adc/plat/Makefile b/drivers/adc/plat/Makefile index 02831d738541..3c304e217fd7 100644 --- a/drivers/adc/plat/Makefile +++ b/drivers/adc/plat/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the adc hardware drivers. # diff --git a/drivers/bluetooth/vflash.c b/drivers/bluetooth/vflash.c old mode 100755 new mode 100644 index bb37c7395718..dcde21b37694 --- a/drivers/bluetooth/vflash.c +++ b/drivers/bluetooth/vflash.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2010 ROCKCHIP, Inc. * Author: roger_chen diff --git a/drivers/cir/Kconfig b/drivers/cir/Kconfig old mode 100755 new mode 100644 index edf8d04e93c4..015913650be9 --- a/drivers/cir/Kconfig +++ b/drivers/cir/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # CIR class/drivers configuration # diff --git a/drivers/cir/Makefile b/drivers/cir/Makefile old mode 100755 new mode 100644 index 8e4f547fa6ee..f17715edaad2 --- a/drivers/cir/Makefile +++ b/drivers/cir/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for CIR class/drivers. # diff --git a/drivers/cmmb/Kconfig b/drivers/cmmb/Kconfig old mode 100755 new mode 100644 index 9df2cd23da80..6a4dc5316cef --- a/drivers/cmmb/Kconfig +++ b/drivers/cmmb/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "CMMB" config CMMB diff --git a/drivers/cmmb/Makefile b/drivers/cmmb/Makefile old mode 100755 new mode 100644 index e32d38451987..ba0ca6115400 --- a/drivers/cmmb/Makefile +++ b/drivers/cmmb/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the dsp core. # diff --git a/drivers/cmmb/cmmb_class.c b/drivers/cmmb/cmmb_class.c old mode 100755 new mode 100644 index 349acd9ec911..016b5545abc2 --- a/drivers/cmmb/cmmb_class.c +++ b/drivers/cmmb/cmmb_class.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/cmmb/cmmb_class.h b/drivers/cmmb/cmmb_class.h old mode 100755 new mode 100644 index d6e9e5a48fd8..51a978ee10fb --- a/drivers/cmmb/cmmb_class.h +++ b/drivers/cmmb/cmmb_class.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _CMMB_CLASS_H_ #define _CMMB_CLASS_H_ diff --git a/drivers/cmmb/cmmb_memory.c b/drivers/cmmb/cmmb_memory.c old mode 100755 new mode 100644 index 0e8c03d26798..b3b756208fc5 --- a/drivers/cmmb/cmmb_memory.c +++ b/drivers/cmmb/cmmb_memory.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "cmmb_memory.h" #include "cmmb_class.h" #include diff --git a/drivers/cmmb/cmmb_memory.h b/drivers/cmmb/cmmb_memory.h old mode 100755 new mode 100644 index efd85ece78ef..f7039df2b265 --- a/drivers/cmmb/cmmb_memory.h +++ b/drivers/cmmb/cmmb_memory.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _CMMB_AV_MEMORY_H_ #define _CMMB_AV_MEMORY_H_ diff --git a/drivers/cmmb/siano/Kconfig b/drivers/cmmb/siano/Kconfig old mode 100755 new mode 100644 index 45a6666b9ed5..6db1b6af7356 --- a/drivers/cmmb/siano/Kconfig +++ b/drivers/cmmb/siano/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Siano Mobile Silicon Digital TV device configuration # diff --git a/drivers/cmmb/siano/compat.h b/drivers/cmmb/siano/compat.h old mode 100755 new mode 100644 index 551696082a4b..91c2860093ef --- a/drivers/cmmb/siano/compat.h +++ b/drivers/cmmb/siano/compat.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * $Id: compat.h,v 1.44 2006/01/15 09:35:16 mchehab Exp $ */ diff --git a/drivers/gpu/arm/mali400/Kbuild b/drivers/gpu/arm/mali400/Kbuild index 9e361d3f7937..addbd0031ca4 100644 --- a/drivers/gpu/arm/mali400/Kbuild +++ b/drivers/gpu/arm/mali400/Kbuild @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-y += mali/ ump/ diff --git a/drivers/gpu/arm/mali400/mali/Kconfig b/drivers/gpu/arm/mali400/mali/Kconfig old mode 100755 new mode 100644 index 7b4e9fb2cf90..3184d395f030 --- a/drivers/gpu/arm/mali400/mali/Kconfig +++ b/drivers/gpu/arm/mali400/mali/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config MALI400 tristate "Mali-300/400/450 support" depends on ARM || ARM64 diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h b/drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h old mode 100755 new mode 100644 index 646fe37498d0..fe5e1224149e --- a/drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h +++ b/drivers/gpu/arm/mali400/mali/platform/rk/custom_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ---------------------------------------------------------------------------- * File: custom_log.h * diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h b/drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h old mode 100755 new mode 100644 index 1c3c6540c177..bd939350c425 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk_ext.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ---------------------------------------------------------------------------- * File: rk_ext.h * diff --git a/drivers/gpu/arm/mali400/ump/Kconfig b/drivers/gpu/arm/mali400/ump/Kconfig old mode 100755 new mode 100644 index 3ae316c90ca3..18df9111534b --- a/drivers/gpu/arm/mali400/ump/Kconfig +++ b/drivers/gpu/arm/mali400/ump/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config UMP tristate "UMP support" depends on ARM diff --git a/drivers/gpu/arm/midgard/platform/rk/custom_log.h b/drivers/gpu/arm/midgard/platform/rk/custom_log.h old mode 100755 new mode 100644 index 646fe37498d0..fe5e1224149e --- a/drivers/gpu/arm/midgard/platform/rk/custom_log.h +++ b/drivers/gpu/arm/midgard/platform/rk/custom_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ---------------------------------------------------------------------------- * File: custom_log.h * diff --git a/drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h b/drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h old mode 100755 new mode 100644 index 646fe37498d0..fe5e1224149e --- a/drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h +++ b/drivers/gpu/arm/midgard_for_linux/platform/rk/custom_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ---------------------------------------------------------------------------- * File: custom_log.h * diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index 80f286fa3a69..456c189eb809 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config DRM_ANALOGIX_DP tristate depends on DRM diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile index cd4010ba6890..472a3a4a9601 100644 --- a/drivers/gpu/drm/bridge/analogix/Makefile +++ b/drivers/gpu/drm/bridge/analogix/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig index 4fd762d1fbde..6e410c39009d 100644 --- a/drivers/gpu/drm/bridge/synopsys/Kconfig +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config DRM_DW_HDMI tristate select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile index d52c7c3ce75e..eca236b30e03 100644 --- a/drivers/gpu/drm/bridge/synopsys/Makefile +++ b/drivers/gpu/drm/bridge/synopsys/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 #ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o dw-hdmi-hdcp.o diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h index d3194b4e186b..3930ba04977b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef DW_HDMI_AUDIO_H #define DW_HDMI_AUDIO_H diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h index cf4dc121a2c4..d27dffbe1bf0 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef DW_HDMI_CEC_H #define DW_HDMI_CEC_H diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index d8813e98073d..4f91c7e9cc4c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/gpu/rogue/Kconfig b/drivers/gpu/rogue/Kconfig old mode 100755 new mode 100644 index 91d129f29c46..5c426b80ffc5 --- a/drivers/gpu/rogue/Kconfig +++ b/drivers/gpu/rogue/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config POWERVR_ROGUE tristate "PowerVR Rogue" default n diff --git a/drivers/gpu/rogue/Makefile b/drivers/gpu/rogue/Makefile old mode 100755 new mode 100644 index f5478bb32c68..f7fe7dfc84d4 --- a/drivers/gpu/rogue/Makefile +++ b/drivers/gpu/rogue/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include drivers/gpu/rogue/config_kernel.mk obj-$(CONFIG_POWERVR_ROGUE) += pvrsrvkm.o diff --git a/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk b/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk index 97136fe6a45d..7a476ab7a3bf 100644 --- a/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk +++ b/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # 64-bit Android AArch64 compiler TARGET_PRIMARY_ARCH := target_aarch64 ifeq ($(MULTIARCH),1) diff --git a/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk b/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk index d671ba9ccc18..c5b488e3b43b 100644 --- a/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk +++ b/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit ARM EABI compiler TARGET_PRIMARY_ARCH := target_armv7-a diff --git a/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk b/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk index 8aaeaadf43d9..f163d3fd9b5e 100644 --- a/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk +++ b/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit Android ARM compiler include $(compilers)/arm-eabi.mk diff --git a/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk b/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk index cd9539c7cf68..f0f1c98b62ba 100644 --- a/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk +++ b/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit x86 compiler TARGET_PRIMARY_ARCH := target_i686 diff --git a/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk b/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk index 008e86b35a92..106480a1adfd 100644 --- a/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk +++ b/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # 64-bit x86 compiler TARGET_FORCE_32BIT := -m32 diff --git a/drivers/gpu/rogue/config_kernel.h b/drivers/gpu/rogue/config_kernel.h index c00d1985435b..39cc52000436 100644 --- a/drivers/gpu/rogue/config_kernel.h +++ b/drivers/gpu/rogue/config_kernel.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define SUPPORT_ION #define PVR_ANDROID_ION_HEADER "../drivers/staging/android/ion/ion.h" #define PVR_ANDROID_ION_PRIV_HEADER "../drivers/staging/android/ion/ion_priv.h" diff --git a/drivers/gpu/rogue/config_kernel.mk b/drivers/gpu/rogue/config_kernel.mk index 493cf06999d5..47fcc2f364de 100644 --- a/drivers/gpu/rogue/config_kernel.mk +++ b/drivers/gpu/rogue/config_kernel.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 override HOST_PRIMARY_ARCH := host_x86_64 override HOST_32BIT_ARCH := host_i386 override HOST_FORCE_32BIT := -m32 diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.c b/drivers/gpu/rogue/system/rk3368/rk_init.c old mode 100755 new mode 100644 index d4e4f3ee8973..10347c435baa --- a/drivers/gpu/rogue/system/rk3368/rk_init.c +++ b/drivers/gpu/rogue/system/rk3368/rk_init.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if defined(SUPPORT_ION) #include "ion_sys.h" #endif /* defined(SUPPORT_ION) */ diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.h b/drivers/gpu/rogue/system/rk3368/rk_init.h old mode 100755 new mode 100644 index b71ad46ce0c4..a66716eac4df --- a/drivers/gpu/rogue/system/rk3368/rk_init.h +++ b/drivers/gpu/rogue/system/rk3368/rk_init.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if !defined(__RK_INIT__) #define __RK_INIT__ diff --git a/drivers/gpu/rogue_m/Kconfig b/drivers/gpu/rogue_m/Kconfig index 59ca0ed4ff10..87b429e05460 100644 --- a/drivers/gpu/rogue_m/Kconfig +++ b/drivers/gpu/rogue_m/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config POWERVR_ROGUE_M tristate "PowerVR Rogue M" select PM_OPP diff --git a/drivers/gpu/rogue_m/Makefile b/drivers/gpu/rogue_m/Makefile index c990871ee4ce..0e954b33bdf9 100644 --- a/drivers/gpu/rogue_m/Makefile +++ b/drivers/gpu/rogue_m/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include drivers/gpu/rogue_m/config_kernel.mk obj-$(CONFIG_POWERVR_ROGUE_M) += pvrsrvkm.o diff --git a/drivers/gpu/rogue_m/build/linux/config/compilers/aarch64-linux-android.mk b/drivers/gpu/rogue_m/build/linux/config/compilers/aarch64-linux-android.mk index 97136fe6a45d..7a476ab7a3bf 100644 --- a/drivers/gpu/rogue_m/build/linux/config/compilers/aarch64-linux-android.mk +++ b/drivers/gpu/rogue_m/build/linux/config/compilers/aarch64-linux-android.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # 64-bit Android AArch64 compiler TARGET_PRIMARY_ARCH := target_aarch64 ifeq ($(MULTIARCH),1) diff --git a/drivers/gpu/rogue_m/build/linux/config/compilers/arm-eabi.mk b/drivers/gpu/rogue_m/build/linux/config/compilers/arm-eabi.mk index d671ba9ccc18..c5b488e3b43b 100644 --- a/drivers/gpu/rogue_m/build/linux/config/compilers/arm-eabi.mk +++ b/drivers/gpu/rogue_m/build/linux/config/compilers/arm-eabi.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit ARM EABI compiler TARGET_PRIMARY_ARCH := target_armv7-a diff --git a/drivers/gpu/rogue_m/build/linux/config/compilers/arm-linux-androideabi.mk b/drivers/gpu/rogue_m/build/linux/config/compilers/arm-linux-androideabi.mk index 8aaeaadf43d9..f163d3fd9b5e 100644 --- a/drivers/gpu/rogue_m/build/linux/config/compilers/arm-linux-androideabi.mk +++ b/drivers/gpu/rogue_m/build/linux/config/compilers/arm-linux-androideabi.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit Android ARM compiler include $(compilers)/arm-eabi.mk diff --git a/drivers/gpu/rogue_m/build/linux/config/compilers/i386-linux-gnu.mk b/drivers/gpu/rogue_m/build/linux/config/compilers/i386-linux-gnu.mk index cd9539c7cf68..f0f1c98b62ba 100644 --- a/drivers/gpu/rogue_m/build/linux/config/compilers/i386-linux-gnu.mk +++ b/drivers/gpu/rogue_m/build/linux/config/compilers/i386-linux-gnu.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 # 32-bit x86 compiler TARGET_PRIMARY_ARCH := target_i686 diff --git a/drivers/gpu/rogue_m/build/linux/config/compilers/x86_64-linux-gnu.mk b/drivers/gpu/rogue_m/build/linux/config/compilers/x86_64-linux-gnu.mk index 008e86b35a92..106480a1adfd 100644 --- a/drivers/gpu/rogue_m/build/linux/config/compilers/x86_64-linux-gnu.mk +++ b/drivers/gpu/rogue_m/build/linux/config/compilers/x86_64-linux-gnu.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # 64-bit x86 compiler TARGET_FORCE_32BIT := -m32 diff --git a/drivers/gpu/rogue_m/config_kernel.h b/drivers/gpu/rogue_m/config_kernel.h index 6303347cc976..35b87df2b535 100644 --- a/drivers/gpu/rogue_m/config_kernel.h +++ b/drivers/gpu/rogue_m/config_kernel.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define SUPPORT_ION #define PVR_ANDROID_ION_HEADER "../drivers/staging/android/ion/ion.h" #define PVR_ANDROID_ION_PRIV_HEADER "../drivers/staging/android/ion/ion_priv.h" diff --git a/drivers/gpu/rogue_m/config_kernel.mk b/drivers/gpu/rogue_m/config_kernel.mk index 482440c3da6b..7389022b5617 100644 --- a/drivers/gpu/rogue_m/config_kernel.mk +++ b/drivers/gpu/rogue_m/config_kernel.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 override HOST_PRIMARY_ARCH := host_x86_64 override HOST_32BIT_ARCH := host_i386 override HOST_FORCE_32BIT := -m32 diff --git a/drivers/gpu/rogue_m/system/rk3368/rk_init.c b/drivers/gpu/rogue_m/system/rk3368/rk_init.c index 205fc569d0ea..1b58883b5ee9 100644 --- a/drivers/gpu/rogue_m/system/rk3368/rk_init.c +++ b/drivers/gpu/rogue_m/system/rk3368/rk_init.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if defined(SUPPORT_ION) #include "ion_sys.h" #endif /* defined(SUPPORT_ION) */ diff --git a/drivers/gpu/rogue_m/system/rk3368/rk_init.h b/drivers/gpu/rogue_m/system/rk3368/rk_init.h index bd4d0491e65b..d1781e5bfd20 100644 --- a/drivers/gpu/rogue_m/system/rk3368/rk_init.h +++ b/drivers/gpu/rogue_m/system/rk3368/rk_init.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if !defined(__RK_INIT__) #define __RK_INIT__ diff --git a/drivers/headset_observe/Kconfig b/drivers/headset_observe/Kconfig old mode 100755 new mode 100644 index ae10bff0762e..972cbd4907b3 --- a/drivers/headset_observe/Kconfig +++ b/drivers/headset_observe/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Headset device configuration # diff --git a/drivers/headset_observe/Makefile b/drivers/headset_observe/Makefile old mode 100755 new mode 100644 index 43ca02b1653b..1bdf4450e463 --- a/drivers/headset_observe/Makefile +++ b/drivers/headset_observe/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK_HEADSET) += rockchip_headset_core.o rk_headset.o rk_headset_irq_hook_adc.o diff --git a/drivers/headset_observe/rk_headset.h b/drivers/headset_observe/rk_headset.h old mode 100755 new mode 100644 index 87ee42d36745..28307bd683c5 --- a/drivers/headset_observe/rk_headset.h +++ b/drivers/headset_observe/rk_headset.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK_HEADSET_H #define RK_HEADSET_H diff --git a/drivers/input/gsensor/Kconfig b/drivers/input/gsensor/Kconfig old mode 100755 new mode 100644 index 5fafd3bbb74a..745750e9c91f --- a/drivers/input/gsensor/Kconfig +++ b/drivers/input/gsensor/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gsensor drivers configuration # diff --git a/drivers/input/gsensor/Makefile b/drivers/input/gsensor/Makefile old mode 100755 new mode 100644 index 728942556a98..7c9fa680b407 --- a/drivers/input/gsensor/Makefile +++ b/drivers/input/gsensor/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gsensor drivers obj-$(CONFIG_GS_MMA7660) += mma7660.o diff --git a/drivers/input/gsensor/lis3dh.c b/drivers/input/gsensor/lis3dh.c old mode 100755 new mode 100644 index 895ba98255c8..6bd453e55404 --- a/drivers/input/gsensor/lis3dh.c +++ b/drivers/input/gsensor/lis3dh.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * File: driver/input/gsensor/lis3dh.c diff --git a/drivers/input/gsensor/lis3dh.h b/drivers/input/gsensor/lis3dh.h index 5383134a6eaf..c356d062a283 100644 --- a/drivers/input/gsensor/lis3dh.h +++ b/drivers/input/gsensor/lis3dh.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * File: driver/input/gsensor/lis3dh.h * Copyright: Copyright (C) 2012-2013 RK Corporation. diff --git a/drivers/input/gyroscope/Kconfig b/drivers/input/gyroscope/Kconfig old mode 100755 new mode 100644 index e6d24d562e25..becaaef2a273 --- a/drivers/input/gyroscope/Kconfig +++ b/drivers/input/gyroscope/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gyroscope drivers configuration # diff --git a/drivers/input/gyroscope/Makefile b/drivers/input/gyroscope/Makefile old mode 100755 new mode 100644 index 710c9d10b9f8..430caef915d7 --- a/drivers/input/gyroscope/Makefile +++ b/drivers/input/gyroscope/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gyroscope drivers obj-$(CONFIG_GYRO_SENSOR_K3G) += k3g.o diff --git a/drivers/input/jogball/Kconfig b/drivers/input/jogball/Kconfig index 268ea38e0038..6765f06a304d 100644 --- a/drivers/input/jogball/Kconfig +++ b/drivers/input/jogball/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Touchscreen driver configuration # diff --git a/drivers/input/jogball/Makefile b/drivers/input/jogball/Makefile index db3864b57f5b..5dfec842a195 100644 --- a/drivers/input/jogball/Makefile +++ b/drivers/input/jogball/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the touchscreen drivers. # diff --git a/drivers/input/keyboard/synaptics_so340010.c b/drivers/input/keyboard/synaptics_so340010.c old mode 100755 new mode 100644 index cd607ee7c1fd..4e8013f25ab9 --- a/drivers/input/keyboard/synaptics_so340010.c +++ b/drivers/input/keyboard/synaptics_so340010.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/hannstar_Synaptics.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/lightsensor/Kconfig b/drivers/input/lightsensor/Kconfig index 4afb3a6c11df..92abd23bc134 100644 --- a/drivers/input/lightsensor/Kconfig +++ b/drivers/input/lightsensor/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gsensor drivers configuration # diff --git a/drivers/input/lightsensor/Makefile b/drivers/input/lightsensor/Makefile index fa05b856b9e5..62f67f0f22cf 100644 --- a/drivers/input/lightsensor/Makefile +++ b/drivers/input/lightsensor/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gsensor drivers obj-$(CONFIG_CM3202) += cm3202.o diff --git a/drivers/input/lightsensor/cm3202.c b/drivers/input/lightsensor/cm3202.c index 09536778e2c4..13375fc78dd1 100644 --- a/drivers/input/lightsensor/cm3202.c +++ b/drivers/input/lightsensor/cm3202.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/lightsensor/cm3217.c b/drivers/input/lightsensor/cm3217.c old mode 100755 new mode 100644 index 36fea403c6dc..61d9bb30f9dd --- a/drivers/input/lightsensor/cm3217.c +++ b/drivers/input/lightsensor/cm3217.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/lightsensor/rk29_lightsensor.c b/drivers/input/lightsensor/rk29_lightsensor.c index 77b1732daaa3..1fcc569c2c88 100644 --- a/drivers/input/lightsensor/rk29_lightsensor.c +++ b/drivers/input/lightsensor/rk29_lightsensor.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/lightsensor/us5151.c b/drivers/input/lightsensor/us5151.c index 6fd600929da2..51552f40faec 100644 --- a/drivers/input/lightsensor/us5151.c +++ b/drivers/input/lightsensor/us5151.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/magnetometer/Kconfig b/drivers/input/magnetometer/Kconfig old mode 100755 new mode 100644 index 89b356c7caba..fd4e66029d64 --- a/drivers/input/magnetometer/Kconfig +++ b/drivers/input/magnetometer/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Magnetometer sensors # diff --git a/drivers/input/magnetometer/Makefile b/drivers/input/magnetometer/Makefile old mode 100755 new mode 100644 index dfd09bfa3ea5..ecbb23867cd2 --- a/drivers/input/magnetometer/Makefile +++ b/drivers/input/magnetometer/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for industrial I/O Magnetometer sensors # diff --git a/drivers/input/magnetometer/ak8973.h b/drivers/input/magnetometer/ak8973.h old mode 100755 new mode 100644 index 350eba7dbe6c..6f5c1ce06515 --- a/drivers/input/magnetometer/ak8973.h +++ b/drivers/input/magnetometer/ak8973.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for ak8973 compass chip. */ diff --git a/drivers/input/magnetometer/ak8975.h b/drivers/input/magnetometer/ak8975.h old mode 100755 new mode 100644 index d26ba79d30c7..ba7f22a54d7b --- a/drivers/input/magnetometer/ak8975.h +++ b/drivers/input/magnetometer/ak8975.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for akm8975 compass chip. */ diff --git a/drivers/input/magnetometer/magnet.h b/drivers/input/magnetometer/magnet.h old mode 100755 new mode 100644 index 64338301f8df..b7a7dda1396e --- a/drivers/input/magnetometer/magnet.h +++ b/drivers/input/magnetometer/magnet.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "../sysfs.h" diff --git a/drivers/input/misc/rk_board_id.c b/drivers/input/misc/rk_board_id.c old mode 100755 new mode 100644 index f23cf4ac81a8..3a6e00d4d303 --- a/drivers/input/misc/rk_board_id.c +++ b/drivers/input/misc/rk_board_id.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/remotectl/Kconfig b/drivers/input/remotectl/Kconfig index 7879c6e538fc..b1c9364b3812 100644 --- a/drivers/input/remotectl/Kconfig +++ b/drivers/input/remotectl/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Input remotectl driver configuration # diff --git a/drivers/input/remotectl/Makefile b/drivers/input/remotectl/Makefile index f84b64131c0d..209472b4a356 100644 --- a/drivers/input/remotectl/Makefile +++ b/drivers/input/remotectl/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the input remotectl drivers. # diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.c b/drivers/input/remotectl/rockchip_pwm_remotectl.c index dd0faae58be5..15b04e3c9e01 100644 --- a/drivers/input/remotectl/rockchip_pwm_remotectl.c +++ b/drivers/input/remotectl/rockchip_pwm_remotectl.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.h b/drivers/input/remotectl/rockchip_pwm_remotectl.h index d1228d002db4..ed430d200606 100644 --- a/drivers/input/remotectl/rockchip_pwm_remotectl.h +++ b/drivers/input/remotectl/rockchip_pwm_remotectl.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKXX_PWM_REMOTECTL_H__ #define __RKXX_PWM_REMOTECTL_H__ diff --git a/drivers/input/sensors/Kconfig b/drivers/input/sensors/Kconfig old mode 100755 new mode 100644 index 1c46745b1492..ebff9437aa66 --- a/drivers/input/sensors/Kconfig +++ b/drivers/input/sensors/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # all sensors drivers configuration # diff --git a/drivers/input/sensors/Makefile b/drivers/input/sensors/Makefile old mode 100755 new mode 100644 index ffd165174928..58992e9aa320 --- a/drivers/input/sensors/Makefile +++ b/drivers/input/sensors/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # sensor drivers obj-$(CONFIG_ANGLE_DEVICE) += angle/ obj-$(CONFIG_GSENSOR_DEVICE) += accel/ diff --git a/drivers/input/sensors/accel/Kconfig b/drivers/input/sensors/accel/Kconfig old mode 100755 new mode 100644 index 2649ccb4b794..fe3d25e6ee71 --- a/drivers/input/sensors/accel/Kconfig +++ b/drivers/input/sensors/accel/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gsensor drivers configuration # diff --git a/drivers/input/sensors/accel/Makefile b/drivers/input/sensors/accel/Makefile old mode 100755 new mode 100644 index fbd981a9e0da..d42d4d5ad597 --- a/drivers/input/sensors/accel/Makefile +++ b/drivers/input/sensors/accel/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_GS_KXTIK) += kxtik.o obj-$(CONFIG_GS_KXTJ9) += kxtj9.o obj-$(CONFIG_GS_MMA8452) += mma8452.o diff --git a/drivers/input/sensors/angle/Kconfig b/drivers/input/sensors/angle/Kconfig old mode 100755 new mode 100644 index 9c09a48b7649..f773b6dee841 --- a/drivers/input/sensors/angle/Kconfig +++ b/drivers/input/sensors/angle/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gsensor drivers configuration # diff --git a/drivers/input/sensors/angle/Makefile b/drivers/input/sensors/angle/Makefile old mode 100755 new mode 100644 index bf01de256af8..0696550b53f8 --- a/drivers/input/sensors/angle/Makefile +++ b/drivers/input/sensors/angle/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o diff --git a/drivers/input/sensors/compass/Kconfig b/drivers/input/sensors/compass/Kconfig old mode 100755 new mode 100644 index 70f78149f6ce..2e4cc822963a --- a/drivers/input/sensors/compass/Kconfig +++ b/drivers/input/sensors/compass/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Magnetometer drivers configuration # diff --git a/drivers/input/sensors/compass/Makefile b/drivers/input/sensors/compass/Makefile old mode 100755 new mode 100644 index da43eb16d143..9c4072a35398 --- a/drivers/input/sensors/compass/Makefile +++ b/drivers/input/sensors/compass/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for industrial I/O Magnetometer sensors # diff --git a/drivers/input/sensors/gyro/Kconfig b/drivers/input/sensors/gyro/Kconfig old mode 100755 new mode 100644 index 481561061559..ae7d2754946c --- a/drivers/input/sensors/gyro/Kconfig +++ b/drivers/input/sensors/gyro/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gyroscope drivers configuration # diff --git a/drivers/input/sensors/gyro/Makefile b/drivers/input/sensors/gyro/Makefile old mode 100755 new mode 100644 index 09de32cac69f..f71fa56856cb --- a/drivers/input/sensors/gyro/Makefile +++ b/drivers/input/sensors/gyro/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gyroscope drivers obj-$(CONFIG_GYRO_SENSOR_K3G) += k3g.o diff --git a/drivers/input/sensors/hall/Kconfig b/drivers/input/sensors/hall/Kconfig index 8209d47a7ca5..25ba43c2f243 100644 --- a/drivers/input/sensors/hall/Kconfig +++ b/drivers/input/sensors/hall/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # hall sensor drivers configuration # diff --git a/drivers/input/sensors/hall/Makefile b/drivers/input/sensors/hall/Makefile index 54edebed4f6c..f78ba4ffb850 100644 --- a/drivers/input/sensors/hall/Makefile +++ b/drivers/input/sensors/hall/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_HS_OCH165T) += och165t_hall.o obj-$(CONFIG_HS_MH248) += mh248.o diff --git a/drivers/input/sensors/lsensor/Kconfig b/drivers/input/sensors/lsensor/Kconfig old mode 100755 new mode 100644 index 575b78551327..89cb8e1f7b1d --- a/drivers/input/sensors/lsensor/Kconfig +++ b/drivers/input/sensors/lsensor/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # light and position sensor drivers configuration # diff --git a/drivers/input/sensors/lsensor/Makefile b/drivers/input/sensors/lsensor/Makefile old mode 100755 new mode 100644 index bba2578ff792..44774f4f4dde --- a/drivers/input/sensors/lsensor/Makefile +++ b/drivers/input/sensors/lsensor/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gsensor drivers obj-$(CONFIG_LS_CM3217) += cm3217.o diff --git a/drivers/input/sensors/lsensor/ls_us5152.c b/drivers/input/sensors/lsensor/ls_us5152.c index d79234051590..93f09284b73d 100644 --- a/drivers/input/sensors/lsensor/ls_us5152.c +++ b/drivers/input/sensors/lsensor/ls_us5152.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/sensors/pressure/Kconfig b/drivers/input/sensors/pressure/Kconfig old mode 100755 new mode 100644 index c172f6dd84ab..9f95d9af77d8 --- a/drivers/input/sensors/pressure/Kconfig +++ b/drivers/input/sensors/pressure/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # pressure sensor drivers configuration # diff --git a/drivers/input/sensors/pressure/Makefile b/drivers/input/sensors/pressure/Makefile old mode 100755 new mode 100644 index 837fafa7d960..18872b53bb4b --- a/drivers/input/sensors/pressure/Makefile +++ b/drivers/input/sensors/pressure/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # pressure sensor drivers configuration # diff --git a/drivers/input/sensors/psensor/Kconfig b/drivers/input/sensors/psensor/Kconfig old mode 100755 new mode 100644 index df799aa117d6..38d107d0787f --- a/drivers/input/sensors/psensor/Kconfig +++ b/drivers/input/sensors/psensor/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # light and position sensor drivers configuration # diff --git a/drivers/input/sensors/psensor/Makefile b/drivers/input/sensors/psensor/Makefile old mode 100755 new mode 100644 index 33a1fcef45ea..3a2e2ff4f66d --- a/drivers/input/sensors/psensor/Makefile +++ b/drivers/input/sensors/psensor/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # gsensor drivers obj-$(CONFIG_PS_AL3006) += ps_al3006.o diff --git a/drivers/input/sensors/temperature/Kconfig b/drivers/input/sensors/temperature/Kconfig old mode 100755 new mode 100644 index cbb615b5424f..4553148011c4 --- a/drivers/input/sensors/temperature/Kconfig +++ b/drivers/input/sensors/temperature/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # temperature sensor drivers configuration # diff --git a/drivers/input/sensors/temperature/Makefile b/drivers/input/sensors/temperature/Makefile old mode 100755 new mode 100644 index 2f9f5efaa2f4..6045760d7e93 --- a/drivers/input/sensors/temperature/Makefile +++ b/drivers/input/sensors/temperature/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # temperature sensor drivers configuration # diff --git a/drivers/input/touchscreen/IT7260_ts.h b/drivers/input/touchscreen/IT7260_ts.h old mode 100755 new mode 100644 index eca2e3d9b56e..4532b088f1f5 --- a/drivers/input/touchscreen/IT7260_ts.h +++ b/drivers/input/touchscreen/IT7260_ts.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define MAX_BUFFER_SIZE 144 #define MAX_FINGER_NUMBER 3 #define MAX_PRESSURE 15 diff --git a/drivers/input/touchscreen/atmel_mxt224.c b/drivers/input/touchscreen/atmel_mxt224.c index fdf30867fb9f..a52e419e072e 100644 --- a/drivers/input/touchscreen/atmel_mxt224.c +++ b/drivers/input/touchscreen/atmel_mxt224.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/atmel_mxt224.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/touchscreen/byd693x_ts.c b/drivers/input/touchscreen/byd693x_ts.c index f3522f94bff4..663c2e831718 100644 --- a/drivers/input/touchscreen/byd693x_ts.c +++ b/drivers/input/touchscreen/byd693x_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/input/touchscreen/byd693x_ts.h b/drivers/input/touchscreen/byd693x_ts.h index d176772c4155..c3ce68cada51 100644 --- a/drivers/input/touchscreen/byd693x_ts.h +++ b/drivers/input/touchscreen/byd693x_ts.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //a4, 52 #define MAX_TOUCH_MAJOR 10 //Charles added #define MAX_WIDTH_MAJOR 15 //Charles added diff --git a/drivers/input/touchscreen/calib_iface_ts.c b/drivers/input/touchscreen/calib_iface_ts.c old mode 100755 new mode 100644 index d67502b2f371..e7da932ec062 --- a/drivers/input/touchscreen/calib_iface_ts.c +++ b/drivers/input/touchscreen/calib_iface_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Export interface in /sys/class/touchpanel for calibration. * diff --git a/drivers/input/touchscreen/ct360_calib.h b/drivers/input/touchscreen/ct360_calib.h index 5f800384e324..b780d78a9156 100644 --- a/drivers/input/touchscreen/ct360_calib.h +++ b/drivers/input/touchscreen/ct360_calib.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ struct ct36x_i2c_data { unsigned char buf[32]; diff --git a/drivers/input/touchscreen/ct360_ch.h b/drivers/input/touchscreen/ct360_ch.h index 55604c700e97..b8d4c1ece29b 100644 --- a/drivers/input/touchscreen/ct360_ch.h +++ b/drivers/input/touchscreen/ct360_ch.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ static char Binary_Data [16384] = { 0x00,0x02,0x2E,0x26,0xD2,0x0B,0x32,0x32,0x32,0x32,0x00,0x02,0x00,0x04,0x00,0x00, diff --git a/drivers/input/touchscreen/ct36x/Kconfig b/drivers/input/touchscreen/ct36x/Kconfig index 335cff4f7402..0d1b8088be01 100644 --- a/drivers/input/touchscreen/ct36x/Kconfig +++ b/drivers/input/touchscreen/ct36x/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Adc hardware configuration # diff --git a/drivers/input/touchscreen/ct36x/Makefile b/drivers/input/touchscreen/ct36x/Makefile index bcebcb0ca072..bf5c701bc5e6 100644 --- a/drivers/input/touchscreen/ct36x/Makefile +++ b/drivers/input/touchscreen/ct36x/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CT36X_TS) += ct36x_ts.o diff --git a/drivers/input/touchscreen/ct36x/core.c b/drivers/input/touchscreen/ct36x/core.c old mode 100755 new mode 100644 index 66fca4cc4032..c24961130f73 --- a/drivers/input/touchscreen/ct36x/core.c +++ b/drivers/input/touchscreen/ct36x/core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "ct36x_priv.h" /* diff --git a/drivers/input/touchscreen/ct36x/ct360.c b/drivers/input/touchscreen/ct36x/ct360.c index e6f8952fd538..e4368b573110 100644 --- a/drivers/input/touchscreen/ct36x/ct360.c +++ b/drivers/input/touchscreen/ct36x/ct360.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ struct ct36x_ops ct360_ops = { }; diff --git a/drivers/input/touchscreen/ct36x/ct363.c b/drivers/input/touchscreen/ct36x/ct363.c old mode 100755 new mode 100644 index 5b57be34f312..2060667c0cdc --- a/drivers/input/touchscreen/ct36x/ct363.c +++ b/drivers/input/touchscreen/ct36x/ct363.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define CT363_POINT_NUM 10 struct ct363_finger_data { diff --git a/drivers/input/touchscreen/ct36x/ct36x_priv.h b/drivers/input/touchscreen/ct36x/ct36x_priv.h old mode 100755 new mode 100644 index 149105771565..2d60fbbdbb61 --- a/drivers/input/touchscreen/ct36x/ct36x_priv.h +++ b/drivers/input/touchscreen/ct36x/ct36x_priv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CT36X_PRIV__ #define __CT36X_PRIV__ diff --git a/drivers/input/touchscreen/ct36x/ct36x_ts.c b/drivers/input/touchscreen/ct36x/ct36x_ts.c old mode 100755 new mode 100644 index 4795854bb5c6..05061a406d81 --- a/drivers/input/touchscreen/ct36x/ct36x_ts.c +++ b/drivers/input/touchscreen/ct36x/ct36x_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "ct36x_priv.h" #include #include diff --git a/drivers/input/touchscreen/ct36x_ts/Kconfig b/drivers/input/touchscreen/ct36x_ts/Kconfig index 1fa974db454e..dcfcefbac9d5 100644 --- a/drivers/input/touchscreen/ct36x_ts/Kconfig +++ b/drivers/input/touchscreen/ct36x_ts/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Touchscreen driver configuration # diff --git a/drivers/input/touchscreen/ct36x_ts/Makefile b/drivers/input/touchscreen/ct36x_ts/Makefile index fec959cc29c4..82977b9def11 100644 --- a/drivers/input/touchscreen/ct36x_ts/Makefile +++ b/drivers/input/touchscreen/ct36x_ts/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the touchscreen drivers. # diff --git a/drivers/input/touchscreen/ct36x_ts/allwinner.c b/drivers/input/touchscreen/ct36x_ts/allwinner.c index bdf4b7af7376..8734c69f8640 100644 --- a/drivers/input/touchscreen/ct36x_ts/allwinner.c +++ b/drivers/input/touchscreen/ct36x_ts/allwinner.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/input/touchscreen/ct36x_ts/chip.h b/drivers/input/touchscreen/ct36x_ts/chip.h index 495ef13c298d..3db5acb78646 100644 --- a/drivers/input/touchscreen/ct36x_ts/chip.h +++ b/drivers/input/touchscreen/ct36x_ts/chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef CHIP_H #define CHIP_H diff --git a/drivers/input/touchscreen/ct36x_ts/ct360.c b/drivers/input/touchscreen/ct36x_ts/ct360.c index 13e18b05e3e5..8be0a080a2b2 100644 --- a/drivers/input/touchscreen/ct36x_ts/ct360.c +++ b/drivers/input/touchscreen/ct36x_ts/ct360.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/input/touchscreen/ct36x_ts/ct360.h b/drivers/input/touchscreen/ct36x_ts/ct360.h index 24b6117acd58..e31f7b5aa4b4 100644 --- a/drivers/input/touchscreen/ct36x_ts/ct360.h +++ b/drivers/input/touchscreen/ct36x_ts/ct360.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef CT360_H #define CT360_H diff --git a/drivers/input/touchscreen/ct36x_ts/ct365.c b/drivers/input/touchscreen/ct36x_ts/ct365.c index f9f4b95c8dae..7a9c12a19550 100644 --- a/drivers/input/touchscreen/ct36x_ts/ct365.c +++ b/drivers/input/touchscreen/ct36x_ts/ct365.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/input/touchscreen/ct36x_ts/ct365.h b/drivers/input/touchscreen/ct36x_ts/ct365.h index b120bb6a37b2..67281a9fe7f0 100644 --- a/drivers/input/touchscreen/ct36x_ts/ct365.h +++ b/drivers/input/touchscreen/ct36x_ts/ct365.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef CT365_H #define CT365_H diff --git a/drivers/input/touchscreen/ct36x_ts/generic.c b/drivers/input/touchscreen/ct36x_ts/generic.c index 8180ffe835e9..b44281ec1183 100644 --- a/drivers/input/touchscreen/ct36x_ts/generic.c +++ b/drivers/input/touchscreen/ct36x_ts/generic.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/input/touchscreen/ct36x_ts/generic.h b/drivers/input/touchscreen/ct36x_ts/generic.h index 9d6e1d7adc51..463413319fd1 100644 --- a/drivers/input/touchscreen/ct36x_ts/generic.h +++ b/drivers/input/touchscreen/ct36x_ts/generic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef GENERIC_H #define GENERIC_H diff --git a/drivers/input/touchscreen/ct36x_ts/platform.h b/drivers/input/touchscreen/ct36x_ts/platform.h index d7af54820555..31e76cabc35f 100644 --- a/drivers/input/touchscreen/ct36x_ts/platform.h +++ b/drivers/input/touchscreen/ct36x_ts/platform.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef PLATFORM_H #define PLATFORM_H diff --git a/drivers/input/touchscreen/ct36x_ts/rockchip.c b/drivers/input/touchscreen/ct36x_ts/rockchip.c index fe679f839296..d82d6f0840c2 100644 --- a/drivers/input/touchscreen/ct36x_ts/rockchip.c +++ b/drivers/input/touchscreen/ct36x_ts/rockchip.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/input/touchscreen/ct36x_ts/rockchip.h b/drivers/input/touchscreen/ct36x_ts/rockchip.h index 827d04944a04..5319282432ab 100644 --- a/drivers/input/touchscreen/ct36x_ts/rockchip.h +++ b/drivers/input/touchscreen/ct36x_ts/rockchip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef ROCKCHIP_H #define ROCKCHIP_H diff --git a/drivers/input/touchscreen/ct36x_ts/tscore.h b/drivers/input/touchscreen/ct36x_ts/tscore.h index 2f0afd2009a6..f1dab79c51a7 100644 --- a/drivers/input/touchscreen/ct36x_ts/tscore.h +++ b/drivers/input/touchscreen/ct36x_ts/tscore.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef TSCORE_H #define TSCORE_H diff --git a/drivers/input/touchscreen/ctp_it7250.c b/drivers/input/touchscreen/ctp_it7250.c old mode 100755 new mode 100644 index c4b832eaa50b..38f542b9d57b --- a/drivers/input/touchscreen/ctp_it7250.c +++ b/drivers/input/touchscreen/ctp_it7250.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/touchscreen/ft5506_wgj.h b/drivers/input/touchscreen/ft5506_wgj.h index 66166b69b43e..cfcdb4a12e9c 100644 --- a/drivers/input/touchscreen/ft5506_wgj.h +++ b/drivers/input/touchscreen/ft5506_wgj.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_FT5X0X_TS_H__ #define __LINUX_FT5X0X_TS_H__ diff --git a/drivers/input/touchscreen/ft5x0x.c b/drivers/input/touchscreen/ft5x0x.c old mode 100755 new mode 100644 index c2335cf37ad6..a4e8fd760cff --- a/drivers/input/touchscreen/ft5x0x.c +++ b/drivers/input/touchscreen/ft5x0x.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/touchscreen/ft5x0x_i2c_ts.h b/drivers/input/touchscreen/ft5x0x_i2c_ts.h old mode 100755 new mode 100644 index d15c8cf908d4..1454ede3dd97 --- a/drivers/input/touchscreen/ft5x0x_i2c_ts.h +++ b/drivers/input/touchscreen/ft5x0x_i2c_ts.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_FT5X0X_TS_H__ #define __LINUX_FT5X0X_TS_H__ diff --git a/drivers/input/touchscreen/goodix_touch.c b/drivers/input/touchscreen/goodix_touch.c old mode 100755 new mode 100644 index 57797bbd45f2..a4213c8c992c --- a/drivers/input/touchscreen/goodix_touch.c +++ b/drivers/input/touchscreen/goodix_touch.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*--------------------------------------------------------------------------------------------------------- * driver/input/touchscreen/goodix_touch.c * diff --git a/drivers/input/touchscreen/goodix_touch_82x.c b/drivers/input/touchscreen/goodix_touch_82x.c old mode 100755 new mode 100644 index 8012a3db48e5..459e273a3c89 --- a/drivers/input/touchscreen/goodix_touch_82x.c +++ b/drivers/input/touchscreen/goodix_touch_82x.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * * Copyright (C) 2011 Goodix, Inc. diff --git a/drivers/input/touchscreen/goodix_touch_82x_760.c b/drivers/input/touchscreen/goodix_touch_82x_760.c old mode 100755 new mode 100644 index b28836a4e060..958653dffb1e --- a/drivers/input/touchscreen/goodix_touch_82x_760.c +++ b/drivers/input/touchscreen/goodix_touch_82x_760.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * * Copyright (C) 2011 Goodix, Inc. diff --git a/drivers/input/touchscreen/gslx680_d708/Makefile b/drivers/input/touchscreen/gslx680_d708/Makefile index f9fcf7e095ed..86d995c5e6c5 100644 --- a/drivers/input/touchscreen/gslx680_d708/Makefile +++ b/drivers/input/touchscreen/gslx680_d708/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the touchscreen drivers. # diff --git a/drivers/input/touchscreen/gslx680_pad.h b/drivers/input/touchscreen/gslx680_pad.h index 839c57deb1ba..528beac4c6d8 100644 --- a/drivers/input/touchscreen/gslx680_pad.h +++ b/drivers/input/touchscreen/gslx680_pad.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _GSLX680_H_ #define _GSLX680_H_ diff --git a/drivers/input/touchscreen/gt9xx/Makefile b/drivers/input/touchscreen/gt9xx/Makefile index 691b0d98e7a1..f63b5f2783a5 100644 --- a/drivers/input/touchscreen/gt9xx/Makefile +++ b/drivers/input/touchscreen/gt9xx/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-y += goodix_gt9xx.o #goodix_gt9xx-y +=goodix_tool.o diff --git a/drivers/input/touchscreen/hannstar_p1003.c b/drivers/input/touchscreen/hannstar_p1003.c old mode 100755 new mode 100644 index a4ba8cac958c..b03b8c39e269 --- a/drivers/input/touchscreen/hannstar_p1003.c +++ b/drivers/input/touchscreen/hannstar_p1003.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/hannstar_p1003.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/touchscreen/ili2102_ts.c b/drivers/input/touchscreen/ili2102_ts.c old mode 100755 new mode 100644 index d898fe496830..c8e1639fd58f --- a/drivers/input/touchscreen/ili2102_ts.c +++ b/drivers/input/touchscreen/ili2102_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/touchscreen/it7260_ts.c b/drivers/input/touchscreen/it7260_ts.c index ad5d9535fbd3..d210e63a63e2 100644 --- a/drivers/input/touchscreen/it7260_ts.c +++ b/drivers/input/touchscreen/it7260_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/i2cpca955x.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/touchscreen/nas_ts.c b/drivers/input/touchscreen/nas_ts.c old mode 100755 new mode 100644 index a118c4e60cb5..d0804332349a --- a/drivers/input/touchscreen/nas_ts.c +++ b/drivers/input/touchscreen/nas_ts.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/hannstar_nas.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.h b/drivers/input/touchscreen/pixcir_i2c_ts.h index e19773eee24b..ec72b7cba669 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.h +++ b/drivers/input/touchscreen/pixcir_i2c_ts.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DRIVERS_TOUCHSCREEN_PIXCIR_TS_H #define __DRIVERS_TOUCHSCREEN_PIXCIR_TS_H diff --git a/drivers/input/touchscreen/rk3028_gslX680_86v.h b/drivers/input/touchscreen/rk3028_gslX680_86v.h old mode 100755 new mode 100644 index 93c410da090c..38aff8f516f7 --- a/drivers/input/touchscreen/rk3028_gslX680_86v.h +++ b/drivers/input/touchscreen/rk3028_gslX680_86v.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _GSLX680_H_ #define _GSLX680_H_ diff --git a/drivers/input/touchscreen/rk_tp.c b/drivers/input/touchscreen/rk_tp.c old mode 100755 new mode 100644 index bf4fc7724967..8a37b127f994 --- a/drivers/input/touchscreen/rk_tp.c +++ b/drivers/input/touchscreen/rk_tp.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/touchscreen/rmi4/Kconfig b/drivers/input/touchscreen/rmi4/Kconfig old mode 100755 new mode 100644 index 3adf21d3c9eb..5b54d71fbb8e --- a/drivers/input/touchscreen/rmi4/Kconfig +++ b/drivers/input/touchscreen/rmi4/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # RMI4 configuration # diff --git a/drivers/input/touchscreen/rmi4/Makefile b/drivers/input/touchscreen/rmi4/Makefile old mode 100755 new mode 100644 index 81db85bb8295..562f672265bd --- a/drivers/input/touchscreen/rmi4/Makefile +++ b/drivers/input/touchscreen/rmi4/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RMI4_BUS) += rmi_bus.o obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o obj-$(CONFIG_RMI4_SPI) += rmi_spi.o diff --git a/drivers/input/touchscreen/rmi4/rmi_reflash.h b/drivers/input/touchscreen/rmi4/rmi_reflash.h index 131baf198c22..aa5121361894 100644 --- a/drivers/input/touchscreen/rmi4/rmi_reflash.h +++ b/drivers/input/touchscreen/rmi4/rmi_reflash.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ unsigned char SynaFirmware[46592] = { 0x9F, 0x45, 0x60, 0x37, 0x00, 0x00, 0x00, 0x05, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, diff --git a/drivers/input/touchscreen/rockchip_gslX680.h b/drivers/input/touchscreen/rockchip_gslX680.h index 835e85adc014..a0266fa441cd 100644 --- a/drivers/input/touchscreen/rockchip_gslX680.h +++ b/drivers/input/touchscreen/rockchip_gslX680.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _GSLX680_H_ #define _GSLX680_H_ diff --git a/drivers/input/touchscreen/rockchip_gslX680_rk3128.h b/drivers/input/touchscreen/rockchip_gslX680_rk3128.h old mode 100755 new mode 100644 index 51e02f29104f..1be4314acb9f --- a/drivers/input/touchscreen/rockchip_gslX680_rk3128.h +++ b/drivers/input/touchscreen/rockchip_gslX680_rk3128.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _GSLX680_H_ #define _GSLX680_H_ diff --git a/drivers/input/touchscreen/rockchip_gslX680_rk3168.h b/drivers/input/touchscreen/rockchip_gslX680_rk3168.h old mode 100755 new mode 100644 index 93c410da090c..38aff8f516f7 --- a/drivers/input/touchscreen/rockchip_gslX680_rk3168.h +++ b/drivers/input/touchscreen/rockchip_gslX680_rk3168.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _GSLX680_H_ #define _GSLX680_H_ diff --git a/drivers/input/touchscreen/sintek_3FA16.c b/drivers/input/touchscreen/sintek_3FA16.c old mode 100755 new mode 100644 index 50b34a2ce616..6bc12ebbbfdb --- a/drivers/input/touchscreen/sintek_3FA16.c +++ b/drivers/input/touchscreen/sintek_3FA16.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** * driver/input/touchscreen/hannstar_p1003.c *Copyright :ROCKCHIP Inc diff --git a/drivers/input/touchscreen/tp_suspend.h b/drivers/input/touchscreen/tp_suspend.h index b900ee530a2a..c0f1c4f0d088 100644 --- a/drivers/input/touchscreen/tp_suspend.h +++ b/drivers/input/touchscreen/tp_suspend.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * TP suspend Control Abstraction * diff --git a/drivers/input/touchscreen/ts_lib/Makefile b/drivers/input/touchscreen/ts_lib/Makefile old mode 100755 new mode 100644 index 39e40c4ab3c9..3a8139a048b8 --- a/drivers/input/touchscreen/ts_lib/Makefile +++ b/drivers/input/touchscreen/ts_lib/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-y += tslib.o variance.o dejitter.o \ No newline at end of file diff --git a/drivers/input/touchscreen/vtl_ts/Makefile b/drivers/input/touchscreen/vtl_ts/Makefile old mode 100755 new mode 100644 index 70b38e6614aa..0d15d7471f7f --- a/drivers/input/touchscreen/vtl_ts/Makefile +++ b/drivers/input/touchscreen/vtl_ts/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TOUCHSCREEN_VTL_CT36X) += vtl_ts_ct36x.o #obj-y += vtl_ts_ct36x.o diff --git a/drivers/input/touchscreen/vtl_ts/apk.c b/drivers/input/touchscreen/vtl_ts/apk.c index e087dbca3ddb..44db1086d264 100644 --- a/drivers/input/touchscreen/vtl_ts/apk.c +++ b/drivers/input/touchscreen/vtl_ts/apk.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/input/touchscreen/vtl_ts/apk.h b/drivers/input/touchscreen/vtl_ts/apk.h old mode 100755 new mode 100644 index c62752635cdf..a0a14b6b3cc8 --- a/drivers/input/touchscreen/vtl_ts/apk.h +++ b/drivers/input/touchscreen/vtl_ts/apk.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _APK_H_ #define _APK_H_ diff --git a/drivers/input/touchscreen/vtl_ts/chip.c b/drivers/input/touchscreen/vtl_ts/chip.c index 6140983b264a..50004cef1f0c 100644 --- a/drivers/input/touchscreen/vtl_ts/chip.c +++ b/drivers/input/touchscreen/vtl_ts/chip.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/input/touchscreen/vtl_ts/chip.h b/drivers/input/touchscreen/vtl_ts/chip.h old mode 100755 new mode 100644 index 3ce237a23130..5ebb121276ed --- a/drivers/input/touchscreen/vtl_ts/chip.h +++ b/drivers/input/touchscreen/vtl_ts/chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _CHIP_H_ #define _CHIP_H_ diff --git a/drivers/input/touchscreen/vtl_ts/tp_fw.h b/drivers/input/touchscreen/vtl_ts/tp_fw.h index aef83916a330..df431fcabca8 100644 --- a/drivers/input/touchscreen/vtl_ts/tp_fw.h +++ b/drivers/input/touchscreen/vtl_ts/tp_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ static unsigned char tp_fw[] = { 0x02, 0x48, 0xA5, 0x02, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4D, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3D, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3D, 0xFF, 0x00, 0x00, diff --git a/drivers/input/touchscreen/vtl_ts/vtl_ts.h b/drivers/input/touchscreen/vtl_ts/vtl_ts.h old mode 100755 new mode 100644 index 35100bf96725..95e280688d74 --- a/drivers/input/touchscreen/vtl_ts/vtl_ts.h +++ b/drivers/input/touchscreen/vtl_ts/vtl_ts.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TS_CORE_H_ #define _TS_CORE_H_ diff --git a/drivers/input/touchscreen/zet62xx/Makefile b/drivers/input/touchscreen/zet62xx/Makefile old mode 100755 new mode 100644 index 0224d4defd1a..1607452edc70 --- a/drivers/input/touchscreen/zet62xx/Makefile +++ b/drivers/input/touchscreen/zet62xx/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TOUCHSCREEN_ZET62XX) += zet62xx.o diff --git a/drivers/input/touchscreen/zet62xx/zet6221_fw.h b/drivers/input/touchscreen/zet62xx/zet6221_fw.h old mode 100755 new mode 100644 index e73ec4804954..168a5489a0f2 --- a/drivers/input/touchscreen/zet62xx/zet6221_fw.h +++ b/drivers/input/touchscreen/zet62xx/zet6221_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 00 - 34 - 02 - 08 - 00 - 13 - 07 - 30 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h b/drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h old mode 100755 new mode 100644 index d5c1d48e6f45..5c1f31e9a85a --- a/drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h +++ b/drivers/input/touchscreen/zet62xx/zet6221_fw_rk3026_w7.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 12 - 08 - 00 - 00 - 00 - 03 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6223_fw.h b/drivers/input/touchscreen/zet62xx/zet6223_fw.h old mode 100755 new mode 100644 index ecab25f47338..1a1ef063da35 --- a/drivers/input/touchscreen/zet62xx/zet6223_fw.h +++ b/drivers/input/touchscreen/zet62xx/zet6223_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 04 - 30 - 29 - 08 - 1D - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h old mode 100755 new mode 100644 index 6219521dae5c..655aa627e0a1 --- a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h +++ b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w10.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 04 - 30 - 29 - 08 - 1D - 0A - 00 - 01 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h old mode 100755 new mode 100644 index ecab25f47338..1a1ef063da35 --- a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h +++ b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w8.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 04 - 30 - 29 - 08 - 1D - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h old mode 100755 new mode 100644 index 058439021b07..edfe356aac5c --- a/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h +++ b/drivers/input/touchscreen/zet62xx/zet6223_fw_rk3026_w9.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 04 - 30 - 29 - 08 - 1D - 09 - 00 - 02 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6231_fw.h b/drivers/input/touchscreen/zet62xx/zet6231_fw.h old mode 100755 new mode 100644 index c4b018ccba49..bef527c9e43d --- a/drivers/input/touchscreen/zet62xx/zet6231_fw.h +++ b/drivers/input/touchscreen/zet62xx/zet6231_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0B - 01 - 0C - 08 - 00 - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw.h b/drivers/input/touchscreen/zet62xx/zet6251_fw.h old mode 100755 new mode 100644 index db4ee5d61018..2357d52525e7 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 1C - 08 - 00 - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h old mode 100755 new mode 100644 index 2278af34c2b2..d2229396ca62 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_bt.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 0E - 01 - 14 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h old mode 100755 new mode 100644 index 63f37be06166..c47a82d19aaa --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v41.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 00 - 00 - 0D ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h old mode 100755 new mode 100644 index aeb04cc9515c..4e4156ee2f03 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v42.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 3A - 08 - 00 - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h old mode 100755 new mode 100644 index 2278af34c2b2..d2229396ca62 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v5.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 0E - 01 - 14 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h old mode 100755 new mode 100644 index 2278af34c2b2..d2229396ca62 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47_v52.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 0E - 01 - 14 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h old mode 100755 new mode 100644 index aeb04cc9515c..4e4156ee2f03 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_ak47h_v20.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 3A - 08 - 00 - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h old mode 100755 new mode 100644 index 9f781677e855..b7b3a2826acb --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v41.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 26 - 08 - 00 - 00 - 00 - 0D ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h old mode 100755 new mode 100644 index 2278af34c2b2..d2229396ca62 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v5.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 0E - 01 - 14 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h old mode 100755 new mode 100644 index 9f781677e855..b7b3a2826acb --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_b52_v52.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 26 - 08 - 00 - 00 - 00 - 0D ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h old mode 100755 new mode 100644 index d5c1d48e6f45..5c1f31e9a85a --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_86v_bt.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 12 - 08 - 00 - 00 - 00 - 03 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h old mode 100755 new mode 100644 index 5bd7e1119e87..d1f059969102 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_th785.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 00 - 00 - 00 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h old mode 100755 new mode 100644 index d5c1d48e6f45..5c1f31e9a85a --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_rk3026_w7.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 12 - 08 - 00 - 00 - 00 - 03 ///====================================================================== diff --git a/drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h b/drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h old mode 100755 new mode 100644 index 28c55a024914..bef9eb356880 --- a/drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h +++ b/drivers/input/touchscreen/zet62xx/zet6251_fw_th71.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ ///====================================================================== /// PROJECT CODE[] = 0C - 01 - 29 - 08 - 00 - 0E - 01 - 14 ///====================================================================== diff --git a/drivers/input/ts/Kconfig b/drivers/input/ts/Kconfig old mode 100755 new mode 100644 index 314a0aab9fac..ca184e2d04e6 --- a/drivers/input/ts/Kconfig +++ b/drivers/input/ts/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # all auto touch screen drivers configuration # diff --git a/drivers/input/ts/Makefile b/drivers/input/ts/Makefile old mode 100755 new mode 100644 index f13cb4a8c733..da734f0c0e2b --- a/drivers/input/ts/Makefile +++ b/drivers/input/ts/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # auto touch screen drivers obj-$(CONFIG_TS_AUTO_I2C) += ts-i2c.o obj-$(CONFIG_TS_AUTO_SPI) += ts-spi.o diff --git a/drivers/input/ts/chips/Kconfig b/drivers/input/ts/chips/Kconfig old mode 100755 new mode 100644 index acdaa0aebc77..e310d77e641e --- a/drivers/input/ts/chips/Kconfig +++ b/drivers/input/ts/chips/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig TS_AUTO_I2C bool "Support auto touch screen with I2C" default n diff --git a/drivers/input/ts/chips/Makefile b/drivers/input/ts/chips/Makefile old mode 100755 new mode 100644 index 8dda843c195e..435ac4a35033 --- a/drivers/input/ts/chips/Makefile +++ b/drivers/input/ts/chips/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TS_FT5306) += ft5306.o obj-$(CONFIG_TS_GT8110) += gt8110.o obj-$(CONFIG_TS_CT360) += ct360.o diff --git a/drivers/input/ts/chips/ct360_firmware.h b/drivers/input/ts/chips/ct360_firmware.h old mode 100755 new mode 100644 index 43f574a35c22..8905f1e40ffc --- a/drivers/input/ts/chips/ct360_firmware.h +++ b/drivers/input/ts/chips/ct360_firmware.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ static char Binary_Data_Ct360 [16384] = { 0x00,0x02,0x2E,0x26,0xD2,0x0B,0x32,0x32,0x32,0x32,0x00,0x02,0x00,0x04,0x00,0x00, diff --git a/drivers/input/ts/ts-serial.c b/drivers/input/ts/ts-serial.c old mode 100755 new mode 100644 index 267e9b7b18d3..4df52c1de85b --- a/drivers/input/ts/ts-serial.c +++ b/drivers/input/ts/ts-serial.c @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //to do diff --git a/drivers/input/ts/ts-spi.c b/drivers/input/ts/ts-spi.c old mode 100755 new mode 100644 index 267e9b7b18d3..4df52c1de85b --- a/drivers/input/ts/ts-spi.c +++ b/drivers/input/ts/ts-spi.c @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //to do diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig index 43428cec3a01..24877562054c 100644 --- a/drivers/media/cec/Kconfig +++ b/drivers/media/cec/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config MEDIA_CEC_RC bool "HDMI CEC RC integration" depends on CEC_CORE && RC_CORE diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile index 3353c1741961..41ee3325e1ea 100644 --- a/drivers/media/cec/Makefile +++ b/drivers/media/cec/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o ifeq ($(CONFIG_CEC_NOTIFIER),y) diff --git a/drivers/media/i2c/soc_camera/rockchip/Kconfig b/drivers/media/i2c/soc_camera/rockchip/Kconfig index 89789052b502..9572f4fc6937 100644 --- a/drivers/media/i2c/soc_camera/rockchip/Kconfig +++ b/drivers/media/i2c/soc_camera/rockchip/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config VIDEO_OV8858 tristate "ov8858 driver adapt to rockchip cif isp platform" depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C diff --git a/drivers/media/i2c/soc_camera/rockchip/Makefile b/drivers/media/i2c/soc_camera/rockchip/Makefile index 5a0546cc8d2f..0e7ffbd16e73 100644 --- a/drivers/media/i2c/soc_camera/rockchip/Makefile +++ b/drivers/media/i2c/soc_camera/rockchip/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_OV8858) += ov_camera_module.o rk_camera_module.o ov8858_v4l2-i2c-subdev.o obj-$(CONFIG_VIDEO_OV2710) += ov_camera_module.o rk_camera_module.o ov2710_v4l2-i2c-subdev.o obj-$(CONFIG_VIDEO_OV4689) += ov_camera_module.o rk_camera_module.o ov4689_v4l2-i2c-subdev.o diff --git a/drivers/media/platform/rk-isp10/Kconfig b/drivers/media/platform/rk-isp10/Kconfig index a51aac2410a2..1b25033d6fce 100644 --- a/drivers/media/platform/rk-isp10/Kconfig +++ b/drivers/media/platform/rk-isp10/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config VIDEO_RK_CIF_ISP10 tristate "Rockchip cif isp10 camera sensors" depends on VIDEO_V4L2 && I2C diff --git a/drivers/media/platform/rk-isp10/Makefile b/drivers/media/platform/rk-isp10/Makefile index 9caf7f94e771..8f760f4a0771 100644 --- a/drivers/media/platform/rk-isp10/Makefile +++ b/drivers/media/platform/rk-isp10/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_RK_CIF_ISP10) += video_cif_isp10.o video_cif_isp10-objs += cif_isp10.o cif_isp10_img_src.o cif_isp10_img_src_v4l2-subdev.o cif_isp10_isp.o cif_isp10_pltfrm.o cif_isp10_rk3288.o cif_isp10_rk3399.o cif_isp10_v4l2.o \ No newline at end of file diff --git a/drivers/media/platform/rockchip-vpu/Makefile b/drivers/media/platform/rockchip-vpu/Makefile index e41269b736dd..b0429e660d36 100644 --- a/drivers/media/platform/rockchip-vpu/Makefile +++ b/drivers/media/platform/rockchip-vpu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_ROCKCHIP_VPU) += rockchip-vpu.o diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile index 18af64853734..0412e837cafa 100644 --- a/drivers/media/platform/rockchip/isp1/Makefile +++ b/drivers/media/platform/rockchip/isp1/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += video_rkisp1.o video_rkisp1-objs += rkisp1.o \ dev.o \ diff --git a/drivers/media/platform/rockchip/rga/Makefile b/drivers/media/platform/rockchip/rga/Makefile index 92fe25490ccd..c37ff6e531c7 100644 --- a/drivers/media/platform/rockchip/rga/Makefile +++ b/drivers/media/platform/rockchip/rga/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 rockchip-rga-objs := rga.o rga-hw.o rga-buf.o obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 19d3e88c1833..59c68f725690 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config ROCK_CHIP_SOC_CAMERA tristate "rockchip supported soc cameras " default n diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 5183702accdb..06075cd80629 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK30_CAMERA_PINGPONG) += rk30_camera_pingpong.o generic_sensor.o \ gc0307.o \ gc0308.o \ diff --git a/drivers/media/video/gc0308_user_series.c b/drivers/media/video/gc0308_user_series.c index 3cd76d86e8cc..6a33467f0b43 100644 --- a/drivers/media/video/gc0308_user_series.c +++ b/drivers/media/video/gc0308_user_series.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if defined(CONFIG_MACH_RK30_PHONE_PAD) diff --git a/drivers/media/video/gt2005_user_series.c b/drivers/media/video/gt2005_user_series.c index 26cbe92173e7..41a3fa1f2f03 100644 --- a/drivers/media/video/gt2005_user_series.c +++ b/drivers/media/video/gt2005_user_series.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if defined(CONFIG_MACH_RK30_PHONE_PAD) /* init 352X288 SVGA */ diff --git a/drivers/media/video/hm5065.h b/drivers/media/video/hm5065.h old mode 100755 new mode 100644 index 4b53839e1d27..9cc20a727c51 --- a/drivers/media/video/hm5065.h +++ b/drivers/media/video/hm5065.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HM5065_H__ #define __HM5065_H__ diff --git a/drivers/media/video/mv9335/Kconfig b/drivers/media/video/mv9335/Kconfig old mode 100755 new mode 100644 index 5ffe46aa6172..6d0981dd846b --- a/drivers/media/video/mv9335/Kconfig +++ b/drivers/media/video/mv9335/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Fujitsu camera isp chip: m6moj. # diff --git a/drivers/media/video/mv9335/Makefile b/drivers/media/video/mv9335/Makefile old mode 100755 new mode 100644 index cde0ceb85daa..4ece962a39b5 --- a/drivers/media/video/mv9335/Makefile +++ b/drivers/media/video/mv9335/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for Fujitsu isp driver # diff --git a/drivers/media/video/mv9335/mv9335.c b/drivers/media/video/mv9335/mv9335.c old mode 100755 new mode 100644 index cfc49b710a31..70efb0a737f9 --- a/drivers/media/video/mv9335/mv9335.c +++ b/drivers/media/video/mv9335/mv9335.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/media/video/nt99252_3way.c b/drivers/media/video/nt99252_3way.c old mode 100755 new mode 100644 index 4b77492af356..f371abadf75c --- a/drivers/media/video/nt99252_3way.c +++ b/drivers/media/video/nt99252_3way.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "generic_sensor.h" /* diff --git a/drivers/media/video/nt99340_2way.c b/drivers/media/video/nt99340_2way.c old mode 100755 new mode 100644 index b5445372cdee..0c380b6e49f9 --- a/drivers/media/video/nt99340_2way.c +++ b/drivers/media/video/nt99340_2way.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "generic_sensor.h" /* diff --git a/drivers/media/video/ov2640_rk.c b/drivers/media/video/ov2640_rk.c old mode 100755 new mode 100644 index 0229d657090d..f2c27944878f --- a/drivers/media/video/ov2640_rk.c +++ b/drivers/media/video/ov2640_rk.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/media/video/ov5640.h b/drivers/media/video/ov5640.h old mode 100755 new mode 100644 index 3592edab5a8e..cc02d24cbf62 --- a/drivers/media/video/ov5640.h +++ b/drivers/media/video/ov5640.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __OV5640_H__ #define __OV5640_H__ struct reginfo diff --git a/drivers/media/video/rk2928_camera.c b/drivers/media/video/rk2928_camera.c old mode 100755 new mode 100644 index 01da2a4a86ad..5d0e26ce1928 --- a/drivers/media/video/rk2928_camera.c +++ b/drivers/media/video/rk2928_camera.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/media/video/rk29_camera.c b/drivers/media/video/rk29_camera.c old mode 100755 new mode 100644 index e8cf5d2ecca1..f5b51417486d --- a/drivers/media/video/rk29_camera.c +++ b/drivers/media/video/rk29_camera.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/media/video/rk29xx/Kconfig b/drivers/media/video/rk29xx/Kconfig index b7def547c535..12c94a8d5882 100644 --- a/drivers/media/video/rk29xx/Kconfig +++ b/drivers/media/video/rk29xx/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config VIDEO_RK29XX_VOUT tristate "RK29XX V4L2-Display driver" depends on ARCH_RK29 diff --git a/drivers/media/video/rk29xx/Makefile b/drivers/media/video/rk29xx/Makefile index 974e62d690e5..8a059cde4ad6 100644 --- a/drivers/media/video/rk29xx/Makefile +++ b/drivers/media/video/rk29xx/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the rk29xx video device drivers. # diff --git a/drivers/media/video/rk_camsys/Kconfig b/drivers/media/video/rk_camsys/Kconfig old mode 100755 new mode 100644 index efd3715d94f5..b8914e70cedc --- a/drivers/media/video/rk_camsys/Kconfig +++ b/drivers/media/video/rk_camsys/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config CAMSYS_DRV tristate "camsys driver " default n diff --git a/drivers/media/video/rk_camsys/Makefile b/drivers/media/video/rk_camsys/Makefile old mode 100755 new mode 100644 index f865c07f12b6..6ac6c7dff01b --- a/drivers/media/video/rk_camsys/Makefile +++ b/drivers/media/video/rk_camsys/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for rockchip camsys driver # diff --git a/drivers/media/video/rk_camsys/camsys_cif.c b/drivers/media/video/rk_camsys/camsys_cif.c old mode 100755 new mode 100644 index 22753b3f50f4..fce0784e6b1c --- a/drivers/media/video/rk_camsys/camsys_cif.c +++ b/drivers/media/video/rk_camsys/camsys_cif.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "camsys_cif.h" static const char miscdev_cif0_name[] = CAMSYS_CIF0_DEVNAME; diff --git a/drivers/media/video/rk_camsys/camsys_cif.h b/drivers/media/video/rk_camsys/camsys_cif.h old mode 100755 new mode 100644 index 6506766cc8f4..bd8f24c8533a --- a/drivers/media/video/rk_camsys/camsys_cif.h +++ b/drivers/media/video/rk_camsys/camsys_cif.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CAMSYS_CIF_H__ #define __CAMSYS_CIF_H__ diff --git a/drivers/media/video/rk_camsys/camsys_drv.c b/drivers/media/video/rk_camsys/camsys_drv.c index 8bcbe5754f6d..94a07edfd93b 100644 --- a/drivers/media/video/rk_camsys/camsys_drv.c +++ b/drivers/media/video/rk_camsys/camsys_drv.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include "camsys_cif.h" diff --git a/drivers/media/video/rk_camsys/camsys_gpio.h b/drivers/media/video/rk_camsys/camsys_gpio.h index bc2c7eca5991..b19437403741 100644 --- a/drivers/media/video/rk_camsys/camsys_gpio.h +++ b/drivers/media/video/rk_camsys/camsys_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_GPIO_H__ #define __RKCAMSYS_GPIO_H__ diff --git a/drivers/media/video/rk_camsys/camsys_internal.h b/drivers/media/video/rk_camsys/camsys_internal.h index eb638dac9557..78672437336b 100644 --- a/drivers/media/video/rk_camsys/camsys_internal.h +++ b/drivers/media/video/rk_camsys/camsys_internal.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_INTERNAL_H__ #define __RKCAMSYS_INTERNAL_H__ diff --git a/drivers/media/video/rk_camsys/camsys_marvin.c b/drivers/media/video/rk_camsys/camsys_marvin.c index e7ec58e1e93a..ffabb4f51ddb 100644 --- a/drivers/media/video/rk_camsys/camsys_marvin.c +++ b/drivers/media/video/rk_camsys/camsys_marvin.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "camsys_marvin.h" #include "camsys_soc_priv.h" #include "camsys_gpio.h" diff --git a/drivers/media/video/rk_camsys/camsys_marvin.h b/drivers/media/video/rk_camsys/camsys_marvin.h old mode 100755 new mode 100644 index 449c1f252876..06eed36f4ef2 --- a/drivers/media/video/rk_camsys/camsys_marvin.h +++ b/drivers/media/video/rk_camsys/camsys_marvin.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CAMSYS_MARVIN_H__ #define __CAMSYS_MARVIN_H__ diff --git a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c index cdef8c847539..fb4b0ab4b4f5 100644 --- a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c +++ b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "camsys_soc_priv.h" #include "camsys_mipicsi_phy.h" diff --git a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h old mode 100755 new mode 100644 index 0be00a1c97df..97ad2237b136 --- a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h +++ b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CAMSYS_MIPICSI_PHY_H__ #define __CAMSYS_MIPICSI_PHY_H__ diff --git a/drivers/media/video/rk_camsys/camsys_soc_priv.c b/drivers/media/video/rk_camsys/camsys_soc_priv.c index 238128dd4eb0..2bdd07b42cb0 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_priv.c +++ b/drivers/media/video/rk_camsys/camsys_soc_priv.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "camsys_soc_priv.h" diff --git a/drivers/media/video/rk_camsys/camsys_soc_priv.h b/drivers/media/video/rk_camsys/camsys_soc_priv.h old mode 100755 new mode 100644 index 730e6281dca2..459d0ee15f69 --- a/drivers/media/video/rk_camsys/camsys_soc_priv.h +++ b/drivers/media/video/rk_camsys/camsys_soc_priv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_SOC_PRIV_H__ #define __RKCAMSYS_SOC_PRIV_H__ diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3288.c b/drivers/media/video/rk_camsys/camsys_soc_rk3288.c old mode 100755 new mode 100644 index 02a5b409565f..f7db3bcfc7b1 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3288.c +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3288.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM #include "camsys_soc_priv.h" #include "camsys_soc_rk3288.h" diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3288.h b/drivers/media/video/rk_camsys/camsys_soc_rk3288.h old mode 100755 new mode 100644 index f82683b152bf..b34727f2a1ec --- a/drivers/media/video/rk_camsys/camsys_soc_rk3288.h +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3288.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_SOC_RK3288_H__ #define __RKCAMSYS_SOC_RK3288_H__ diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3366.c b/drivers/media/video/rk_camsys/camsys_soc_rk3366.c index a4a1bec59c37..1dcef7c86555 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3366.c +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3366.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM64 #include "camsys_soc_priv.h" #include "camsys_soc_rk3366.h" diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3366.h b/drivers/media/video/rk_camsys/camsys_soc_rk3366.h index a0e9ae2c37f4..99f6793fa133 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3366.h +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3366.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_SOC_RK3366_H__ #define __RKCAMSYS_SOC_RK3366_H__ diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3368.c b/drivers/media/video/rk_camsys/camsys_soc_rk3368.c index 1058b3a13a0d..74dbcbcb535d 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3368.c +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3368.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM64 #include "camsys_soc_priv.h" #include "camsys_soc_rk3368.h" diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3368.h b/drivers/media/video/rk_camsys/camsys_soc_rk3368.h index 121c30eaae08..7bfb32dce7f0 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3368.h +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3368.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_SOC_RK3368_H__ #define __RKCAMSYS_SOC_RK3368_H__ diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3399.c b/drivers/media/video/rk_camsys/camsys_soc_rk3399.c index 09a30a8e66a6..8f5d57693ed3 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3399.c +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3399.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM64 #include "camsys_soc_priv.h" #include "camsys_soc_rk3399.h" diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3399.h b/drivers/media/video/rk_camsys/camsys_soc_rk3399.h index af246a8873a5..9df66e79c55b 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3399.h +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3399.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_SOC_RK3399_H__ #define __RKCAMSYS_SOC_RK3399_H__ diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig b/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig old mode 100755 new mode 100644 index 370ee54b73e0..b12c5b78d1d3 --- a/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig +++ b/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config FLASHLIGHT bool "Flashlight Support" default n diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile b/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile old mode 100755 new mode 100644 index c96b20eb4769..c0fb3bf73c91 --- a/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile +++ b/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_FLASHLIGHT) += flashlight.o rk_ext_fshled_ctl.o obj-$(CONFIG_RT_FLASH_LED) += rtfled.o obj-$(CONFIG_LEDS_RT8547) += leds-rt8547.o diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c index 24aed21abac1..120a183fd5d1 100644 --- a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c +++ b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "rk_ext_fshled_ctl.h" #include "../camsys_gpio.h" #include "flashlight.h" diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h old mode 100755 new mode 100644 index d66af0ddd9c3..4fe98441e358 --- a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h +++ b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK_EXT_FSHLED_H__ #define __RK_EXT_FSHLED_H__ #include "../camsys_internal.h" diff --git a/drivers/media/video/s5k5ca.h b/drivers/media/video/s5k5ca.h old mode 100755 new mode 100644 index de1643ceb812..5bf5e4f4220f --- a/drivers/media/video/s5k5ca.h +++ b/drivers/media/video/s5k5ca.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __S5K6AA_H__ #define __S5K6AA_H__ diff --git a/drivers/media/video/s5k6aa.h b/drivers/media/video/s5k6aa.h index de1643ceb812..5bf5e4f4220f 100644 --- a/drivers/media/video/s5k6aa.h +++ b/drivers/media/video/s5k6aa.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __S5K6AA_H__ #define __S5K6AA_H__ diff --git a/drivers/mfd/rk610-core.c b/drivers/mfd/rk610-core.c old mode 100755 new mode 100644 index b0a6a9ba7ebf..a76bb44cdc97 --- a/drivers/mfd/rk610-core.c +++ b/drivers/mfd/rk610-core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/mfd/rk616-core.c b/drivers/mfd/rk616-core.c old mode 100755 new mode 100644 index 23efc531e740..630fd4ad5285 --- a/drivers/mfd/rk616-core.c +++ b/drivers/mfd/rk616-core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/mfd/rk616-vif.c b/drivers/mfd/rk616-vif.c old mode 100755 new mode 100644 index 9ecaef7d728a..ba3343627809 --- a/drivers/mfd/rk616-vif.c +++ b/drivers/mfd/rk616-vif.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/mfd/tlv320aic3262-core.c b/drivers/mfd/tlv320aic3262-core.c index ddf4bd6f32e1..9bd92d20e2da 100644 --- a/drivers/mfd/tlv320aic3262-core.c +++ b/drivers/mfd/tlv320aic3262-core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/mfd/tlv320aic3262-irq.c b/drivers/mfd/tlv320aic3262-irq.c index 9a76f0f02e81..f91f260f7c24 100644 --- a/drivers/mfd/tlv320aic3262-irq.c +++ b/drivers/mfd/tlv320aic3262-irq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/misc/3g_module/Kconfig b/drivers/misc/3g_module/Kconfig old mode 100755 new mode 100644 index 058f7f31a9c7..a2aabc55cfb5 --- a/drivers/misc/3g_module/Kconfig +++ b/drivers/misc/3g_module/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # 3G device configuration # diff --git a/drivers/misc/3g_module/Makefile b/drivers/misc/3g_module/Makefile old mode 100755 new mode 100644 index f0a3bcc74cc3..3284a1dbc441 --- a/drivers/misc/3g_module/Makefile +++ b/drivers/misc/3g_module/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MU509) += mu509.o obj-$(CONFIG_MW100) += mw100.o obj-$(CONFIG_MT6229) += mt6229.o diff --git a/drivers/misc/5v_en.c b/drivers/misc/5v_en.c index d8dc49b9ea77..6dea234835dc 100644 --- a/drivers/misc/5v_en.c +++ b/drivers/misc/5v_en.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/ac_usb_switch.c b/drivers/misc/ac_usb_switch.c old mode 100755 new mode 100644 index a083c28a5544..111f1cd2c3ed --- a/drivers/misc/ac_usb_switch.c +++ b/drivers/misc/ac_usb_switch.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/bp/Kconfig b/drivers/misc/bp/Kconfig old mode 100755 new mode 100644 index 112a2afdf50c..1443491cbc30 --- a/drivers/misc/bp/Kconfig +++ b/drivers/misc/bp/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # all auto modem control drivers configuration # diff --git a/drivers/misc/bp/Makefile b/drivers/misc/bp/Makefile old mode 100755 new mode 100644 index d32f5e16fae4..5afb298e7fa1 --- a/drivers/misc/bp/Makefile +++ b/drivers/misc/bp/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # auto modem control drivers obj-$(CONFIG_BP_AUTO) += chips/ obj-$(CONFIG_BP_AUTO) += bp-auto.o \ No newline at end of file diff --git a/drivers/misc/bp/bp-auto.c b/drivers/misc/bp/bp-auto.c old mode 100755 new mode 100644 index e5f972c4705d..94894c96f9e9 --- a/drivers/misc/bp/bp-auto.c +++ b/drivers/misc/bp/bp-auto.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/bp/chips/Kconfig b/drivers/misc/bp/chips/Kconfig old mode 100755 new mode 100644 index 5662db07171a..73a8951d2e64 --- a/drivers/misc/bp/chips/Kconfig +++ b/drivers/misc/bp/chips/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config BP_AUTO_MT6229 bool "modem mt6229" default n diff --git a/drivers/misc/bp/chips/Makefile b/drivers/misc/bp/chips/Makefile old mode 100755 new mode 100644 index f0029888458a..ba308b8573ed --- a/drivers/misc/bp/chips/Makefile +++ b/drivers/misc/bp/chips/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_BP_AUTO) += mw100.o obj-$(CONFIG_BP_AUTO) += mi700.o obj-$(CONFIG_BP_AUTO) += mt6229.o diff --git a/drivers/misc/fm580x.h b/drivers/misc/fm580x.h old mode 100755 new mode 100644 index 5fae06a398df..13e4210b9c66 --- a/drivers/misc/fm580x.h +++ b/drivers/misc/fm580x.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for fm580x chip. */ diff --git a/drivers/misc/gps/Kconfig b/drivers/misc/gps/Kconfig old mode 100755 new mode 100644 index f6902169512d..7da51e0e6bbb --- a/drivers/misc/gps/Kconfig +++ b/drivers/misc/gps/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gps device configuration # diff --git a/drivers/misc/gps/Makefile b/drivers/misc/gps/Makefile old mode 100755 new mode 100644 index 66bb6f730402..e135d7bada41 --- a/drivers/misc/gps/Makefile +++ b/drivers/misc/gps/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_GPS_DEVICES) += rk_gps/ obj-$(CONFIG_GPS_GNS7560) += rk29_gps.o diff --git a/drivers/misc/gps/rk29_gps.c b/drivers/misc/gps/rk29_gps.c old mode 100755 new mode 100644 index 9b1f2615cf4b..f5e94b0acfab --- a/drivers/misc/gps/rk29_gps.c +++ b/drivers/misc/gps/rk29_gps.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/gps/rk29_gps.h b/drivers/misc/gps/rk29_gps.h index 2599b7e4c4b2..c50ca1d7288b 100644 --- a/drivers/misc/gps/rk29_gps.h +++ b/drivers/misc/gps/rk29_gps.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* 2011.01.2 lw@rock-chips.com */ diff --git a/drivers/misc/gps/rk_gps/Kconfig b/drivers/misc/gps/rk_gps/Kconfig old mode 100755 new mode 100644 index 85a47c60be5d..3a20096c3105 --- a/drivers/misc/gps/rk_gps/Kconfig +++ b/drivers/misc/gps/rk_gps/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # gps device configuration # diff --git a/drivers/misc/gps/rk_gps/Makefile b/drivers/misc/gps/rk_gps/Makefile old mode 100755 new mode 100644 index 5399d06cfe37..560d4a2c4f7d --- a/drivers/misc/gps/rk_gps/Makefile +++ b/drivers/misc/gps/rk_gps/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # All selected in one module named smsmdtv gps-objs := rk_gps_null.o obj-$(CONFIG_GPS_RK) += gps.o diff --git a/drivers/misc/gps/rk_gps/rk_gps.h b/drivers/misc/gps/rk_gps/rk_gps.h old mode 100755 new mode 100644 index 4e21aeb0a66c..1a2f931a0b7d --- a/drivers/misc/gps/rk_gps/rk_gps.h +++ b/drivers/misc/gps/rk_gps/rk_gps.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* 2012.07.25 lby@rock-chips.com */ diff --git a/drivers/misc/gps/rk_gps/rk_gps_null.c b/drivers/misc/gps/rk_gps/rk_gps_null.c index 2c24bb1c5aa9..589b8bb768ad 100644 --- a/drivers/misc/gps/rk_gps/rk_gps_null.c +++ b/drivers/misc/gps/rk_gps/rk_gps_null.c @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //for rk_gps building diff --git a/drivers/misc/inv_mpu/Kconfig b/drivers/misc/inv_mpu/Kconfig old mode 100755 new mode 100644 index 864363062e01..a49985623f47 --- a/drivers/misc/inv_mpu/Kconfig +++ b/drivers/misc/inv_mpu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config MPU_SENSORS_TIMERIRQ tristate "MPU Timer IRQ" help diff --git a/drivers/misc/inv_mpu/Makefile b/drivers/misc/inv_mpu/Makefile old mode 100755 new mode 100644 index 248648f6567c..7a10fec9266f --- a/drivers/misc/inv_mpu/Makefile +++ b/drivers/misc/inv_mpu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # Kernel makefile for motions sensors # diff --git a/drivers/misc/inv_mpu/accel/Kconfig b/drivers/misc/inv_mpu/accel/Kconfig old mode 100755 new mode 100644 index 4e280bd876bc..462f2b266029 --- a/drivers/misc/inv_mpu/accel/Kconfig +++ b/drivers/misc/inv_mpu/accel/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig INV_SENSORS_ACCELEROMETERS bool "Accelerometer Slave Sensors" default y diff --git a/drivers/misc/inv_mpu/accel/Makefile b/drivers/misc/inv_mpu/accel/Makefile old mode 100755 new mode 100644 index 1f0f5bec6774..06b09a2d2914 --- a/drivers/misc/inv_mpu/accel/Makefile +++ b/drivers/misc/inv_mpu/accel/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Accel Slaves to MPUxxxx # diff --git a/drivers/misc/inv_mpu/compass/Kconfig b/drivers/misc/inv_mpu/compass/Kconfig old mode 100755 new mode 100644 index 2830d320a6e7..2e59ad274cdf --- a/drivers/misc/inv_mpu/compass/Kconfig +++ b/drivers/misc/inv_mpu/compass/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig INV_SENSORS_COMPASS bool "Compass Slave Sensors" default y diff --git a/drivers/misc/inv_mpu/compass/Makefile b/drivers/misc/inv_mpu/compass/Makefile old mode 100755 new mode 100644 index 08d35481c002..89440f6c1e31 --- a/drivers/misc/inv_mpu/compass/Makefile +++ b/drivers/misc/inv_mpu/compass/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Compass Slaves MPUxxxx # diff --git a/drivers/misc/inv_mpu/pressure/Kconfig b/drivers/misc/inv_mpu/pressure/Kconfig old mode 100755 new mode 100644 index f1c021e8f126..fa00858e30ef --- a/drivers/misc/inv_mpu/pressure/Kconfig +++ b/drivers/misc/inv_mpu/pressure/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig: INV_SENSORS_PRESSURE bool "Pressure Sensor Slaves" depends on INV_SENSORS diff --git a/drivers/misc/inv_mpu/pressure/Makefile b/drivers/misc/inv_mpu/pressure/Makefile old mode 100755 new mode 100644 index 595923d809dc..facbc8048ffc --- a/drivers/misc/inv_mpu/pressure/Makefile +++ b/drivers/misc/inv_mpu/pressure/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Pressure Slaves to MPUxxxx # diff --git a/drivers/misc/modem_sound.c b/drivers/misc/modem_sound.c old mode 100755 new mode 100644 index 800405deefe8..9cf3ae781a7c --- a/drivers/misc/modem_sound.c +++ b/drivers/misc/modem_sound.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/modem_sound.h b/drivers/misc/modem_sound.h old mode 100755 new mode 100644 index 35b1d0ea0a1d..d1ec4b1948dc --- a/drivers/misc/modem_sound.h +++ b/drivers/misc/modem_sound.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __MODEM_SOUND_H__ #define __MODEM_SOUND_H__ diff --git a/drivers/misc/rk2928_callpad_misc/Kconfig b/drivers/misc/rk2928_callpad_misc/Kconfig old mode 100755 new mode 100644 index 48f2e3b0c166..2285a07464dd --- a/drivers/misc/rk2928_callpad_misc/Kconfig +++ b/drivers/misc/rk2928_callpad_misc/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # rk2928 callpad misc device configuration # diff --git a/drivers/misc/rk2928_callpad_misc/Makefile b/drivers/misc/rk2928_callpad_misc/Makefile old mode 100755 new mode 100644 index d2328ae02260..b1386aef2114 --- a/drivers/misc/rk2928_callpad_misc/Makefile +++ b/drivers/misc/rk2928_callpad_misc/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_AUDIO_SWITCH) += audio_switch.o diff --git a/drivers/misc/rk2928_callpad_misc/audio_switch.h b/drivers/misc/rk2928_callpad_misc/audio_switch.h old mode 100755 new mode 100644 index eaf1d5ed0e90..6ee14b1f2687 --- a/drivers/misc/rk2928_callpad_misc/audio_switch.h +++ b/drivers/misc/rk2928_callpad_misc/audio_switch.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK2928_AUDIO_SWTICH_H #define RK2928_AUDIO_SWTICH_H diff --git a/drivers/misc/rk29_modem/Kconfig b/drivers/misc/rk29_modem/Kconfig index 9e11339a5bc5..f3fb88610634 100644 --- a/drivers/misc/rk29_modem/Kconfig +++ b/drivers/misc/rk29_modem/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # USB Serial device configuration # diff --git a/drivers/misc/rk29_modem/Makefile b/drivers/misc/rk29_modem/Makefile index a98c411d53ae..f652985e2b64 100644 --- a/drivers/misc/rk29_modem/Makefile +++ b/drivers/misc/rk29_modem/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem.o obj-$(CONFIG_MODEM_ROCKCHIP_DEMO) += modem_rockchip_demo.o obj-$(CONFIG_MODEM_LONGCHEER_U6300V) +=modem_longcheer_u6300v.o diff --git a/drivers/misc/rk29_modem/modem_longcheer_u6300v.c b/drivers/misc/rk29_modem/modem_longcheer_u6300v.c index 350ae34df333..5045dd7383ce 100644 --- a/drivers/misc/rk29_modem/modem_longcheer_u6300v.c +++ b/drivers/misc/rk29_modem/modem_longcheer_u6300v.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/rk29_modem/modem_rockchip_demo.c b/drivers/misc/rk29_modem/modem_rockchip_demo.c index 4e3a2be2fa32..2c41e4e5fc49 100644 --- a/drivers/misc/rk29_modem/modem_rockchip_demo.c +++ b/drivers/misc/rk29_modem/modem_rockchip_demo.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/rk29_modem/modem_thinkwill_mw100g.c b/drivers/misc/rk29_modem/modem_thinkwill_mw100g.c index 182fbf4e86d8..acef01ff0fd5 100644 --- a/drivers/misc/rk29_modem/modem_thinkwill_mw100g.c +++ b/drivers/misc/rk29_modem/modem_thinkwill_mw100g.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/rk29_modem/rk29_modem.c b/drivers/misc/rk29_modem/rk29_modem.c index bff4bf5051c5..7f99917eaa18 100644 --- a/drivers/misc/rk29_modem/rk29_modem.c +++ b/drivers/misc/rk29_modem/rk29_modem.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/rk29_modem/rk29_modem.h b/drivers/misc/rk29_modem/rk29_modem.h index 09516ec342b2..95814bfa646f 100644 --- a/drivers/misc/rk29_modem/rk29_modem.h +++ b/drivers/misc/rk29_modem/rk29_modem.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/misc/sc8800.c b/drivers/misc/sc8800.c old mode 100755 new mode 100644 index c06d00a58436..b3b56c85fe26 --- a/drivers/misc/sc8800.c +++ b/drivers/misc/sc8800.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/scaler/Kconfig b/drivers/misc/scaler/Kconfig old mode 100755 new mode 100644 index 062ec0cc5988..b621148a093d --- a/drivers/misc/scaler/Kconfig +++ b/drivers/misc/scaler/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # all auto modem control drivers configuration # diff --git a/drivers/misc/scaler/Makefile b/drivers/misc/scaler/Makefile index 53d6aa7b52f7..2284543338e0 100644 --- a/drivers/misc/scaler/Makefile +++ b/drivers/misc/scaler/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the display core. # diff --git a/drivers/misc/scaler/chips/Kconfig b/drivers/misc/scaler/chips/Kconfig index c6a828263f1a..78b4c9ee88f1 100644 --- a/drivers/misc/scaler/chips/Kconfig +++ b/drivers/misc/scaler/chips/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # #config tv5735 support inport type and output type # diff --git a/drivers/misc/scaler/chips/Makefile b/drivers/misc/scaler/chips/Makefile index 3667cad99485..b633d1ff59ad 100644 --- a/drivers/misc/scaler/chips/Makefile +++ b/drivers/misc/scaler/chips/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_SCALER_TV5735) += tv5735.o obj-$(CONFIG_SCALER_TEST) += test.o diff --git a/drivers/misc/scaler/chips/test.c b/drivers/misc/scaler/chips/test.c index 81d50274e939..b98f75797301 100644 --- a/drivers/misc/scaler/chips/test.c +++ b/drivers/misc/scaler/chips/test.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2010 by Rockchip. */ diff --git a/drivers/misc/scaler/chips/tv5735.c b/drivers/misc/scaler/chips/tv5735.c index f9dd561433c5..a507d3508b5c 100644 --- a/drivers/misc/scaler/chips/tv5735.c +++ b/drivers/misc/scaler/chips/tv5735.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2010 by Rockchip. */ diff --git a/drivers/misc/scaler/chips/tv_setting.h b/drivers/misc/scaler/chips/tv_setting.h index 112ceda3693b..a75d2b8ed540 100644 --- a/drivers/misc/scaler/chips/tv_setting.h +++ b/drivers/misc/scaler/chips/tv_setting.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include /****************rgb to vga**************/ unsigned char tv1280_720to1280_720_reg[]= diff --git a/drivers/misc/scaler/scaler-core.c b/drivers/misc/scaler/scaler-core.c index 0a2d28250695..8983173faf5f 100644 --- a/drivers/misc/scaler/scaler-core.c +++ b/drivers/misc/scaler/scaler-core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * * Copyright (C) 2012 Rockchip diff --git a/drivers/misc/scaler/scaler-edid.c b/drivers/misc/scaler/scaler-edid.c index b2296418fe19..21a94d2cf752 100644 --- a/drivers/misc/scaler/scaler-edid.c +++ b/drivers/misc/scaler/scaler-edid.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/scaler/scaler-sysfs.c b/drivers/misc/scaler/scaler-sysfs.c index 969efcb47d3c..846ea78a495a 100644 --- a/drivers/misc/scaler/scaler-sysfs.c +++ b/drivers/misc/scaler/scaler-sysfs.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/misc/tcc_bt_dev.c b/drivers/misc/tcc_bt_dev.c old mode 100755 new mode 100644 index c8137d0bfa23..7e7572f4cc0e --- a/drivers/misc/tcc_bt_dev.c +++ b/drivers/misc/tcc_bt_dev.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2010-2011 RDA Micro diff --git a/drivers/mtd/rknand/Kconfig b/drivers/mtd/rknand/Kconfig old mode 100755 new mode 100644 index 5742f2087ce5..0abd524a6feb --- a/drivers/mtd/rknand/Kconfig +++ b/drivers/mtd/rknand/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # linux/drivers/mtd/rknand/Kconfig # diff --git a/drivers/mtd/rknand/Makefile b/drivers/mtd/rknand/Makefile old mode 100755 new mode 100644 index 964ea55489f3..5ddcdf1a7c28 --- a/drivers/mtd/rknand/Makefile +++ b/drivers/mtd/rknand/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # linux/drivers/rknand/Makefile # diff --git a/drivers/mtd/rknand/api_flash.h b/drivers/mtd/rknand/api_flash.h old mode 100755 new mode 100644 index 2340d4bb9c0d..3ca267b1146e --- a/drivers/mtd/rknand/api_flash.h +++ b/drivers/mtd/rknand/api_flash.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /******************************************************************************** ********************************************************************************* COPYRIGHT (c) 2004 BY ROCK-CHIP FUZHOU diff --git a/drivers/mtd/rknand/rknand_base.h b/drivers/mtd/rknand/rknand_base.h old mode 100755 new mode 100644 index 073fc4260c9e..6460e9eace46 --- a/drivers/mtd/rknand/rknand_base.h +++ b/drivers/mtd/rknand/rknand_base.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * linux/drivers/mtd/rknand/rknand_base.c * diff --git a/drivers/mtd/rknand/rknand_base_ko.c b/drivers/mtd/rknand/rknand_base_ko.c old mode 100755 new mode 100644 index e0c2e59c4a26..5a462b76dc42 --- a/drivers/mtd/rknand/rknand_base_ko.c +++ b/drivers/mtd/rknand/rknand_base_ko.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * linux/drivers/mtd/rknand/rknand_base.c * diff --git a/drivers/net/ethernet/rockchip/Kconfig b/drivers/net/ethernet/rockchip/Kconfig old mode 100755 new mode 100644 index 777b5e897ff7..1602843de8b1 --- a/drivers/net/ethernet/rockchip/Kconfig +++ b/drivers/net/ethernet/rockchip/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # rockchip device configuration # diff --git a/drivers/net/ethernet/rockchip/Makefile b/drivers/net/ethernet/rockchip/Makefile old mode 100755 new mode 100644 index 55fe6e177e64..acbfcdeee0b3 --- a/drivers/net/ethernet/rockchip/Makefile +++ b/drivers/net/ethernet/rockchip/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the rockchip device drivers. # diff --git a/drivers/net/ethernet/rockchip/eth_mac.c b/drivers/net/ethernet/rockchip/eth_mac.c old mode 100755 new mode 100644 index 296c828f5d88..8c2f1135ea9f --- a/drivers/net/ethernet/rockchip/eth_mac.c +++ b/drivers/net/ethernet/rockchip/eth_mac.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2010 ROCKCHIP, Inc. * Author: roger_chen diff --git a/drivers/net/ethernet/rockchip/gmac/Kconfig b/drivers/net/ethernet/rockchip/gmac/Kconfig old mode 100755 new mode 100644 index 957a46bdbc18..1079cb5fe18e --- a/drivers/net/ethernet/rockchip/gmac/Kconfig +++ b/drivers/net/ethernet/rockchip/gmac/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK_GMAC_ETH tristate "Rockchip 10/100/1000 Ethernet driver" depends on HAS_IOMEM && HAS_DMA diff --git a/drivers/net/ethernet/rockchip/gmac/Makefile b/drivers/net/ethernet/rockchip/gmac/Makefile old mode 100755 new mode 100644 index 7abf9db73cc2..3459e8cec641 --- a/drivers/net/ethernet/rockchip/gmac/Makefile +++ b/drivers/net/ethernet/rockchip/gmac/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK_GMAC_ETH) += stmmac.o stmmac-$(CONFIG_RK_GMAC_ETH) += stmmac_platform.o stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o diff --git a/drivers/net/ethernet/rockchip/vmac/Kconfig b/drivers/net/ethernet/rockchip/vmac/Kconfig old mode 100755 new mode 100644 index 23f5af837e7f..6449c40afb4b --- a/drivers/net/ethernet/rockchip/vmac/Kconfig +++ b/drivers/net/ethernet/rockchip/vmac/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK_VMAC_ETH bool "Rockchip 10/100 Ethernet driver" depends on HAS_IOMEM && HAS_DMA diff --git a/drivers/net/ethernet/rockchip/vmac/Makefile b/drivers/net/ethernet/rockchip/vmac/Makefile old mode 100755 new mode 100644 index 4de386217110..4359c4f60e57 --- a/drivers/net/ethernet/rockchip/vmac/Makefile +++ b/drivers/net/ethernet/rockchip/vmac/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK_VMAC_ETH) += rk29_vmac.o obj-$(CONFIG_RK_VMAC_ETH) += rk29_vmac_phy.o diff --git a/drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c b/drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c old mode 100755 new mode 100644 index 20ba49169a1f..7d60d192ac74 --- a/drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c +++ b/drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/net/irda/bu92725guw.c b/drivers/net/irda/bu92725guw.c old mode 100755 new mode 100644 index cf00fe1c69fc..2b0100f19883 --- a/drivers/net/irda/bu92725guw.c +++ b/drivers/net/irda/bu92725guw.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * * File: bu92725guw.c diff --git a/drivers/net/irda/bu92725guw.h b/drivers/net/irda/bu92725guw.h old mode 100755 new mode 100644 index 5355d87e300a..41d36dc3fb08 --- a/drivers/net/irda/bu92725guw.h +++ b/drivers/net/irda/bu92725guw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * * File: bu92725guw.h diff --git a/drivers/net/irda/ir_serial.h b/drivers/net/irda/ir_serial.h old mode 100755 new mode 100644 index f0b3fe436bf1..c200c899645a --- a/drivers/net/irda/ir_serial.h +++ b/drivers/net/irda/ir_serial.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IR_SERIAL_H_ #define _IR_SERIAL_H_ diff --git a/drivers/net/irda/rk29_ir.h b/drivers/net/irda/rk29_ir.h old mode 100755 new mode 100644 index beb3e7bc840c..4d89f2f5a4cb --- a/drivers/net/irda/rk29_ir.h +++ b/drivers/net/irda/rk29_ir.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DRIVERS_NET_IRDA_RK29_IR_H #define __DRIVERS_NET_IRDA_RK29_IR_H diff --git a/drivers/net/wireless/rockchip_wlan/Kconfig b/drivers/net/wireless/rockchip_wlan/Kconfig index 8c9cd20aa4a5..c5bcbf5ebb6f 100644 --- a/drivers/net/wireless/rockchip_wlan/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig WL_ROCKCHIP bool "Rockchip Wireless LAN support" select WIRELESS_EXT diff --git a/drivers/net/wireless/rockchip_wlan/Makefile b/drivers/net/wireless/rockchip_wlan/Makefile index 9bc3dcc9bf66..a941feedba49 100644 --- a/drivers/net/wireless/rockchip_wlan/Makefile +++ b/drivers/net/wireless/rockchip_wlan/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_AP6XXX) += rkwifi/ obj-$(CONFIG_RTL8188EU) += rtl8188eu/ obj-$(CONFIG_RTL8188FU) += rtl8188fu/ diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/Kconfig b/drivers/net/wireless/rockchip_wlan/esp8089/Kconfig old mode 100755 new mode 100644 index 399189a8362c..3bf7688428fc --- a/drivers/net/wireless/rockchip_wlan/esp8089/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/esp8089/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config ESP8089 # depends on WLAN_80211 && MMC select WIRELESS_EXT diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/Makefile b/drivers/net/wireless/rockchip_wlan/esp8089/Makefile old mode 100755 new mode 100644 index 93e8ee8c331c..33161248cfc1 --- a/drivers/net/wireless/rockchip_wlan/esp8089/Makefile +++ b/drivers/net/wireless/rockchip_wlan/esp8089/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ESP8089) += esp_premalloc/ esp_driver/ diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig old mode 100755 new mode 100644 index 20fc17765773..70fd7aeb867c --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config ESP8089 depends on WLAN_80211 && MMC select WIRELESS_EXT diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile old mode 100755 new mode 100644 index 392bcf5974f0..29e144932763 --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # copyright (c) 2011 - 2012 espressif system DRIVER_NAME := wlan include drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h old mode 100755 new mode 100644 index a2e03fbd73b6..90f86e66b133 --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw1.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) Espressif System diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h old mode 100755 new mode 100644 index fa4189f78bb3..30b05f9457d4 --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw2.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) Espressif System diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h old mode 100755 new mode 100644 index d05598ddf86a..e4ad77f0a300 --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/eagle_fw3.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) Espressif System diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk old mode 100755 new mode 100644 index 2026cdf8be64..3acb74476df8 --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_config.mk @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += -DP2P_CONCURRENT -DESP_ACK_INTERRUPT -DESP_USE_SDIO diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h old mode 100755 new mode 100644 index 3f783263ddf3..03130720541e --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_driver/esp_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVER_VER 0x8b6d429f0a53ll diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile b/drivers/net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile old mode 100755 new mode 100644 index 40880645e12a..1b45e8e6603d --- a/drivers/net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile +++ b/drivers/net/wireless/rockchip_wlan/esp8089/esp_premalloc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # copyright (c) 2011 - 2012 espressif system # linux_sdio #ifneq ($(KERNELRELEASE),) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/Kconfig b/drivers/net/wireless/rockchip_wlan/rkwifi/Kconfig index 913607bbb233..ef5c939a2b4a 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config AP6XXX tristate "ap6xxx wireless sdio cards support" #depends on MMC && WLAN_80211 diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/Makefile index 1ffced552d36..6ddbbe7f7326 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 #rkwifi packed Makefile # (gwl) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig old mode 100755 new mode 100644 index bba8b4f59ae2..303e009bf4a1 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config BCMDHD tristate "Broadcom FullMAC wireless cards support" ---help--- diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile index 0dc7f6819a5a..a24a0826fd71 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # bcmdhd # 1. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4, # otherwise please remove it. diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c index c54ebba0c80d..f6d30ba7a920 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h index 0a194936f35a..bfa6a3ea31e6 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _dhd_config_ #define _dhd_config_ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c index a4ae259d8df5..ef3f67b49077 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c index a2acf0a31d24..c615ba041829 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c old mode 100755 new mode 100644 index b7a46db92254..e16f292031fb --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/rkversion.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* rk_wifi_config.c * * RKWIFI driver version. diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c index 507edc16cd16..e510c241f536 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c index f9be06301ba6..a5aa76bad90c 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if defined(WL_ESCAN) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h index 04255d4e2d04..62bc0d28b0e8 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _wl_escan_ #define _wl_escan_ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c b/drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c old mode 100755 new mode 100644 index 566f4672b867..fa07a94c27c1 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/rk_wifi_config.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* rk_wifi_config.c * * RKWIFI driver version. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8188eu/Kconfig index 013175c374b2..512e319aa0f3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8188EU tristate "Realtek 8188E USB WiFi" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8188eu/Makefile index 4dc4f0da45a5..d3a60ea47ed9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi.c index d23ed2682c3f..186c4206efe2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi_sms4.c index fc01212ecfe3..01762acc22b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.c index 38c89d10caf6..88b68716b9dc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.h index e75127c10a6d..cddf396840da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.c index 312877dd9b28..4e80a00858f1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.h index 00fed716141d..30aa455ccb3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8192e2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.c index 8471ed7343bb..bf811a9e2a51 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.h index ed5ebe0cc73a..eb06cffd3651 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8703b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.c index 98b12ac442fc..c3de3d31ae87 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.h index af476d9659d1..9d610124b767 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.c index 3b1dd4a53344..f4f9a99f7b8b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.h index b44959cf02dd..4b7da302fa34 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.c index 9be8d62305b3..87989e1eb48c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.h index 0265ab3df0dd..8e5cf17a93d9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723bwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8723BWIFIONLYHWCFG_H #define __INC_HAL8723BWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.c index 80d4ca5347ed..7af3c87d1719 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.h index 76edd5a30f2f..2408e1f68c24 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.c index da21d953931a..c489b52bc49e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.h index 1472796e6ce0..b0fe6f8013fd 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8723d2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.c index f1cefab2e5de..dfe2c6558177 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.h index e786d375d7c8..7fbf445e0efb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.c index 038405b62c30..96a412ef8fd1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.h index fa19aaf67a76..26db0e85bd0f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8812a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.c index bba78ae0f410..3451a5185023 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.h index 53a531348eef..75e6f708047f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.c index 80efc338f2ec..0ca35add2367 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.h index 81513976951a..a4997fe58cde 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.c index 34b1305f3611..7377db9b3f43 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.h index f712494e6f53..24c7835781b0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.c index 5bae8161fb31..984f0692bbcc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.h index f89b1fa51e04..94a40078ab3d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821c2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.c index 6de8db015f85..0291a2f9a4b7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" static struct rfe_type_8821c_wifi_only gl_rfe_type_8821c_1ant; diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.h index afa2b2f84b71..65c57c641616 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8821cwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8821CWIFIONLYHWCFG_H #define __INC_HAL8821CWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.c index 50673e7a59c8..167c9930c4e7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.h index e84a27e87515..05f7253530df 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.c index 6f3d6b5680bc..82927981ae62 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.h index 875733436c9d..0a20d7555618 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.c index 35004d731338..214fc8b61b84 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.h index 3f5ef3bc1a3e..71a1b7e81dc3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtc8822bwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8822BWIFIONLYHWCFG_H #define __INC_HAL8822BWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtcoutsrc.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtcoutsrc.h index 14a56dee2698..e11f275098a4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtcoutsrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/btc/halbtcoutsrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/efuse/efuse_mask.h index faafed48f009..849a4e49d0bf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/hal_btcoex_wifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/hal_btcoex_wifionly.c index 861bcfb4ba44..838bb97fc7c3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/hal_btcoex_wifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/hal_btcoex_wifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "btc/mp_precomp.h" #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/halhwimg.h index 14a9f63f55d4..cca28990f647 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.c index f10d7ef58ad2..1e9cf35fb66e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.h index 2acd0f533609..6ebd7f6d7195 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_adc_sampling.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_ADCSMP_H #define __INC_ADCSMP_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.c index 80aae83d0ca1..c21e2ed7aacd 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.h index f13fa0b0ae6b..043d4e3e1a60 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_PHYDM_BEAMFORMING_H #define __INC_PHYDM_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.c index 1d7d468a094d..efa67bbcbcd8 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.h index d9adf6332e30..123eaa5ae32b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/phydm_ccx.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __PHYDMCCX_H__ #define __PHYDMCCX_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.c index f6e9f1b9a39f..a46399ab2080 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.h index 14bc70a1d96a..a62f8df45ff0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/hal8188erateadaptive.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_RA_H #define __INC_RA_H /*++ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/version_rtl8188e.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/version_rtl8188e.h index 0facf233a901..87cde3a9d295 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/version_rtl8188e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/rtl8188e/version_rtl8188e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8188E PHY Parameters*/ /* [Caution] diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.c index 2349fa9588ed..dcc9571e5a8b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.h index 37beb45eda7e..6e889d9f58d0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.c index 7be33f0f41aa..65b738efae99 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.h index 618ca809f0c1..87740119313b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.c index ffa7c3bb090a..4b490a2a0e1f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.h index d66374ceb7c5..fe0d66463b13 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.c index 2503d584e87f..40f999018a91 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.h index 9f86f7c8913b..df7881f4cc0f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.c index d09d49899067..32f04fc221ec 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.h index 915812cb7699..ff0313defc20 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.c index 600d703ee260..bebdb8762e13 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.h index 7c7f73ed391a..045dd6647806 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ #if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/phydm_hal_txbf_api.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/phydm_hal_txbf_api.c index 317204db2a26..6f1f74b9cce6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/phydm_hal_txbf_api.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/phydm/txbf/phydm_hal_txbf_api.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8188FPwrSeq.h index 81e613227bdb..59aba21de9a5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPhyReg.h index cd13c22bc398..b69ccd01c901 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPwrSeq.h index 12bb2fb6be05..9332505c84c0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8703BPwrSeq.h index a53ca9a0767a..fb36455f3279 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723BPwrSeq.h index 6b895621e1c5..d18d064dae0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723DPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723DPwrSeq.h index 5032e7cafebf..74debbaac9ee 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723DPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723DPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723D #define REALTEK_POWER_SEQUENCE_8723D diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723PwrSeq.h index 6669641e8767..e463f74b7ae3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8821APwrSeq.h index 393068b3f3cf..091c2e56d967 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/custom_gpio.h index 5691d9a1c6cc..54e491872992 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/hal_btcoex_wifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/hal_btcoex_wifionly.h index 2633d9585b91..89b3ad5321c9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/hal_btcoex_wifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/hal_btcoex_wifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_WIFIONLY_H__ #define __HALBTC_WIFIONLY_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_version.h index 46e312420ae8..39b6b2a15a0a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v5.2.2.3_24783.20171030" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wapi.h index 635aec0db4ee..216ab6997c04 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wifi_regd.h index 2182712648bd..541a211f9511 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188eu/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8188eu/os_dep/linux/wifi_regd.c index 2f6f5b1d067e..d79e3a30e7d4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188eu/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188eu/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8188fu/Kconfig index 5bc5e68dcd78..87af8ddaf49e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8188FU tristate "Realtek 8188F USB WiFi" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8188fu/Makefile index 40b92a839f71..19d0a845abb1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi.c index d4835daadb96..a7d574cc46d1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi_sms4.c index 6126ed9a00c6..75f10ab4752e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.c index 86e006dba32b..bcde0c67b4da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.h index 02914bcad506..ed4fcd117e5d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.c index 648e6699724a..889262e5ccf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.h index 1876bf470892..5c01aceb3470 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.c index c43a9c28d95f..8d788cad9f68 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.h index 89484610ab2f..bbbdfc6b0907 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.c index d5c5c4771269..c0ed795cd81b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.h index 361c44368edb..d879f6234a56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8703b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.c index 265ef130af0d..0effd8656627 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.h index 8e70ac6636c2..5575bb5e87f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.c index 6273bcc75fa0..aa58bc1f9f90 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.h index de7a9bda4e60..348dae834199 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.c index b911f31dbcfe..cd8ff0a8b31a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.h index c4ec1a4c8f16..44698240fd54 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.c index 34ebffb810a7..8aab78d75da0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.h index ac86e98dc562..53e52f3d2471 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.c index c840c7792653..269edc27cb3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.h index 4c7469ef67c8..684e9468ce18 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.c index f107bb8485c3..0943586975d3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.h index 6b465e33ecd1..99cd0409036a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.c index bd60df4ebb24..a8111a2d22fb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.h index aeebf82196da..ef304b138c06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A_CSR 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtcOutSrc.h index 6dbdcec29b1f..13ea845260c2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/btc/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/efuse/efuse_mask.h index 9611e48f4408..866c605d8312 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.c index 6410a03b431a..346931549830 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.h index 1d4bf83c7d40..a1f1079a0a06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_BEAMFORMING_H #define __INC_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/hal8188freg.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/hal8188freg.h index 40b1a0a4cf63..6284f863b213 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/hal8188freg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/hal8188freg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/version_rtl8188f.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/version_rtl8188f.h index f8709ad70991..83f136832bf8 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/version_rtl8188f.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/rtl8188f/version_rtl8188f.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8188F PHY Parameters*/ /* [Caution] diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.c index 426a1933bc7b..535a6ff7ef81 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.h index abb9d594fafd..610bec3ff0e5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.c index 754686bfe0d5..311f91e3ad36 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.h index 406c2d6e06b8..64c4af860041 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.c index 3aa7b82421d2..e3653d45feb4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.h index 7efdc025ce2e..e13d33cc53b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.c index eff8e984ab7d..e7e85c07196d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /*Description:*/ /*This file is for 8812/8821/8811 TXBF mechanism*/ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.h index c92d79a3dd84..f54b7fca17f3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8821b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8821B_H__ #define __HAL_TXBF_8821B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.c index caa18a9c6244..5a97a4a22aa4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.h index bc22bcef10f7..8709d3e14814 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.c index badd23b4c9aa..5b80cd141165 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.h index 0318ad369cbe..35ad3cf20c44 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.c index 2f18aa9ba3c3..404953f976f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.h index 49a5fdff1e6a..3879a4f637ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/Hal8188FPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/Hal8188FPwrSeq.c index 277f85b21e6b..13f210a6fdfe 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/Hal8188FPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/Hal8188FPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8188FPwrSeq.h index b6d0c59aa7b2..9686d1e33e96 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPhyReg.h index 20627341815e..5f5d4586dc4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPwrSeq.h index 7acc0d187175..07d4c4ee7da3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8703BPwrSeq.h index c61519aa7d43..84a0d989d40e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723BPwrSeq.h index d2124454a8af..c3bb0e95e586 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723PwrSeq.h index 307ac90d1373..b2b2489d370f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8821APwrSeq.h index 840dd742ed3b..b70c59381d2b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/custom_gpio.h index c76b340ff75b..5499a2d38c47 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_version.h index 210ce338ca3e..e4510e1510bd 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.3.23.6_20964.20170110" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wapi.h index 582410c6965f..cf1111cfe963 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wifi_regd.h index aea6365290f8..13679b809803 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/os_dep/linux/wifi_regd.c index 154a28fa4bf9..1adcfe6d10e1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8189es/Kconfig index 4b53bc8bff0d..caede6065e3b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8189ES tristate "Realtek 8189E SDIO WiFi" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8189es/Makefile index c9b89c97f1d9..6c71051d7af2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi.c index d4835daadb96..a7d574cc46d1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi_sms4.c index 6126ed9a00c6..75f10ab4752e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.c index 86e006dba32b..bcde0c67b4da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.h index 02914bcad506..ed4fcd117e5d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.c index 648e6699724a..889262e5ccf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.h index 1876bf470892..5c01aceb3470 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.c index bdc2713c935e..a0ef0feeb072 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.h index b7d2d76b2ca5..68484a391e33 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.c index d5c5c4771269..c0ed795cd81b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.h index 361c44368edb..d879f6234a56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8703b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.c index 265ef130af0d..0effd8656627 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.h index 8e70ac6636c2..5575bb5e87f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.c index 6273bcc75fa0..aa58bc1f9f90 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.h index de7a9bda4e60..348dae834199 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.c index b911f31dbcfe..cd8ff0a8b31a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.h index c4ec1a4c8f16..44698240fd54 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.c index 34ebffb810a7..8aab78d75da0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.h index ac86e98dc562..53e52f3d2471 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.c index c840c7792653..269edc27cb3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.h index 4c7469ef67c8..684e9468ce18 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.c index 759418ea69ad..18c3abb29c1e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.h index 6b465e33ecd1..99cd0409036a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.c index bd60df4ebb24..a8111a2d22fb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.h index aeebf82196da..ef304b138c06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A_CSR 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtcOutSrc.h index 83d6b9ea4495..f2a5c11d7e30 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/btc/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/efuse/efuse_mask.h index 9611e48f4408..866c605d8312 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c index fa7ecd85f0d3..5a040df76160 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.h index 1f001e5949e3..2f5608625289 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_BEAMFORMING_H #define __INC_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.c index 50fa1536281e..7f2621d2ad13 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.h index d11f2283ea28..3dbd1ed3108a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/rtl8188e/hal8188erateadaptive.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_RA_H #define __INC_RA_H /*++ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8188FPwrSeq.h index b6d0c59aa7b2..9686d1e33e96 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPhyReg.h index 02a3f865a96b..dce3c8fbc7b7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPwrSeq.h index 7acc0d187175..07d4c4ee7da3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8703BPwrSeq.h index c61519aa7d43..84a0d989d40e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723BPwrSeq.h index d2124454a8af..c3bb0e95e586 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723PwrSeq.h index 307ac90d1373..b2b2489d370f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8821APwrSeq.h index 840dd742ed3b..b70c59381d2b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/custom_gpio.h index c76b340ff75b..5499a2d38c47 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_version.h index d6267a68214e..ccebb16c0cd9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.3.18.4_22798.20170620" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wapi.h index 582410c6965f..cf1111cfe963 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wifi_regd.h index aea6365290f8..13679b809803 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/wifi_regd.c index 154a28fa4bf9..1adcfe6d10e1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8189fs/Kconfig index 0684b5971fb0..6d184f6d8444 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8189FS tristate "Realtek 8189F SDIO WiFi" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8189fs/Makefile index 5ea67785573e..8bd53d427a40 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi.c index d4835daadb96..a7d574cc46d1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi_sms4.c index 6126ed9a00c6..75f10ab4752e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.c index 86e006dba32b..bcde0c67b4da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.h index 02914bcad506..ed4fcd117e5d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.c index 648e6699724a..889262e5ccf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.h index 1876bf470892..5c01aceb3470 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.c index ccc67ee85a3e..2feeb6ad9454 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.h index 89484610ab2f..bbbdfc6b0907 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.c index d5c5c4771269..c0ed795cd81b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.h index 361c44368edb..d879f6234a56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8703b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.c index 265ef130af0d..0effd8656627 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.h index 8e70ac6636c2..5575bb5e87f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.c index 6273bcc75fa0..aa58bc1f9f90 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.h index de7a9bda4e60..348dae834199 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.c index b911f31dbcfe..cd8ff0a8b31a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.h index c4ec1a4c8f16..44698240fd54 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.c index 34ebffb810a7..8aab78d75da0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.h index ac86e98dc562..53e52f3d2471 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.c index c840c7792653..269edc27cb3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.h index 4c7469ef67c8..684e9468ce18 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.c index f107bb8485c3..0943586975d3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.h index 6b465e33ecd1..99cd0409036a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.c index bd60df4ebb24..a8111a2d22fb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.h index aeebf82196da..ef304b138c06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A_CSR 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtcOutSrc.h index 6dbdcec29b1f..13ea845260c2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/btc/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/efuse/efuse_mask.h index 9611e48f4408..866c605d8312 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.c index 6410a03b431a..346931549830 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.h index 1d4bf83c7d40..a1f1079a0a06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_BEAMFORMING_H #define __INC_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/hal8188freg.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/hal8188freg.h index 40b1a0a4cf63..6284f863b213 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/hal8188freg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/hal8188freg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/version_rtl8188f.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/version_rtl8188f.h index c27a0536a3aa..bcf778cfba8c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/version_rtl8188f.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/rtl8188f/version_rtl8188f.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8188F PHY Parameters*/ /* [Caution] diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.c index 426a1933bc7b..535a6ff7ef81 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.h index abb9d594fafd..610bec3ff0e5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.c index 754686bfe0d5..311f91e3ad36 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.h index 406c2d6e06b8..64c4af860041 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.c index d7e254518f75..b47270312b01 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.h index 7efdc025ce2e..e13d33cc53b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.c index eff8e984ab7d..e7e85c07196d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /*Description:*/ /*This file is for 8812/8821/8811 TXBF mechanism*/ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.h index c92d79a3dd84..f54b7fca17f3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8821b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8821B_H__ #define __HAL_TXBF_8821B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c index caa18a9c6244..5a97a4a22aa4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.h index bc22bcef10f7..8709d3e14814 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.c index badd23b4c9aa..5b80cd141165 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.h index 0318ad369cbe..35ad3cf20c44 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.c index 2f18aa9ba3c3..404953f976f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.h index 49a5fdff1e6a..3879a4f637ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/Hal8188FPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/Hal8188FPwrSeq.c index 277f85b21e6b..13f210a6fdfe 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/Hal8188FPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/Hal8188FPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8188FPwrSeq.h index b6d0c59aa7b2..9686d1e33e96 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPhyReg.h index 20627341815e..5f5d4586dc4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPwrSeq.h index 7acc0d187175..07d4c4ee7da3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8703BPwrSeq.h index c61519aa7d43..84a0d989d40e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723BPwrSeq.h index d2124454a8af..c3bb0e95e586 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723PwrSeq.h index 307ac90d1373..b2b2489d370f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8821APwrSeq.h index 840dd742ed3b..b70c59381d2b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/custom_gpio.h index c76b340ff75b..5499a2d38c47 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_version.h index 8d47e51feec0..d0471b2c8a6c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.3.24.8_22657.20170607" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wapi.h index 582410c6965f..cf1111cfe963 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wifi_regd.h index aea6365290f8..13679b809803 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/os_dep/linux/wifi_regd.c index 154a28fa4bf9..1adcfe6d10e1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig old mode 100755 new mode 100644 index a0bbb8da70e4..b40363bee23f --- a/drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8192cu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8192CU tristate "Realtek 8192CU USB WiFi Support" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile old mode 100755 new mode 100644 index 4105a703026e..33a337f02d52 --- a/drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8192cu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192cu/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8192cu/include/rtw_version.h index 4fb9dd437109..452e4fea201a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192cu/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8192cu/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.0.2_9000.20130911" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h b/drivers/net/wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h old mode 100755 new mode 100644 index 1a50dc40e647..630fc12741b0 --- a/drivers/net/wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8192cu/os_dep/linux/wifi_version.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Yongle Lai @ Rockchip */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8192du/Kconfig index 4bc9acf42dbc..9267a229bc90 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8192DU tristate "Realtek 8192DU USB WiFi Support" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8192du/Makefile index 550699a2c197..a7b13279e0be 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 -Wframe-larger-than=1200 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_version.h index bf4aed90c970..a702c5200ad7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.0.4_10867.20140321_beta" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_wifi_regd.h index 8b28be34b0ae..382210a7a816 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_regd.c index e7f8d534f954..3fbde22bd280 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_version.h b/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_version.h index b09fa9d3de1c..33c5b6248c7d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8192du/os_dep/linux/wifi_version.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Yongle Lai @ Rockchip */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig old mode 100755 new mode 100644 index 43f9697fa814..91d27185bcae --- a/drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723as/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723AS tristate "Realtek 8723AS SDIO WiFi Support" depends on WLAN_80211 && MMC diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig old mode 100755 new mode 100644 index b469e2747948..a06f2d820792 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723AU tristate "Realtek 8723AU USB WiFi Support" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile old mode 100755 new mode 100644 index 77d4badb9b41..60e605079519 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 -Wframe-larger-than=1200 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c old mode 100755 new mode 100644 index d4835daadb96..a7d574cc46d1 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c old mode 100755 new mode 100644 index 6126ed9a00c6..75f10ab4752e --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c old mode 100755 new mode 100644 index 83a07d3f7543..f87b55fe58b0 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*Created on 2011/ 6/16, 6: 8*/ #include "../odm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h old mode 100755 new mode 100644 index b237bcaea6b7..a75b1edc621b --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CEMACImg_CE.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8192CE_MAC_IMG_H #define __INC_HAL8192CE_MAC_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c old mode 100755 new mode 100644 index ff4856de3856..9fe2143a3531 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*Created on 2011/ 6/16, 6: 8*/ #include "../odm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h old mode 100755 new mode 100644 index 869025a98f1a..60867c7c33e5 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8192c/Hal8192CUMACImg_CE.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8192CU_MAC_IMG_H #define __INC_HAL8192CU_MAC_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h old mode 100755 new mode 100644 index 08cf946bf0d7..3d6aeb10ff3b --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723SHWImg_CE.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8723S_FW_IMG_H #define __INC_HAL8723S_FW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h old mode 100755 new mode 100644 index 0449eb783784..43ad55caa20d --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/OUTSRC/rtl8723a/Hal8723UHWImg_CE.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8723U_FW_IMG_H #define __INC_HAL8723U_FW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c old mode 100755 new mode 100644 index 97255cd3bc88..befd88b5ef63 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/hal/rtl8723a/Hal8723PwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h old mode 100755 new mode 100644 index ab1c32a014a0..a66d54e13cf8 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h old mode 100755 new mode 100644 index c76b340ff75b..5499a2d38c47 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h old mode 100755 new mode 100644 index d8ebbe51bbe1..4323e1e3958a --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.1.11_12622.20141215_BTCOEX20140409_ver3.5" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h old mode 100755 new mode 100644 index f72c666dd226..11c1459f5f61 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h old mode 100755 new mode 100644 index 73db7e4760ae..20ad9c35e475 --- a/drivers/net/wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723au/os_dep/linux/wifi_version.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Yongle Lai @ Rockchip */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig old mode 100755 new mode 100644 index 9f38cb75f395..4550106824f0 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723BS_VQ0 tristate "Realtek 8723BS-VQ0 COB WiFi" ---help--- diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile old mode 100755 new mode 100644 index 42f41762b443..f24ce83de74a --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 -Wframe-larger-than=1200 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c old mode 100755 new mode 100644 index d4835daadb96..a7d574cc46d1 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c old mode 100755 new mode 100644 index 6126ed9a00c6..75f10ab4752e --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c old mode 100755 new mode 100644 index 6e9454ca5cca..9a109778d0ea --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h old mode 100755 new mode 100644 index ce7ec564414f..64e55aa01bf0 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c old mode 100755 new mode 100644 index cb60379c9a86..6e18fda61218 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h old mode 100755 new mode 100644 index 85fd6742ca2f..d21fd68db5d2 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c old mode 100755 new mode 100644 index 12dfe4b210eb..ebde19d3ff3d --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h old mode 100755 new mode 100644 index 8792ec8d381c..ac1b68cb37d9 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E_1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c old mode 100755 new mode 100644 index 8bde294c93f2..9f2ab2438437 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h old mode 100755 new mode 100644 index 58cddce87a41..32aaf8a47bee --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c old mode 100755 new mode 100644 index 8ea08e87d3de..6f677f3e7131 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h old mode 100755 new mode 100644 index e8c2fd003fee..e4f6b6d64c09 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c old mode 100755 new mode 100644 index ffe117596f5b..8c18b578155d --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h old mode 100755 new mode 100644 index f0cc8b546972..3d0d9deebbc2 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c old mode 100755 new mode 100644 index bada4139b1f2..0d621307f531 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h old mode 100755 new mode 100644 index 248874d55f56..45c8235ed62f --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c old mode 100755 new mode 100644 index c0ced8e21a89..60891a7f9718 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h old mode 100755 new mode 100644 index 2c049f9fcebf..f12336a48c90 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c old mode 100755 new mode 100644 index d081053b8c5c..a4b9e1813a22 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h old mode 100755 new mode 100644 index 4f2df7a6033d..9fba3f5ac1be --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A_1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c old mode 100755 new mode 100644 index 82029305e9b1..fbe39f693cf4 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h old mode 100755 new mode 100644 index 4f6f5d1210c7..61771447aedb --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c old mode 100755 new mode 100644 index c05c7668623d..053a949c062c --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h old mode 100755 new mode 100644 index 4c7469ef67c8..684e9468ce18 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c old mode 100755 new mode 100644 index 14ad651a9eb3..bc756ffe268c --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h old mode 100755 new mode 100644 index 3da55176f5ba..805ff42dc59f --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c old mode 100755 new mode 100644 index 824b8fbb0f69..f88ed31722c6 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h old mode 100755 new mode 100644 index aeebf82196da..ef304b138c06 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A_CSR 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h old mode 100755 new mode 100644 index d74397076ee5..fbd0919d2412 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h old mode 100755 new mode 100644 index c92a04864b91..30f1d330afea --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/OUTSRC/rtl8723b/Hal8723BReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c old mode 100755 new mode 100644 index 5f2a976a2ac4..d419a679cb0a --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/hal/rtl8723b/Hal8723BPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h old mode 100755 new mode 100644 index 02a3f865a96b..dce3c8fbc7b7 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h old mode 100755 new mode 100644 index 7acc0d187175..07d4c4ee7da3 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h old mode 100755 new mode 100644 index d2124454a8af..c3bb0e95e586 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h old mode 100755 new mode 100644 index 307ac90d1373..b2b2489d370f --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h old mode 100755 new mode 100644 index 840dd742ed3b..b70c59381d2b --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h old mode 100755 new mode 100644 index c76b340ff75b..5499a2d38c47 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h old mode 100755 new mode 100644 index 514a5ceda020..b0c411211096 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.3.9_12575.20141104_BTCOEX20140929-5443" #define BTCOEXVERSION "BTCOEX20140929-5443" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h old mode 100755 new mode 100644 index 582410c6965f..cf1111cfe963 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h old mode 100755 new mode 100644 index aea6365290f8..13679b809803 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c old mode 100755 new mode 100644 index 04ffe781a410..645895e8ee85 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h old mode 100755 new mode 100644 index dbe1554100fe..eb02621f3519 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs-vq0/os_dep/linux/wifi_version.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Yongle Lai @ Rockchip */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Kconfig index 70db25ba9959..19d980ffe62c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723BS tristate "Realtek 8723B SDIO or SPI WiFi" ---help--- diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile index da844039b11b..b1403a8e22af 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi.c index d4835daadb96..a7d574cc46d1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi_sms4.c index 6126ed9a00c6..75f10ab4752e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.c index 8a4d9777f0ff..3bb9b10ea383 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.h index e75127c10a6d..cddf396840da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.c index 76e0e937dee6..83d873028f75 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.h index 5a4786a5e4a3..eccf9b6b04ae 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.c index 9d610e3a9e0a..9f9f66b27c0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.h index 28fcfcaa26e1..3d584fa00b05 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.c index d5c5c4771269..c0ed795cd81b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.h index 361c44368edb..d879f6234a56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8703b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.c index 4ae0856b6118..528007c38ea4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.h index 9a2ad23e617d..3b754a623e79 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.c index 2c34f678a807..f0f8f0fd5d40 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.h index 4fe39b295b9c..8a45a899d960 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.c index e094caa62658..fe0270015ea5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.h index e786d375d7c8..7fbf445e0efb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.c index cd8a547e9746..1c0381c52b6f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.h index be08dd391258..4952aab1bae1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.c index 81ddf035143d..87d2f77b8cf1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.h index 6c9c327e34b9..e9c83eade55b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.c index 010a422001b1..105cafd26114 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.h index 73252dd1fb9c..6af9608f2fab 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.c index b69d156689fc..81410fe2ad0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.h index 8d228fb17454..6880768f1b97 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtcOutSrc.h index 25252c8dacbd..768260c584ae 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/btc/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/efuse/efuse_mask.h index 9611e48f4408..866c605d8312 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.c index 6410a03b431a..346931549830 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.h index 1d4bf83c7d40..a1f1079a0a06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_BEAMFORMING_H #define __INC_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/hal8723breg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/hal8723breg.h index e572a235d094..7a3963d70067 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/hal8723breg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/hal8723breg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/version_rtl8723b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/version_rtl8723b.h index e13787376b52..70c7d2cd40da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/version_rtl8723b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/rtl8723b/version_rtl8723b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8723B PHY Parameters*/ #define SVN_COMMIT_VERSION_8723B 26 #define RELEASE_DATE_8723B 20150617 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.c index 426a1933bc7b..535a6ff7ef81 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.h index abb9d594fafd..610bec3ff0e5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.c index 754686bfe0d5..311f91e3ad36 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.h index 406c2d6e06b8..64c4af860041 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.c index d7e254518f75..b47270312b01 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.h index 7efdc025ce2e..e13d33cc53b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.c index eff8e984ab7d..e7e85c07196d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /*Description:*/ /*This file is for 8812/8821/8811 TXBF mechanism*/ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.h index c92d79a3dd84..f54b7fca17f3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8821b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8821B_H__ #define __HAL_TXBF_8821B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.c index caa18a9c6244..5a97a4a22aa4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.h index bc22bcef10f7..8709d3e14814 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.c index badd23b4c9aa..5b80cd141165 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.h index 0318ad369cbe..35ad3cf20c44 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.c index 2f18aa9ba3c3..404953f976f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.h index 49a5fdff1e6a..3879a4f637ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/Hal8723BPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/Hal8723BPwrSeq.c index 5f2a976a2ac4..d419a679cb0a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/Hal8723BPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/Hal8723BPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8188FPwrSeq.h index b6d0c59aa7b2..9686d1e33e96 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPhyReg.h index 20627341815e..5f5d4586dc4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPwrSeq.h index 7acc0d187175..07d4c4ee7da3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8703BPwrSeq.h index c61519aa7d43..84a0d989d40e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723BPwrSeq.h index d2124454a8af..c3bb0e95e586 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723PwrSeq.h index 307ac90d1373..b2b2489d370f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8821APwrSeq.h index 840dd742ed3b..b70c59381d2b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/custom_gpio.h index c76b340ff75b..5499a2d38c47 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_version.h index c069ab41cadf..ef5a2f636d72 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.4.2_17831.20160519_BTCOEX20151223-654a" #define BTCOEXVERSION "BTCOEX20151223-654a" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wapi.h index 582410c6965f..cf1111cfe963 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wifi_regd.h index aea6365290f8..13679b809803 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/wifi_regd.c index 154a28fa4bf9..1adcfe6d10e1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig old mode 100755 new mode 100644 index fdef0094743a..1b83762cfb74 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723BU tristate "Realtek 8723B USB WiFi" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile old mode 100755 new mode 100644 index acd4feb584b8..541757cdbc4d --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c old mode 100755 new mode 100644 index d4835daadb96..a7d574cc46d1 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c old mode 100755 new mode 100644 index 6126ed9a00c6..75f10ab4752e --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.c index 8a4d9777f0ff..3bb9b10ea383 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.h index e75127c10a6d..cddf396840da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.c index 76e0e937dee6..83d873028f75 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.h index 5a4786a5e4a3..eccf9b6b04ae 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.c index 9d610e3a9e0a..9f9f66b27c0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.h index 28fcfcaa26e1..3d584fa00b05 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.c index d5c5c4771269..c0ed795cd81b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.h index 361c44368edb..d879f6234a56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8703b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8703B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.c index 7e35172267ad..4129b86f9b03 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.h index 6ff7ef5d2dbe..634616b5e71c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.c index 2c34f678a807..f0f8f0fd5d40 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.h index 4fe39b295b9c..8a45a899d960 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.c index e094caa62658..fe0270015ea5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.h index e786d375d7c8..7fbf445e0efb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.c index cd8a547e9746..1c0381c52b6f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.h index be08dd391258..4952aab1bae1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.c index 81ddf035143d..87d2f77b8cf1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.h index 6c9c327e34b9..e9c83eade55b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.c index 010a422001b1..105cafd26114 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.h index 73252dd1fb9c..6af9608f2fab 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.c index b69d156689fc..81410fe2ad0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.h index 8d228fb17454..6880768f1b97 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtcOutSrc.h index 32055feb588f..5bb22df82321 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/btc/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h old mode 100755 new mode 100644 index 9611e48f4408..866c605d8312 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.c index 6410a03b431a..346931549830 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.h index 1d4bf83c7d40..a1f1079a0a06 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_BEAMFORMING_H #define __INC_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/hal8723breg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/hal8723breg.h index e572a235d094..7a3963d70067 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/hal8723breg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/hal8723breg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/version_rtl8723b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/version_rtl8723b.h index e13787376b52..70c7d2cd40da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/version_rtl8723b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/rtl8723b/version_rtl8723b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8723B PHY Parameters*/ #define SVN_COMMIT_VERSION_8723B 26 #define RELEASE_DATE_8723B 20150617 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.c index 426a1933bc7b..535a6ff7ef81 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.h index abb9d594fafd..610bec3ff0e5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.c index 754686bfe0d5..311f91e3ad36 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.h index 406c2d6e06b8..64c4af860041 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.c index d7e254518f75..b47270312b01 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.h index 7efdc025ce2e..e13d33cc53b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.c index eff8e984ab7d..e7e85c07196d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /*Description:*/ /*This file is for 8812/8821/8811 TXBF mechanism*/ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.h index c92d79a3dd84..f54b7fca17f3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8821b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8821B_H__ #define __HAL_TXBF_8821B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.c index caa18a9c6244..5a97a4a22aa4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.h index bc22bcef10f7..8709d3e14814 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ #if (BEAMFORMING_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.c index badd23b4c9aa..5b80cd141165 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.h index 0318ad369cbe..35ad3cf20c44 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.c index 2f18aa9ba3c3..404953f976f5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.h index 49a5fdff1e6a..3879a4f637ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c old mode 100755 new mode 100644 index 5f2a976a2ac4..d419a679cb0a --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/Hal8723BPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8188FPwrSeq.h index b6d0c59aa7b2..9686d1e33e96 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPhyReg.h index 20627341815e..5f5d4586dc4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPwrSeq.h index 7acc0d187175..07d4c4ee7da3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8703BPwrSeq.h index c61519aa7d43..84a0d989d40e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h old mode 100755 new mode 100644 index d2124454a8af..c3bb0e95e586 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723PwrSeq.h index 307ac90d1373..b2b2489d370f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8821APwrSeq.h index 840dd742ed3b..b70c59381d2b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h old mode 100755 new mode 100644 index c76b340ff75b..5499a2d38c47 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h old mode 100755 new mode 100644 index 0c80d7239298..cd3a0b7edd29 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.4.2_18635.20161006_BTCOEX20151228-664a" #define BTCOEXVERSION "BTCOEX20151228-664a" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h old mode 100755 new mode 100644 index 582410c6965f..cf1111cfe963 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h old mode 100755 new mode 100644 index aea6365290f8..13679b809803 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c old mode 100755 new mode 100644 index 154a28fa4bf9..1adcfe6d10e1 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723cs/Kconfig index 4986677f669e..78e5f124ca80 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723CS tristate "Realtek 8723C SDIO or SPI WiFi" ---help--- diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723cs/Makefile index cbfbe5ada474..b14fed53b49a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi.c index d23ed2682c3f..186c4206efe2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi_sms4.c index fc01212ecfe3..01762acc22b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.c index 38c89d10caf6..88b68716b9dc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.h index e75127c10a6d..cddf396840da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.c index 312877dd9b28..4e80a00858f1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.h index 00fed716141d..30aa455ccb3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8192e2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.c index eb242bf03b3c..838e3f4e6b50 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.h index 35ba9324b98a..c6602353df60 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8703b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.c index 98b12ac442fc..c3de3d31ae87 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.h index af476d9659d1..9d610124b767 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.c index 3b1dd4a53344..f4f9a99f7b8b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.h index b44959cf02dd..4b7da302fa34 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.c index 9be8d62305b3..87989e1eb48c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.h index 0265ab3df0dd..8e5cf17a93d9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723bwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8723BWIFIONLYHWCFG_H #define __INC_HAL8723BWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.c index 80d4ca5347ed..7af3c87d1719 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.h index 76edd5a30f2f..2408e1f68c24 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.c index da21d953931a..c489b52bc49e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.h index 1472796e6ce0..b0fe6f8013fd 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8723d2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.c index f1cefab2e5de..dfe2c6558177 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.h index e786d375d7c8..7fbf445e0efb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.c index 038405b62c30..96a412ef8fd1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.h index fa19aaf67a76..26db0e85bd0f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8812a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.c index bba78ae0f410..3451a5185023 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.h index 53a531348eef..75e6f708047f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.c index 80efc338f2ec..0ca35add2367 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.h index 81513976951a..a4997fe58cde 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.c index 34b1305f3611..7377db9b3f43 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.h index f712494e6f53..24c7835781b0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.c index 5bae8161fb31..984f0692bbcc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.h index f89b1fa51e04..94a40078ab3d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821c2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.c index 6de8db015f85..0291a2f9a4b7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" static struct rfe_type_8821c_wifi_only gl_rfe_type_8821c_1ant; diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.h index afa2b2f84b71..65c57c641616 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8821cwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8821CWIFIONLYHWCFG_H #define __INC_HAL8821CWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.c index 50673e7a59c8..167c9930c4e7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.h index e84a27e87515..05f7253530df 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.c index 6f3d6b5680bc..82927981ae62 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.h index 875733436c9d..0a20d7555618 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.c index 35004d731338..214fc8b61b84 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.h index 3f5ef3bc1a3e..71a1b7e81dc3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtc8822bwifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HAL8822BWIFIONLYHWCFG_H #define __INC_HAL8822BWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtcoutsrc.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtcoutsrc.h index 7e8e4c673f38..07253da41c05 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtcoutsrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/btc/halbtcoutsrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/efuse/efuse_mask.h index faafed48f009..849a4e49d0bf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_btcoex_wifionly.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_btcoex_wifionly.c index 861bcfb4ba44..838bb97fc7c3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_btcoex_wifionly.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_btcoex_wifionly.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "btc/mp_precomp.h" #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/halhwimg.h index 14a9f63f55d4..cca28990f647 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.c index c0832a02d8cb..e24b0b74ca35 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.h index 2acd0f533609..6ebd7f6d7195 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_adc_sampling.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_ADCSMP_H #define __INC_ADCSMP_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.c index 529e751ccd40..1eb81d05e448 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.h index 8a9093814217..6f5747a93d6c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_PHYDM_BEAMFORMING_H #define __INC_PHYDM_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.c index a6164fb7a4fb..4564d228e073 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.h index 5641b738813b..f4cf0d031eb1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/phydm_ccx.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __PHYDMCCX_H__ #define __PHYDMCCX_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/rtl8703b/version_rtl8703b.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/rtl8703b/version_rtl8703b.h index d30ef19d0d6d..fab4934825a6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/rtl8703b/version_rtl8703b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/rtl8703b/version_rtl8703b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8703B PHY Parameters*/ /* [Caution] diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.c index 1536778f70c3..82cc53b61a8c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.h index 0ce056d006a2..691d1744ec85 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.c index eee072951b37..c9ac950ad76e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.h index 618ca809f0c1..87740119313b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.c index 8ab72d2200c1..894e6deb3522 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.h index bb72401add2e..3958be756fe8 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.c index df72b5576570..1ab5c52c0d62 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.h index 6d2af5470c05..d416e8b9d0ea 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.c index cce430ee1337..905dce6ffe8e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.h index e888724795b9..7ffe538c66bf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.c index 379c26eb2bb6..d56e0b6c42bb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.h index 7c7f73ed391a..045dd6647806 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ #if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/phydm_hal_txbf_api.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/phydm_hal_txbf_api.c index 317204db2a26..6f1f74b9cce6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/phydm_hal_txbf_api.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/phydm/txbf/phydm_hal_txbf_api.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/Hal8703BPwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/Hal8703BPwrSeq.c index 2cc47fefaf49..e416db5f946c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/Hal8703BPwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/Hal8703BPwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8188FPwrSeq.h index 81e613227bdb..59aba21de9a5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPhyReg.h index cd13c22bc398..b69ccd01c901 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPwrSeq.h index 12bb2fb6be05..9332505c84c0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8703BPwrSeq.h index a53ca9a0767a..fb36455f3279 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723BPwrSeq.h index 6b895621e1c5..d18d064dae0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723DPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723DPwrSeq.h index 5032e7cafebf..74debbaac9ee 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723DPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723DPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723D #define REALTEK_POWER_SEQUENCE_8723D diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723PwrSeq.h index 6669641e8767..e463f74b7ae3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8821APwrSeq.h index 393068b3f3cf..091c2e56d967 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/custom_gpio.h index 5691d9a1c6cc..54e491872992 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/hal_btcoex_wifionly.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/hal_btcoex_wifionly.h index 2633d9585b91..89b3ad5321c9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/hal_btcoex_wifionly.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/hal_btcoex_wifionly.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_WIFIONLY_H__ #define __HALBTC_WIFIONLY_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_version.h index 80f296cff7f1..9c417f42a2d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v5.2.1.7_25082.20171108_COEX20170626-1a00_wifi_hal" #define BTCOEXVERSION "COEX20170626-1a00" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wapi.h index 635aec0db4ee..216ab6997c04 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wifi_regd.h index 2182712648bd..541a211f9511 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/os_dep/linux/wifi_regd.c index 2f6f5b1d067e..d79e3a30e7d4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8723ds/Kconfig index 63bbe8e63c37..9d5b17c9b892 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723DS tristate "Realtek 8723D SDIO or SPI WiFi" ---help--- diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723ds/Makefile index 561832a87989..fcd0c27cfd1d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.c index 1db3b7364918..272efc97c0c9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.h index 0ba11936dcc6..0136de48dc6d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.c index d111bcf67ad6..d20631876bda 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.h index 56567ebabb62..9fb0a4637bd3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8822b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/ap_makefile.mk b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/ap_makefile.mk index 566c74cdc7c0..9f8fa2504172 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/ap_makefile.mk +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/ap_makefile.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 _PHYDM_FILES :=\ phydm/phydm.o \ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.c index 3ab8189c496e..9acc8e9e6885 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.h b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.h index d7016dfdc647..df5446e43ff3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/halrf/halrf_txgapcal.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ void odm_tx_gain_gap_calibration( void *p_dm_void diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/phydm.mk b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/phydm.mk index 15bdad8e5bc8..f272636bcdc0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/phydm.mk +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/phydm.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += -I$(src)/hal/phydm _PHYDM_FILES := hal/phydm/phydm_debug.o \ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/rtl8723d/version_rtl8723d.h b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/rtl8723d/version_rtl8723d.h index 2bb4856f1e76..bde7025c93bc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/rtl8723d/version_rtl8723d.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/phydm/rtl8723d/version_rtl8723d.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8723D PHY Parameters*/ #define RELEASE_DATE_8723D 20170824 #define COMMIT_BY_8723D "BB_Jessica" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8723ds/include/rtw_version.h index 4467cb239648..45f786493ffa 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v5.2.15.1_25011.20171107_COEX20171025-2020" #define BTCOEXVERSION "COEX20171025-2020" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig old mode 100755 new mode 100644 index c03d084041f7..ca7f5379786e --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8812AU tristate "Realtek 8812AU USB WiFi Support" depends on USB diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile old mode 100755 new mode 100644 index c70766234273..0233dff9f108 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c old mode 100755 new mode 100644 index d4835daadb96..a7d574cc46d1 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c old mode 100755 new mode 100644 index 6126ed9a00c6..75f10ab4752e --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c old mode 100755 new mode 100644 index 6e9454ca5cca..9a109778d0ea --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h old mode 100755 new mode 100644 index ce7ec564414f..64e55aa01bf0 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c old mode 100755 new mode 100644 index cb60379c9a86..6e18fda61218 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h old mode 100755 new mode 100644 index 85fd6742ca2f..d21fd68db5d2 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c old mode 100755 new mode 100644 index 12dfe4b210eb..ebde19d3ff3d --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h old mode 100755 new mode 100644 index 8792ec8d381c..ac1b68cb37d9 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E_1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c old mode 100755 new mode 100644 index 8bde294c93f2..9f2ab2438437 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h old mode 100755 new mode 100644 index 58cddce87a41..32aaf8a47bee --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192E 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c old mode 100755 new mode 100644 index 8ea08e87d3de..6f677f3e7131 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h old mode 100755 new mode 100644 index e8c2fd003fee..e4f6b6d64c09 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c old mode 100755 new mode 100644 index ffe117596f5b..8c18b578155d --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h old mode 100755 new mode 100644 index f0cc8b546972..3d0d9deebbc2 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c old mode 100755 new mode 100644 index ed9941fd0ec1..e4a51730a2fb --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h old mode 100755 new mode 100644 index f7ebc96e8bd9..a65a2bb9be96 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c old mode 100755 new mode 100644 index 096b30da729d..22132171a6cb --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h old mode 100755 new mode 100644 index 2c049f9fcebf..f12336a48c90 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723B 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c old mode 100755 new mode 100644 index d081053b8c5c..a4b9e1813a22 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h old mode 100755 new mode 100644 index 4f2df7a6033d..9fba3f5ac1be --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A_1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c old mode 100755 new mode 100644 index 82029305e9b1..fbe39f693cf4 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h old mode 100755 new mode 100644 index 4f6f5d1210c7..61771447aedb --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8812A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c old mode 100755 new mode 100644 index c05c7668623d..053a949c062c --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h old mode 100755 new mode 100644 index 4c7469ef67c8..684e9468ce18 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 1ANT BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c old mode 100755 new mode 100644 index 14ad651a9eb3..bc756ffe268c --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h old mode 100755 new mode 100644 index 3da55176f5ba..805ff42dc59f --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c old mode 100755 new mode 100644 index 824b8fbb0f69..f88ed31722c6 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h old mode 100755 new mode 100644 index aeebf82196da..ef304b138c06 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtc8821aCsr2Ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8821A_CSR 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h old mode 100755 new mode 100644 index 9da0b6746d02..d49442f3cc45 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c old mode 100755 new mode 100644 index 756481725dbd..f9882a1bc222 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/Hal8821APwrSeq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*++ Copyright (c) Realtek Semiconductor Corp. All rights reserved. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h old mode 100755 new mode 100644 index 02a3f865a96b..dce3c8fbc7b7 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h old mode 100755 new mode 100644 index 7acc0d187175..07d4c4ee7da3 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h old mode 100755 new mode 100644 index d2124454a8af..c3bb0e95e586 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h old mode 100755 new mode 100644 index 307ac90d1373..b2b2489d370f --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h old mode 100755 new mode 100644 index 840dd742ed3b..b70c59381d2b --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h old mode 100755 new mode 100644 index c76b340ff75b..5499a2d38c47 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h old mode 100755 new mode 100644 index 1d7025bd7844..4cda9b77a09d --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_version.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v4.3.8_12175.20140902" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h old mode 100755 new mode 100644 index 582410c6965f..cf1111cfe963 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h old mode 100755 new mode 100644 index aea6365290f8..13679b809803 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c old mode 100755 new mode 100644 index 04ffe781a410..645895e8ee85 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h b/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h old mode 100755 new mode 100644 index 73db7e4760ae..20ad9c35e475 --- a/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8812au/os_dep/linux/wifi_version.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Yongle Lai @ Rockchip */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/Kconfig b/drivers/net/wireless/rockchip_wlan/rtl8822be/Kconfig index 9cc4c2bd7792..f9fa9fa20998 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/Kconfig +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8822BE tristate "Realtek 8822B PCIE WiFi" depends on PCI diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8822be/Makefile index d82ed3d1bbd3..8737389936bf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -O1 #EXTRA_CFLAGS += -O3 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi.c index eb1605eb73a0..cae1ca47e709 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi_sms4.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi_sms4.c index fc01212ecfe3..01762acc22b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_wapi_sms4.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_WAPI_SUPPORT #include diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.c index d8d4a11fa8e2..ac82d7336115 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.h index ce7ec564414f..64e55aa01bf0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8188c2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8188C 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.c index 239c073c1b8b..6f8e68f48d1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.h index 85fd6742ca2f..d21fd68db5d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192d2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8192D 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.c index b19a1f155cb7..d4f41668dee6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.h index e75127c10a6d..cddf396840da 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.c index 76e0e937dee6..83d873028f75 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.h index 5a4786a5e4a3..eccf9b6b04ae 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8192e2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.c index 022566999824..98871d341e9d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.h index cf167a5c7a61..2f94a2a31f0c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8703b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.c index db5b42e48b3f..bcb2ffe91800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.h index e8c2fd003fee..e4f6b6d64c09 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 1Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.c index f32bd9f8e33e..b53a536d7a4e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.h index f0cc8b546972..3d0d9deebbc2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //=========================================== // The following is for 8723A 2Ant BT Co-exist definition //=========================================== diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.c index 565b3bb76232..02297a88de48 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.h index 19bac7b351e5..2ffb28b9e0ad 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.c index 2c34f678a807..f0f8f0fd5d40 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.h index 4fe39b295b9c..8a45a899d960 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.c index f877b2007c81..cda14ecd013e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.h index 2ccd575626ee..14dfbd100c32 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.c index a2801ae2ff37..2991bfc0e1ad 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.h index 15a56ce2c7cc..5a4ef37a06d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8723d2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.c index f5a4a6d6f42a..5c09578201c5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.h index e786d375d7c8..7fbf445e0efb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.c index c5c0186bb9b7..c121d517ae36 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.h index be08dd391258..4952aab1bae1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8812a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.c index 81ddf035143d..87d2f77b8cf1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.h index 6c9c327e34b9..e9c83eade55b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.c index db26f41ddb07..929696edcfd1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.h index 73252dd1fb9c..6af9608f2fab 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821a2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.c index acf641a4965c..3a282b4f6331 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.h index 8d228fb17454..6880768f1b97 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8821acsr2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.c index 11b96262a476..64597238497b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.h index 0d0ea72f6725..c874e3b60b46 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b1ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c index 442b0be82772..c35140199ed1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* ************************************************************ * Description: * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.h index dac2afd4da69..28a7f111e499 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if (BT_SUPPORT == 1 && COEX_SUPPORT == 1) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtcoutsrc.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtcoutsrc.h index b5e2de2fef50..9f6587dc747c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtcoutsrc.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtcoutsrc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/efuse/efuse_mask.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/efuse/efuse_mask.h index e1c38c1961df..a990be8e4225 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/efuse/efuse_mask.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/efuse/efuse_mask.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #if DEV_BUS_TYPE == RT_USB_INTERFACE diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_cfg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_cfg.h index 4386ec898ee0..8ef925b45feb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_cfg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_cfg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_8197F_CFG_H_ #define _HALMAC_8197F_CFG_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_pwr_seq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_pwr_seq.h index a4bb2ecb28c5..a10675bacd93 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_pwr_seq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_8197f_pwr_seq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef HALMAC_POWER_SEQUENCE_8197F #define HALMAC_POWER_SEQUENCE_8197F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f.h index 5c61b413a32d..bf9df5791274 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8197F_H_ #define _HALMAC_API_8197F_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_pcie.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_pcie.h index 1e546a6d1eed..a2eebe18e9c3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_pcie.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_pcie.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8197F_PCIE_H_ #define _HALMAC_API_8197F_PCIE_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_sdio.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_sdio.h index c6e59c3912ca..f61af18e59b9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_sdio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_sdio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8197F_SDIO_H_ #define _HALMAC_API_8197F_SDIO_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_usb.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_usb.h index 4bf5779785c4..2203b17674ad 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_usb.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_api_8197f_usb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8197F_USB_H_ #define _HALMAC_API_8197F_USB_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_func_8197f.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_func_8197f.h index 1432b41ded88..4f16ddf32438 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_func_8197f.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8197f/halmac_func_8197f.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_FUNC_8197F_H_ #define _HALMAC_FUNC_8197F_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_8821c_pwr_seq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_8821c_pwr_seq.h index c813530435de..b023d3af6175 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_8821c_pwr_seq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_8821c_pwr_seq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef HALMAC_POWER_SEQUENCE_8821C #define HALMAC_POWER_SEQUENCE_8821C diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c.h index c244cd339201..380b07a797be 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8821C_H_ #define _HALMAC_API_8821C_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_pcie.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_pcie.h index 0100303acb7d..bc1e42bae06e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_pcie.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_pcie.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8821C_PCIE_H_ #define _HALMAC_API_8821C_PCIE_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_sdio.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_sdio.h index baa7f47902b0..7246fbccb22f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_sdio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_sdio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8821C_SDIO_H_ #define _HALMAC_API_8821C_SDIO_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_usb.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_usb.h index ea1be953c289..c8a7ae74c548 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_usb.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_api_8821c_usb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8821C_USB_H_ #define _HALMAC_API_8821C_USB_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_func_8821c.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_func_8821c.h index 3c0364ce4102..9a4b4b923547 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_func_8821c.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8821c/halmac_func_8821c.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_FUNC_8821C_H_ #define _HALMAC_FUNC_8821C_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c index c26c88d7c044..6bd4ce29ff42 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "../halmac_88xx_cfg.h" #include "halmac_8822b_cfg.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h index 5f97169d2000..8de4ea649895 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef HALMAC_POWER_SEQUENCE_8822B #define HALMAC_POWER_SEQUENCE_8822B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h index f5a5194771f6..e5880867fbe8 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8822B_H_ #define _HALMAC_API_8822B_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c index 5b09c1078575..b44d28f74538 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "../halmac_88xx_cfg.h" #include "halmac_8822b_cfg.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h index 9c3763fd7b62..1986abc57062 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8822B_PCIE_H_ #define _HALMAC_API_8822B_PCIE_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c index 63fe7c13d94e..231758fbf040 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_8822b_cfg.h" /** diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h index 5d61a8bbfc32..9be196c23b79 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8822B_SDIO_H_ #define _HALMAC_API_8822B_SDIO_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c index 95f26c469cba..5740ec407c9e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "../halmac_88xx_cfg.h" #include "halmac_8822b_cfg.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h index 7105d8d38aa3..7df6ddec5566 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_8822B_USB_H_ #define _HALMAC_API_8822B_USB_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c index e2e27a191404..4570350746d3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_8822b_cfg.h" HALMAC_RET_STATUS diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h index 68654d9cc695..c31bd976d816 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_FUNC_8822B_H_ #define _HALMAC_FUNC_8822B_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_88xx_cfg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_88xx_cfg.h index f8669a4cb56d..4cc75b9e26f2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_88xx_cfg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_88xx_cfg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_88XX_CFG_H_ #define _HALMAC_88XX_CFG_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.c index 8337d6b04fdc..ca23b3fe4800 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_88xx_cfg.h" /** diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.h index 79262b60c566..72fc82763694 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_88XX_H_ #define _HALMAC_API_88XX_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.c index 76e5cd3825e1..59af8d4bf81c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_88xx_cfg.h" /** diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.h index 434d9bda3d6c..1d0cfcf416f6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_pcie.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_88XX_PCIE_H_ #define _HALMAC_API_88XX_PCIE_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.c index b5c9a8b14e0b..5b2f428c43f4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_88xx_cfg.h" /** diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.h index dbb4a0e256d1..5d3fad0123a2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_sdio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_88XX_SDIO_H_ #define _HALMAC_API_88XX_SDIO_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.c index f4a89196737c..42aca91c1622 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_88xx_cfg.h" /** diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.h index c3e9cf9fb09a..68c3f5133141 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_api_88xx_usb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_88XX_USB_H_ #define _HALMAC_API_88XX_USB_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.c index 612cd2cb6a17..36325f7ee8c4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_88xx_cfg.h" HALMAC_RET_STATUS diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.h index b085ed71cf32..a0f77032a2d6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_88xx/halmac_func_88xx.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_FUNC_88XX_H_ #define _HALMAC_FUNC_88XX_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.c index 93b7b48e2754..e3d042656571 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "halmac_2_platform.h" #include "halmac_type.h" #if HALMAC_PLATFORM_WINDOWS == 1 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.h index a10436ede44a..9c585e23466c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_api.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_API_H_ #define _HALMAC_API_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit2.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit2.h index e5191d86a9fb..8f665faae718 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit2.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit2.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RTL_WLAN_BITDEF_H__ #define __RTL_WLAN_BITDEF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8821c.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8821c.h index 5081766add36..1aab60706280 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8821c.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8821c.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HALMAC_BIT_8821C_H #define __INC_HALMAC_BIT_8821C_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8822b.h index 089f8d3013ba..f0dfb13f99a1 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_bit_8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HALMAC_BIT_8822B_H #define __INC_HALMAC_BIT_8822B_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_info.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_info.h index 4b821db1749a..cbdd6e83a6ce 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_info.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_FW_INFO_H_ #define _HALMAC_FW_INFO_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_ap.h index b2f9ecb4849e..3d878231e7b0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_FWOFFLOADC2HFORMAT_H2C_C2H_AP_H_ #define _HAL_FWOFFLOADC2HFORMAT_H2C_C2H_AP_H_ #define C2H_SUB_CMD_ID_C2H_DBG 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_nic.h index ff73963a02da..cea12bbdcafd 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_c2h_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_FWOFFLOADC2HFORMAT_H2C_C2H_NIC_H_ #define _HAL_FWOFFLOADC2HFORMAT_H2C_C2H_NIC_H_ #define C2H_SUB_CMD_ID_C2H_DBG 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_ap.h index 8e5e6a10b2be..3df8e70681be 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_FWOFFLOADH2CFORMAT_H2C_C2H_AP_H_ #define _HAL_FWOFFLOADH2CFORMAT_H2C_C2H_AP_H_ #define CMD_ID_FW_OFFLOAD_H2C 0XFF diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_nic.h index 83f5740a3958..f0d7382c7ad0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_fw_offload_h2c_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_FWOFFLOADH2CFORMAT_H2C_C2H_NIC_H_ #define _HAL_FWOFFLOADH2CFORMAT_H2C_C2H_NIC_H_ #define CMD_ID_FW_OFFLOAD_H2C 0XFF diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_ap.h index f19324ad9fe4..46ffe6340880 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_H2CEXTRAINFO_H2C_C2H_AP_H_ #define _HAL_H2CEXTRAINFO_H2C_C2H_AP_H_ #define PHY_PARAMETER_INFO_GET_LENGTH(__pExtraInfo) GET_C2H_FIELD(__pExtraInfo + 0X00, 0, 8) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_nic.h index 20bfb5ad2afc..5a0e3ae03d05 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_h2c_extra_info_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_H2CEXTRAINFO_H2C_C2H_NIC_H_ #define _HAL_H2CEXTRAINFO_H2C_C2H_NIC_H_ #define PHY_PARAMETER_INFO_GET_LENGTH(__pExtraInfo) LE_BITS_TO_4BYTE(__pExtraInfo + 0X00, 0, 8) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_hw_cfg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_hw_cfg.h index 60a346af09d6..33f0be58fd4d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_hw_cfg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_hw_cfg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALMAC__HW_CFG_H__ #define __HALMAC__HW_CFG_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_ap.h index 433da106b98e..05f1a115ebf3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_ORIGINALC2HFORMAT_H2C_C2H_AP_H_ #define _HAL_ORIGINALC2HFORMAT_H2C_C2H_AP_H_ #define CMD_ID_C2H 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_nic.h index b72c1ce51d12..11933e4c5299 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_c2h_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_ORIGINALC2HFORMAT_H2C_C2H_NIC_H_ #define _HAL_ORIGINALC2HFORMAT_H2C_C2H_NIC_H_ #define CMD_ID_C2H 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_ap.h index 248ffad72f58..2b0405e17c0a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_ORIGINALH2CFORMAT_H2C_C2H_AP_H_ #define _HAL_ORIGINALH2CFORMAT_H2C_C2H_AP_H_ #define CMD_ID_ORIGINAL_H2C 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_nic.h index a42022d19303..b74184d82357 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_original_h2c_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HAL_ORIGINALH2CFORMAT_H2C_C2H_NIC_H_ #define _HAL_ORIGINALH2CFORMAT_H2C_C2H_NIC_H_ #define CMD_ID_ORIGINAL_H2C 0X00 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pcie_reg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pcie_reg.h index 8808e7b44ffe..e8e5dcdce887 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pcie_reg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pcie_reg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALMAC_PCIE_REG_H__ #define __HALMAC_PCIE_REG_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pwr_seq_cmd.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pwr_seq_cmd.h index 0367fe3acd15..0c845d6ab255 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pwr_seq_cmd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_pwr_seq_cmd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef HALMAC_POWER_SEQUENCE_CMD #define HALMAC_POWER_SEQUENCE_CMD diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg2.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg2.h index 9f0c31c1f314..3da8115dcadc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg2.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg2.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALMAC_COM_REG_H__ #define __HALMAC_COM_REG_H__ /*-------------------------Modification Log----------------------------------- diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8821c.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8821c.h index e49ef5649b88..d0826dbf2fa0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8821c.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8821c.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HALMAC_REG_8821C_H #define __INC_HALMAC_REG_8821C_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8822b.h index 0f9f929b0bd1..597fce3213d5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_reg_8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_HALMAC_REG_8822B_H #define __INC_HALMAC_REG_8822B_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_ap.h index 5bb01c029fde..828e5908225e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_BD_AP_H_ #define _HALMAC_RX_BD_AP_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_chip.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_chip.h index 601f11c5f6f0..500ceb208ccb 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_chip.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_BD_CHIP_H_ #define _HALMAC_RX_BD_CHIP_H_ #if (HALMAC_8814A_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_nic.h index dc7d5cd6f48d..572507e47c82 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_bd_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_BD_NIC_H_ #define _HALMAC_RX_BD_NIC_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_ap.h index 386e41840ad3..6d2d79f78590 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_DESC_AP_H_ #define _HALMAC_RX_DESC_AP_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_chip.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_chip.h index 43d80572c805..6987150acd8f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_chip.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_DESC_CHIP_H_ #define _HALMAC_RX_DESC_CHIP_H_ #if (HALMAC_8814A_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_nic.h index 7722df1ce107..b6f446db1451 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_rx_desc_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_RX_DESC_NIC_H_ #define _HALMAC_RX_DESC_NIC_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_sdio_reg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_sdio_reg.h index 18dfbe5d6619..b7e27472c07a 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_sdio_reg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_sdio_reg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALMAC_SDIO_REG_H__ #define __HALMAC_SDIO_REG_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_ap.h index 1cff6b19b939..a5313cbc31dc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_BD_AP_H_ #define _HALMAC_TX_BD_AP_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_chip.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_chip.h index 17004bc511c6..c30b1de37a42 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_chip.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_BD_CHIP_H_ #define _HALMAC_TX_BD_CHIP_H_ #if (HALMAC_8814A_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_nic.h index 1d53accdc53f..897aa81568ba 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_bd_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_BD_NIC_H_ #define _HALMAC_TX_BD_NIC_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT || HALMAC_8188F_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_ap.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_ap.h index e9c1e59e9ee5..e33d669d532c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_ap.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_ap.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_DESC_AP_H_ #define _HALMAC_TX_DESC_AP_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_chip.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_chip.h index d15b6cf8077e..d14623f6d4c7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_chip.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_chip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_DESC_CHIP_H_ #define _HALMAC_TX_DESC_CHIP_H_ #if (HALMAC_8814A_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_nic.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_nic.h index 94eefbe6e92a..f2abbaeac33f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_nic.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_tx_desc_nic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TX_DESC_NIC_H_ #define _HALMAC_TX_DESC_NIC_H_ #if (HALMAC_8814A_SUPPORT || HALMAC_8822B_SUPPORT || HALMAC_8197F_SUPPORT || HALMAC_8821C_SUPPORT) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_type.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_type.h index e4f31efbca35..b1fc7bd7bcbe 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_type.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_type.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _HALMAC_TYPE_H_ #define _HALMAC_TYPE_H_ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_usb_reg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_usb_reg.h index 1ff9bde668fd..9b20b2b367ba 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_usb_reg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/halmac/halmac_usb_reg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HALMAC_USB_REG_H__ #define __HALMAC_USB_REG_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/halhwimg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/halhwimg.h index 108f71509129..a7155cbb85cc 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/halhwimg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/halhwimg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #pragma once #ifndef __INC_HW_IMG_H #define __INC_HW_IMG_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.c index 21f6b188e4d6..7839de693887 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.h index 2cbcd64c84da..578c4b7d3d18 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_adc_sampling.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_ADCSMP_H #define __INC_ADCSMP_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c index 790f150cf377..d75415f8b353 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.h index 079fced69f11..dd0f7a2141be 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_PHYDM_BEAMFORMING_H #define __INC_PHYDM_BEAMFORMING_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.c index 7d81f229e99c..a65197b942c7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.h index 18b0dd2e892c..d39c35f05027 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_ccx.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __PHYDMCCX_H__ #define __PHYDMCCX_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/rtl8822b/version_rtl8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/rtl8822b/version_rtl8822b.h index 4424a3bd33e5..c28ae9665bcf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/rtl8822b/version_rtl8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/rtl8822b/version_rtl8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*RTL8822B PHY Parameters*/ /* [Caution] diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.c index dd8e5c4be06e..67c1280b58a9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.h index 4d87082ab83e..1b593c4254f6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/halcomtxbf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_COM_TXBF_H__ #define __HAL_COM_TXBF_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.c index 778eb919d597..00b5755c156b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.h index 6092438490df..4a019812d035 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8192e.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8192E_H__ #define __HAL_TXBF_8192E_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.c index 7012dbe09faf..a6968628c2cf 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.h index 904078fe26f9..2593021a8e72 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8814a.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8814A_H__ #define __HAL_TXBF_8814A_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.c index 582ffadf0a10..c4d3f1e14cc4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*============================================================*/ /* Description: */ /* */ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.h index abf92967b2d2..310e09a1190d 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbf8822b.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_8822B_H__ #define __HAL_TXBF_8822B_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c index 4fbad2db84f4..9c24888a910b 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.h index 0e5134707ebc..bca4121c8136 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_INTERFACE_H__ #define __HAL_TXBF_INTERFACE_H__ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.c index e1253710f697..1b91329abcad 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //============================================================ // Description: // diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.h index 8260d9b2f9ca..80961a243ba9 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfjaguar.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL_TXBF_JAGUAR_H__ #define __HAL_TXBF_JAGUAR_H__ #if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/phydm_hal_txbf_api.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/phydm_hal_txbf_api.c index fd3417bf8ce7..0e1828a4e9fa 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/phydm_hal_txbf_api.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/phydm_hal_txbf_api.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "mp_precomp.h" #include "phydm_precomp.h" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8188FPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8188FPwrSeq.h index 81e613227bdb..59aba21de9a5 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8188FPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8188FPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8188F #define REALTEK_POWER_SEQUENCE_8188F diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPhyReg.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPhyReg.h index cd13c22bc398..b69ccd01c901 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPhyReg.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPhyReg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /***************************************************************************** * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. * diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPwrSeq.h index 12bb2fb6be05..9332505c84c0 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8192EPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8192E #define REALTEK_POWER_SEQUENCE_8192E diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8703BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8703BPwrSeq.h index a53ca9a0767a..fb36455f3279 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8703BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8703BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8703B #define REALTEK_POWER_SEQUENCE_8703B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723BPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723BPwrSeq.h index 6b895621e1c5..d18d064dae0e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723BPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723BPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723B #define REALTEK_POWER_SEQUENCE_8723B diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723DPwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723DPwrSeq.h index e7a6013d1025..5d3585f3c465 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723DPwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723DPwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8723D #define REALTEK_POWER_SEQUENCE_8723D diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723PwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723PwrSeq.h index 6669641e8767..e463f74b7ae3 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723PwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8723PwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HAL8723PWRSEQ_H__ #define __HAL8723PWRSEQ_H__ /* diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8821APwrSeq.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8821APwrSeq.h index 393068b3f3cf..091c2e56d967 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8821APwrSeq.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/Hal8821APwrSeq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef REALTEK_POWER_SEQUENCE_8821 #define REALTEK_POWER_SEQUENCE_8821 diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/custom_gpio.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/custom_gpio.h index 5691d9a1c6cc..54e491872992 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/custom_gpio.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/custom_gpio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __CUSTOM_GPIO_H__ #define __CUSTOM_GPIO_H___ diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_version.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_version.h index c90d9c7ffd41..10d112741f4f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_version.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_version.h @@ -1,2 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define DRIVERVERSION "v5.1.7a.Foxconn_21299.20170224" #define BTCOEXVERSION "BTCOEX20161116-413c" diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wapi.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wapi.h index 635aec0db4ee..216ab6997c04 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wapi.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wapi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __INC_WAPI_H #define __INC_WAPI_H diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wifi_regd.h b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wifi_regd.h index 2182712648bd..541a211f9511 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wifi_regd.h +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/include/rtw_wifi_regd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/os_dep/linux/wifi_regd.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/os_dep/linux/wifi_regd.c index 7efa85b8c242..0c7000b4e7f2 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/os_dep/linux/wifi_regd.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/os_dep/linux/wifi_regd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /****************************************************************************** * * Copyright(c) 2009-2010 Realtek Corporation. diff --git a/drivers/net/wireless/rockchip_wlan/wifi_launcher/Makefile b/drivers/net/wireless/rockchip_wlan/wifi_launcher/Makefile index 6d8d07677647..c63456766cdb 100644 --- a/drivers/net/wireless/rockchip_wlan/wifi_launcher/Makefile +++ b/drivers/net/wireless/rockchip_wlan/wifi_launcher/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-m := wlan.o diff --git a/drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h b/drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h old mode 100755 new mode 100644 index 136da06c5639..bd7adac40237 --- a/drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h +++ b/drivers/net/wireless/rockchip_wlan/wifi_launcher/wlan_param.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _WLAN_PARAM_H_ #define _WLAN_PARAM_H_ diff --git a/drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c b/drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c index 4b9de11788dd..f79fe447ce1f 100644 --- a/drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c +++ b/drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/net/wireless/rtl8723as/Kconfig b/drivers/net/wireless/rtl8723as/Kconfig old mode 100755 new mode 100644 index 43f9697fa814..91d27185bcae --- a/drivers/net/wireless/rtl8723as/Kconfig +++ b/drivers/net/wireless/rtl8723as/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RTL8723AS tristate "Realtek 8723AS SDIO WiFi Support" depends on WLAN_80211 && MMC diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig index 5a68069db897..165d8dd0ca2c 100644 --- a/drivers/phy/rockchip/Kconfig +++ b/drivers/phy/rockchip/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Phy drivers for Rockchip platforms # diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile index 751dc955b2b3..181abeb0083d 100644 --- a/drivers/phy/rockchip/Makefile +++ b/drivers/phy/rockchip/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB3) += phy-rockchip-inno-usb3.o diff --git a/drivers/power/reset/reboot-mode.h b/drivers/power/reset/reboot-mode.h index 44ed34fc56a0..342df786d043 100644 --- a/drivers/power/reset/reboot-mode.h +++ b/drivers/power/reset/reboot-mode.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ diff --git a/drivers/power/rk29_charger_display.c b/drivers/power/rk29_charger_display.c old mode 100755 new mode 100644 index 407486f68bf0..0e8cb9f440c1 --- a/drivers/power/rk29_charger_display.c +++ b/drivers/power/rk29_charger_display.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/drivers/regulator/rockchip_io_vol_domain.c b/drivers/regulator/rockchip_io_vol_domain.c old mode 100755 new mode 100644 index 262d151f12ce..5a5b70bcd9e5 --- a/drivers/regulator/rockchip_io_vol_domain.c +++ b/drivers/regulator/rockchip_io_vol_domain.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/rk_nand/Kconfig b/drivers/rk_nand/Kconfig index 49fc9d62174e..c49a1c28b702 100644 --- a/drivers/rk_nand/Kconfig +++ b/drivers/rk_nand/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 if ARCH_ROCKCHIP config RK_NAND tristate "RK NAND Device Support" diff --git a/drivers/rk_nand/Makefile b/drivers/rk_nand/Makefile index 93e4aa343a61..f8f93992636a 100644 --- a/drivers/rk_nand/Makefile +++ b/drivers/rk_nand/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RK_NAND) += rk_ftl.o rk_nand_base.o rk_nand_blk.o ifdef CONFIG_THUMB2_KERNEL rk_ftl-$(CONFIG_THUMB2_KERNEL) += rk_ftl_arm_v7_thumb.o diff --git a/drivers/rtc/auto-wake.c b/drivers/rtc/auto-wake.c old mode 100755 new mode 100644 index 4642867c6ea0..abdd73fd4797 --- a/drivers/rtc/auto-wake.c +++ b/drivers/rtc/auto-wake.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/smc/Kconfig b/drivers/smc/Kconfig old mode 100755 new mode 100644 index 28f75170f4d7..49beb68e9146 --- a/drivers/smc/Kconfig +++ b/drivers/smc/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK29_SMC bool "rk29 smc interface" diff --git a/drivers/smc/Makefile b/drivers/smc/Makefile old mode 100755 new mode 100644 index 5e5258e921c4..cf1c720d010b --- a/drivers/smc/Makefile +++ b/drivers/smc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the Linux IrDA infrared port device drivers. # diff --git a/drivers/smc/rk29_smc.c b/drivers/smc/rk29_smc.c old mode 100755 new mode 100644 index 36d99d9fbfbb..86f7437b88e1 --- a/drivers/smc/rk29_smc.c +++ b/drivers/smc/rk29_smc.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/staging/android/ion/rockchip/Makefile b/drivers/staging/android/ion/rockchip/Makefile index 1871de8ce23a..89265fcbbe6f 100644 --- a/drivers/staging/android/ion/rockchip/Makefile +++ b/drivers/staging/android/ion/rockchip/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-y += rockchip_ion.o obj-$(CONFIG_ION_ROCKCHIP_SNAPSHOT) += rockchip_ion_snapshot.o diff --git a/drivers/staging/android/trace/ion.h b/drivers/staging/android/trace/ion.h index 9eb14453de3b..45347d9c09b3 100644 --- a/drivers/staging/android/trace/ion.h +++ b/drivers/staging/android/trace/ion.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define ION_TRACE_EMIT #ifdef ION_TRACE_EMIT diff --git a/drivers/staging/iio/imu/inv_mpu/Kconfig b/drivers/staging/iio/imu/inv_mpu/Kconfig index c84db8190cb5..4b548a8cf748 100644 --- a/drivers/staging/iio/imu/inv_mpu/Kconfig +++ b/drivers/staging/iio/imu/inv_mpu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # inv-mpu-iio driver for Invensense MPU devices and combos # diff --git a/drivers/staging/iio/imu/inv_mpu/Makefile b/drivers/staging/iio/imu/inv_mpu/Makefile index c11ad51899d7..6bf1d0369e46 100644 --- a/drivers/staging/iio/imu/inv_mpu/Makefile +++ b/drivers/staging/iio/imu/inv_mpu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for Invensense inv-mpu-iio device. # diff --git a/drivers/staging/iio/imu/inv_mpu/inv_counters.c b/drivers/staging/iio/imu/inv_mpu/inv_counters.c index 3b26ca97284f..3ba495fab8ae 100644 --- a/drivers/staging/iio/imu/inv_mpu/inv_counters.c +++ b/drivers/staging/iio/imu/inv_mpu/inv_counters.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * @file inv_counters.c * @brief Exports i2c read write counts through sysfs diff --git a/drivers/staging/iio/imu/inv_mpu/inv_counters.h b/drivers/staging/iio/imu/inv_mpu/inv_counters.h index d60dac9d97bd..c3221718a55f 100644 --- a/drivers/staging/iio/imu/inv_mpu/inv_counters.h +++ b/drivers/staging/iio/imu/inv_mpu/inv_counters.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * @file inv_counters.h * @brief Debug file to keep track of various counters for the InvenSense diff --git a/drivers/staging/imgtec/Kconfig b/drivers/staging/imgtec/Kconfig index f1295a6edfeb..f4f343270cb6 100644 --- a/drivers/staging/imgtec/Kconfig +++ b/drivers/staging/imgtec/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config POWERVR_ADF_FBDEV tristate "ADF driver for fbdev-only systems" depends on ADF diff --git a/drivers/staging/imgtec/Makefile b/drivers/staging/imgtec/Makefile index 5c44ffb15617..d7ad8f0cb8cb 100644 --- a/drivers/staging/imgtec/Makefile +++ b/drivers/staging/imgtec/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_POWERVR_ADF_FBDEV) += powervr_adf_fbdev.o powervr_adf_fbdev-y += adf_common.o adf_fbdev.o ccflags-y += \ diff --git a/drivers/staging/imgtec/apollo/Kconfig b/drivers/staging/imgtec/apollo/Kconfig index 23f94a530816..10449f198a4f 100644 --- a/drivers/staging/imgtec/apollo/Kconfig +++ b/drivers/staging/imgtec/apollo/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config POWERVR_APOLLO tristate "PowerVR Apollo test chip support" depends on X86 diff --git a/drivers/staging/imgtec/apollo/Makefile b/drivers/staging/imgtec/apollo/Makefile index 9be68f69c2b0..72791b52834c 100644 --- a/drivers/staging/imgtec/apollo/Makefile +++ b/drivers/staging/imgtec/apollo/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_POWERVR_APOLLO) += apollo.o apollo-y += apollo_drv.o ion_lma_heap.o pci_support.o ccflags-y += -include drivers/staging/imgtec/config_kernel.h \ diff --git a/drivers/staging/imgtec/config_kernel.h b/drivers/staging/imgtec/config_kernel.h index 0d91bf597bee..0bb0350e6d8c 100644 --- a/drivers/staging/imgtec/config_kernel.h +++ b/drivers/staging/imgtec/config_kernel.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define RGX_FW_HEAP_SHIFT 25 #define RGX_FW_FILENAME "rgx.fw.signed" #define LINUX diff --git a/drivers/staging/imgtec/rogue/Kconfig b/drivers/staging/imgtec/rogue/Kconfig index c699aa1952c5..7e5c3ac1b26f 100644 --- a/drivers/staging/imgtec/rogue/Kconfig +++ b/drivers/staging/imgtec/rogue/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config POWERVR_ROGUE_N tristate "PowerVR Rogue" default n diff --git a/drivers/staging/imgtec/rogue/Makefile b/drivers/staging/imgtec/rogue/Makefile index b2ee456547f6..644308007e2a 100644 --- a/drivers/staging/imgtec/rogue/Makefile +++ b/drivers/staging/imgtec/rogue/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 ccflags-y += -include $(srctree)/drivers/staging/imgtec/config_kernel.h \ -I$(srctree)/drivers/staging/imgtec \ -I$(srctree)/$(src) \ diff --git a/drivers/staging/rk29/ipp/Kconfig b/drivers/staging/rk29/ipp/Kconfig old mode 100755 new mode 100644 index 13acbc79fecd..aaa6de0ec4a9 --- a/drivers/staging/rk29/ipp/Kconfig +++ b/drivers/staging/rk29/ipp/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "IPP" config RK29_IPP tristate "ROCKCHIP RK29 IPP" diff --git a/drivers/staging/rk29/ipp/Makefile b/drivers/staging/rk29/ipp/Makefile index 79bbd9a33a40..40583099a6ad 100644 --- a/drivers/staging/rk29/ipp/Makefile +++ b/drivers/staging/rk29/ipp/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the ipp. # diff --git a/drivers/switch/Kconfig b/drivers/switch/Kconfig index 19404b6f7778..e997504baf89 100644 --- a/drivers/switch/Kconfig +++ b/drivers/switch/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig SWITCH tristate "Switch class support" help diff --git a/drivers/switch/Makefile b/drivers/switch/Makefile index f7606ed4a719..c2118f87bb3c 100644 --- a/drivers/switch/Makefile +++ b/drivers/switch/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # Switch Class Driver obj-$(CONFIG_SWITCH) += switch_class.o obj-$(CONFIG_SWITCH_GPIO) += switch_gpio.o diff --git a/drivers/testcode/Kconfig b/drivers/testcode/Kconfig old mode 100755 new mode 100644 index e3a89d7c734c..c5aa4c1a0674 --- a/drivers/testcode/Kconfig +++ b/drivers/testcode/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Input misc drivers configuration # diff --git a/drivers/testcode/Makefile b/drivers/testcode/Makefile old mode 100755 new mode 100644 index fa7569c07fe5..deda19e16fab --- a/drivers/testcode/Makefile +++ b/drivers/testcode/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the test code drivers. # diff --git a/drivers/testcode/gpio_wave.c b/drivers/testcode/gpio_wave.c old mode 100755 new mode 100644 index 9e3bae87fd7b..3b958ddf53ce --- a/drivers/testcode/gpio_wave.c +++ b/drivers/testcode/gpio_wave.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/testcode/gpio_wave.h b/drivers/testcode/gpio_wave.h old mode 100755 new mode 100644 index 592cfba8a641..6ef181b383f9 --- a/drivers/testcode/gpio_wave.h +++ b/drivers/testcode/gpio_wave.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __GPIO_PWM_H__ #define __GPIO_PWM_H__ diff --git a/drivers/usb/dwc_otg_310/Kconfig b/drivers/usb/dwc_otg_310/Kconfig index 1ad735ef666c..f2720a3b4ec5 100644 --- a/drivers/usb/dwc_otg_310/Kconfig +++ b/drivers/usb/dwc_otg_310/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "ROCKCHIP USB Support" depends on ARCH_ROCKCHIP diff --git a/drivers/usb/dwc_otg_310/Makefile b/drivers/usb/dwc_otg_310/Makefile index a7fd8784976b..a7c85ec1a9b2 100644 --- a/drivers/usb/dwc_otg_310/Makefile +++ b/drivers/usb/dwc_otg_310/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for DWC_otg Highspeed USB controller driver # diff --git a/drivers/usb/dwc_otg_310/Makefile-original b/drivers/usb/dwc_otg_310/Makefile-original index d53ffb19a8ad..b1b4bb781f29 100644 --- a/drivers/usb/dwc_otg_310/Makefile-original +++ b/drivers/usb/dwc_otg_310/Makefile-original @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for DWC_otg Highspeed USB controller driver # diff --git a/drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c b/drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c old mode 100755 new mode 100644 index 794b1dc45b5c..43c3543e2e9e --- a/drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c +++ b/drivers/usb/dwc_otg_310/common_port/dwc_common_linux.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/usb/dwc_otg_310/common_port/dwc_mem.c b/drivers/usb/dwc_otg_310/common_port/dwc_mem.c old mode 100755 new mode 100644 index 6d6c6c52d0e3..adb3d2575c3d --- a/drivers/usb/dwc_otg_310/common_port/dwc_mem.c +++ b/drivers/usb/dwc_otg_310/common_port/dwc_mem.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* Memory Debugging */ #ifdef DWC_DEBUG_MEMORY diff --git a/drivers/usb/dwc_otg_310/common_port/dwc_notifier.c b/drivers/usb/dwc_otg_310/common_port/dwc_notifier.c old mode 100755 new mode 100644 index bbe769201a87..5cdbcd100ae4 --- a/drivers/usb/dwc_otg_310/common_port/dwc_notifier.c +++ b/drivers/usb/dwc_otg_310/common_port/dwc_notifier.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef DWC_NOTIFYLIB #include "dwc_notifier.h" diff --git a/drivers/usb/dwc_otg_310/common_port/dwc_notifier.h b/drivers/usb/dwc_otg_310/common_port/dwc_notifier.h old mode 100755 new mode 100644 index 4a8cdfe565b1..7daba3817ff8 --- a/drivers/usb/dwc_otg_310/common_port/dwc_notifier.h +++ b/drivers/usb/dwc_otg_310/common_port/dwc_notifier.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DWC_NOTIFIER_H__ #define __DWC_NOTIFIER_H__ diff --git a/drivers/usb/dwc_otg_310/dwc_otg_os_dep.h b/drivers/usb/dwc_otg_310/dwc_otg_os_dep.h index e890bfbd81e5..d8e511577ec9 100644 --- a/drivers/usb/dwc_otg_310/dwc_otg_os_dep.h +++ b/drivers/usb/dwc_otg_310/dwc_otg_os_dep.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DWC_OS_DEP_H_ #define _DWC_OS_DEP_H_ diff --git a/drivers/usb/dwc_otg_310/dwc_otg_rk_common_if.h b/drivers/usb/dwc_otg_310/dwc_otg_rk_common_if.h index 8b137891791f..85c5b5ec218d 100644 --- a/drivers/usb/dwc_otg_310/dwc_otg_rk_common_if.h +++ b/drivers/usb/dwc_otg_310/dwc_otg_rk_common_if.h @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ diff --git a/drivers/usb/dwc_otg_310/gadget_supplement.c b/drivers/usb/dwc_otg_310/gadget_supplement.c index 7a9bd7a0d6e4..314a5b3529fd 100644 --- a/drivers/usb/dwc_otg_310/gadget_supplement.c +++ b/drivers/usb/dwc_otg_310/gadget_supplement.c @@ -1 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "linux/dwc_otg_plat.h" \ No newline at end of file diff --git a/drivers/usb/dwc_otg_310/usbdev_bc.h b/drivers/usb/dwc_otg_310/usbdev_bc.h index 58529f78efc7..fd6847848321 100644 --- a/drivers/usb/dwc_otg_310/usbdev_bc.h +++ b/drivers/usb/dwc_otg_310/usbdev_bc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _USBDEV_BC_H #define _USBDEV_BC_H diff --git a/drivers/usb/dwc_otg_310/usbdev_grf_regs.h b/drivers/usb/dwc_otg_310/usbdev_grf_regs.h index 275820311f35..3a0f3328b807 100644 --- a/drivers/usb/dwc_otg_310/usbdev_grf_regs.h +++ b/drivers/usb/dwc_otg_310/usbdev_grf_regs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __USBDEV_GRF_REGS_H__ #define __USBDEV_GRF_REGS_H__ diff --git a/drivers/usb/dwc_otg_310/usbdev_rk.h b/drivers/usb/dwc_otg_310/usbdev_rk.h index 8bb78179c626..7fb62c23e16c 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk.h +++ b/drivers/usb/dwc_otg_310/usbdev_rk.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __USBDEV_RK_H #define __USBDEV_RK_H diff --git a/drivers/usb/dwc_otg_310/usbdev_rk30.c b/drivers/usb/dwc_otg_310/usbdev_rk30.c index 92c1d016bd0e..9bc7ff7a013b 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk30.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk30.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM #include "usbdev_rk.h" #include "usbdev_grf_regs.h" diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3036.c b/drivers/usb/dwc_otg_310/usbdev_rk3036.c index 4de1212903b0..5f56fdbddbc3 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk3036.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk3036.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM #include "usbdev_rk.h" #include "usbdev_grf_regs.h" diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3126.c b/drivers/usb/dwc_otg_310/usbdev_rk3126.c index 434e98f620b1..1c1903b9791d 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk3126.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk3126.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM #include "usbdev_rk.h" #include "usbdev_grf_regs.h" diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3190_grf_regs.h b/drivers/usb/dwc_otg_310/usbdev_rk3190_grf_regs.h index 5100dbc2e66b..850153ea9d16 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk3190_grf_regs.h +++ b/drivers/usb/dwc_otg_310/usbdev_rk3190_grf_regs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __USBDEV_RK3190_GRF_REGS_H__ #define __USBDEV_RK3190_GRF_REGS_H__ #include diff --git a/drivers/usb/dwc_otg_310/usbdev_rk32.c b/drivers/usb/dwc_otg_310/usbdev_rk32.c index 5f3839072615..0983033e6ff3 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk32.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk32.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM #include "usbdev_rk.h" #include "usbdev_grf_regs.h" diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3368.c b/drivers/usb/dwc_otg_310/usbdev_rk3368.c index 1507bd37f020..65739aa3b7e3 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rk3368.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk3368.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifdef CONFIG_ARM64 #include "usbdev_rk.h" #include "dwc_otg_regs.h" diff --git a/drivers/usb/dwc_otg_310/usbdev_rkuoc.h b/drivers/usb/dwc_otg_310/usbdev_rkuoc.h index 6ff88f80e306..972e760b260b 100644 --- a/drivers/usb/dwc_otg_310/usbdev_rkuoc.h +++ b/drivers/usb/dwc_otg_310/usbdev_rkuoc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __USBDEV_RKUOC_H #define _USBDEV_RKUOC_H diff --git a/drivers/video/backlight/aw9364_bl.h b/drivers/video/backlight/aw9364_bl.h index bac874d6dd53..a802d096038b 100644 --- a/drivers/video/backlight/aw9364_bl.h +++ b/drivers/video/backlight/aw9364_bl.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DRIVERS_TOUCHSCREEN_AW9364_TS_H #define __DRIVERS_TOUCHSCREEN_AW9364_TS_H diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig old mode 100755 new mode 100644 index b050f8a46fff..5808d0a4dbdd --- a/drivers/video/rockchip/Kconfig +++ b/drivers/video/rockchip/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig FB_ROCKCHIP tristate "Frame buffer support for Rockchip " depends on FB diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile old mode 100755 new mode 100644 index 14a2e5faefa4..245c2456392d --- a/drivers/video/rockchip/Makefile +++ b/drivers/video/rockchip/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ROCKCHIP_RGA) += rga/ obj-$(CONFIG_ROCKCHIP_RGA2) += rga2/ obj-$(CONFIG_FB_ROCKCHIP) += rk_fb.o rkfb_sysfs.o bmp_helper.o screen/ diff --git a/drivers/video/rockchip/display-sys.c b/drivers/video/rockchip/display-sys.c index 6db202ae63be..6c03b2795840 100644 --- a/drivers/video/rockchip/display-sys.c +++ b/drivers/video/rockchip/display-sys.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/dp/Kconfig b/drivers/video/rockchip/dp/Kconfig index bcd7cf73d5ed..1dd5cf2ed802 100644 --- a/drivers/video/rockchip/dp/Kconfig +++ b/drivers/video/rockchip/dp/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "DP" config ROCKCHIP_DP diff --git a/drivers/video/rockchip/dp/Makefile b/drivers/video/rockchip/dp/Makefile index a057b346af61..bb86dd5ec24c 100644 --- a/drivers/video/rockchip/dp/Makefile +++ b/drivers/video/rockchip/dp/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ROCKCHIP_DP) += rockchip_dp_core.o rockchip_dp.o cdn-dp-fb-reg.o diff --git a/drivers/video/rockchip/dp/rockchip_dp.c b/drivers/video/rockchip/dp/rockchip_dp.c index 74f20fcdf2a3..4dc803d7988c 100644 --- a/drivers/video/rockchip/dp/rockchip_dp.c +++ b/drivers/video/rockchip/dp/rockchip_dp.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "rockchip_dp.h" #include #include diff --git a/drivers/video/rockchip/dp/rockchip_dp.h b/drivers/video/rockchip/dp/rockchip_dp.h index f549e4e08410..d098e7a1a072 100644 --- a/drivers/video/rockchip/dp/rockchip_dp.h +++ b/drivers/video/rockchip/dp/rockchip_dp.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_DP_H__ #define __ROCKCHIP_DP_H__ diff --git a/drivers/video/rockchip/dp/rockchip_dp_core.h b/drivers/video/rockchip/dp/rockchip_dp_core.h index 7f7beb538d5a..05dd66541851 100644 --- a/drivers/video/rockchip/dp/rockchip_dp_core.h +++ b/drivers/video/rockchip/dp/rockchip_dp_core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_DP_CORE_H__ #define __ROCKCHIP_DP_CORE_H__ diff --git a/drivers/video/rockchip/hdmi/Kconfig b/drivers/video/rockchip/hdmi/Kconfig index aead78ade0b9..941f9f742bd6 100644 --- a/drivers/video/rockchip/hdmi/Kconfig +++ b/drivers/video/rockchip/hdmi/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig RK_HDMI bool "Rockchip HDMI support" depends on FB_ROCKCHIP || DRM_ROCKCHIP diff --git a/drivers/video/rockchip/hdmi/Makefile b/drivers/video/rockchip/hdmi/Makefile index cabca13757bb..98bf7edb35c6 100644 --- a/drivers/video/rockchip/hdmi/Makefile +++ b/drivers/video/rockchip/hdmi/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for HDMI linux kernel module. # diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c index 78bba0431ba0..ba0938e5d0cb 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.h b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.h index 97130cda1618..74e2b9918720 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_HDMI_CEC_H__ #define __ROCKCHIP_HDMI_CEC_H__ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c index 91cbd9ac5946..d940a53914a7 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include "rockchip-hdmi.h" diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c index 1a9ee37c1166..d99be01bb8bd 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "rockchip-hdmi.h" #include "../../fbdev/edid.h" diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c index 45727290b800..49b6d3547583 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "rockchip-hdmi.h" static const struct hdmi_video_timing hdmi_mode[] = { diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c index b27f0712f486..af43598ab76e 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi.h b/drivers/video/rockchip/hdmi/rockchip-hdmi.h index 08e1f9b47ee9..6bd2d2020b05 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_HDMI_H__ #define __ROCKCHIP_HDMI_H__ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig index f8fa433de3d8..bd92ea912860 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK_HDMI_V1 bool "RockChip HDMI V1 support" depends on RK_HDMI diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Makefile b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Makefile index 9a67d1dcd6ca..c1a66540f661 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Makefile +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for HDMI linux kernel module. # diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.c index e7cda3e67fb0..eaa3834bc199 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.h b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.h index 488f80980595..ba9a4720f139 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_HDMI_V1_H__ #define __ROCKCHIP_HDMI_V1_H__ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_cec.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_cec.c index fdd3cea62729..6d0f61cf45c0 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_cec.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_cec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "rockchip_hdmiv1.h" #include "rockchip_hdmiv1_hw.h" #include "../rockchip-hdmi-cec.h" diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.c index bcc368c0e9fa..e104010444f0 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.h b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.h index 49d1737d06c1..0ac4f6ee4a2b 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hdcp.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_HDMIV1_HDCP_H__ #define __ROCKCHIP_HDMIV1_HDCP_H__ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.c index a4501f23fb79..3878b79f2b7c 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.h b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.h index aca4958cc261..d3be29dbfb3f 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv1/rockchip_hdmiv1_hw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_HDMI_V1_HW_H__ #define __ROCKCHIP_HDMI_V1_HW_H__ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig index 5d62e73ceac8..c45593abbf58 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK_HDMI_V2 bool "RockChip HDMI V2 support" depends on RK_HDMI diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Makefile b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Makefile index ddff17707dac..f853c433cb9f 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Makefile +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for HDMI linux kernel module. # diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c index 87842211c3c9..0b0ff31ddd81 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h index 1eae751e2f15..a8d4257c788f 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK32_HDMI_H__ #define __RK32_HDMI_H__ #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c index 3c7279400c69..d50f7c2cd314 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include "../rockchip-hdmi-cec.h" #include "rockchip_hdmiv2.h" diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hdcp.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hdcp.c index d47b8e21c257..fb02ec9a8fed 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hdcp.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hdcp.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c index 024ae92091e1..62b475686a6a 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.h b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.h index 7aa1ce46a047..368322b7ebde 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK3288_HDMI_HW_H #define _RK3288_HDMI_HW_H #include diff --git a/drivers/video/rockchip/iep/Kconfig b/drivers/video/rockchip/iep/Kconfig old mode 100755 new mode 100644 index 9fd3d2728d3d..e4f8bbb31fc1 --- a/drivers/video/rockchip/iep/Kconfig +++ b/drivers/video/rockchip/iep/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "IEP" depends on ARCH_ROCKCHIP diff --git a/drivers/video/rockchip/iep/Makefile b/drivers/video/rockchip/iep/Makefile old mode 100755 new mode 100644 index 781907395012..37760fbf42b7 --- a/drivers/video/rockchip/iep/Makefile +++ b/drivers/video/rockchip/iep/Makefile @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_IEP) += hw_iep_reg.o iep_drv.o iep_iommu_drm.o iep_iommu_ion.o iep_iommu_ops.o diff --git a/drivers/video/rockchip/iep/hw_iep_config_addr.h b/drivers/video/rockchip/iep/hw_iep_config_addr.h index 41b2eaea8ce9..1f4a0706233f 100644 --- a/drivers/video/rockchip/iep/hw_iep_config_addr.h +++ b/drivers/video/rockchip/iep/hw_iep_config_addr.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef HW_IEP_CONFIG_ADDR_H_ #define HW_IEP_CONFIG_ADDR_H_ diff --git a/drivers/video/rockchip/iep/hw_iep_reg.h b/drivers/video/rockchip/iep/hw_iep_reg.h index 9c8706434731..03d9fe92ca23 100644 --- a/drivers/video/rockchip/iep/hw_iep_reg.h +++ b/drivers/video/rockchip/iep/hw_iep_reg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef IEP_REGS_H #define IEP_REGS_H #include "hw_iep_config_addr.h" diff --git a/drivers/video/rockchip/iep/iep.h b/drivers/video/rockchip/iep/iep.h index cf3753f7d555..784b77c8bed8 100644 --- a/drivers/video/rockchip/iep/iep.h +++ b/drivers/video/rockchip/iep/iep.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IEP_H_ #define _IEP_H_ diff --git a/drivers/video/rockchip/iep/iep_drv.h b/drivers/video/rockchip/iep/iep_drv.h index a2feb9791238..43d1e8167a8a 100644 --- a/drivers/video/rockchip/iep/iep_drv.h +++ b/drivers/video/rockchip/iep/iep_drv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef IEP_DRV_H_ #define IEP_DRV_H_ diff --git a/drivers/video/rockchip/iep/iep_mmu.h b/drivers/video/rockchip/iep/iep_mmu.h old mode 100755 new mode 100644 index 0f9591e926fe..027754640cc9 --- a/drivers/video/rockchip/iep/iep_mmu.h +++ b/drivers/video/rockchip/iep/iep_mmu.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IEP_MMU_H_ #define _IEP_MMU_H_ diff --git a/drivers/video/rockchip/lcdc/Kconfig b/drivers/video/rockchip/lcdc/Kconfig index 9a9ebf490fb7..f57a508bcba5 100644 --- a/drivers/video/rockchip/lcdc/Kconfig +++ b/drivers/video/rockchip/lcdc/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config LCDC_RK2928 tristate "rk2928 lcdc support" depends on (DRM_ROCKCHIP || FB_ROCKCHIP) && ARCH_RK2928 diff --git a/drivers/video/rockchip/lcdc/Makefile b/drivers/video/rockchip/lcdc/Makefile index b751d1c2d1f9..1c2522c949e0 100644 --- a/drivers/video/rockchip/lcdc/Makefile +++ b/drivers/video/rockchip/lcdc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_LCDC_RK30) += rk30_lcdc.o obj-$(CONFIG_LCDC_RK2928) += rk2928_lcdc.o obj-$(CONFIG_LCDC_RK3066B) += rk3066b_lcdc.o diff --git a/drivers/video/rockchip/lcdc/rk2928_lcdc.h b/drivers/video/rockchip/lcdc/rk2928_lcdc.h index c32c64175fbc..2339a71259bc 100644 --- a/drivers/video/rockchip/lcdc/rk2928_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk2928_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK2928_LCDC_H_ #define RK2928_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.h b/drivers/video/rockchip/lcdc/rk3036_lcdc.h old mode 100755 new mode 100644 index 3c988e59d4b8..330cb0824d51 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK3036_LCDC_H_ #define _RK3036_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk30_lcdc.h b/drivers/video/rockchip/lcdc/rk30_lcdc.h index ea87f6002e04..9d754971afa5 100644 --- a/drivers/video/rockchip/lcdc/rk30_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk30_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK30_LCDC_H_ #define RK30_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk312x_lcdc.h b/drivers/video/rockchip/lcdc/rk312x_lcdc.h old mode 100755 new mode 100644 index ec1d3cece51b..431bd0f97747 --- a/drivers/video/rockchip/lcdc/rk312x_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk312x_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK312X_LCDC_H_ #define _RK312X_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk3188_lcdc.h b/drivers/video/rockchip/lcdc/rk3188_lcdc.h old mode 100755 new mode 100644 index 27c8c9289d4b..3e199e5f71ce --- a/drivers/video/rockchip/lcdc/rk3188_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3188_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK3188_LCDC_H_ #define RK3188_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk322x_lcdc.h b/drivers/video/rockchip/lcdc/rk322x_lcdc.h index d7466e904d03..13e573c62ed4 100644 --- a/drivers/video/rockchip/lcdc/rk322x_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk322x_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK322X_LCDC_H_ #define RK322X_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk3288_lcdc.h b/drivers/video/rockchip/lcdc/rk3288_lcdc.h old mode 100755 new mode 100644 index 01af7054984b..77218d2a6610 --- a/drivers/video/rockchip/lcdc/rk3288_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3288_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK3288_LCDC_H_ #define RK3288_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk3368_lcdc.h b/drivers/video/rockchip/lcdc/rk3368_lcdc.h old mode 100755 new mode 100644 index e8d47202565c..bcab60348233 --- a/drivers/video/rockchip/lcdc/rk3368_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3368_lcdc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK3368_LCDC_H_ #define RK3368_LCDC_H_ diff --git a/drivers/video/rockchip/lcdc/rk_vop_lite.h b/drivers/video/rockchip/lcdc/rk_vop_lite.h index 7b2ffe1a4757..4f8c096b2d4e 100644 --- a/drivers/video/rockchip/lcdc/rk_vop_lite.h +++ b/drivers/video/rockchip/lcdc/rk_vop_lite.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK_VOPLITE_H_ #define RK_VOPLITE_H_ diff --git a/drivers/video/rockchip/rga/Kconfig b/drivers/video/rockchip/rga/Kconfig old mode 100755 new mode 100644 index 6eb482848ba2..6023b2eb23a7 --- a/drivers/video/rockchip/rga/Kconfig +++ b/drivers/video/rockchip/rga/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "RGA" depends on ARCH_ROCKCHIP diff --git a/drivers/video/rockchip/rga/Makefile b/drivers/video/rockchip/rga/Makefile old mode 100755 new mode 100644 index 1a476f0c7be9..58dd4c6a3e42 --- a/drivers/video/rockchip/rga/Makefile +++ b/drivers/video/rockchip/rga/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 rga-y := rga_drv.o rga_mmu_info.o rga_reg_info.o RGA_API.o obj-$(CONFIG_ROCKCHIP_RGA) += rga.o diff --git a/drivers/video/rockchip/rga/RGA_API.c b/drivers/video/rockchip/rga/RGA_API.c old mode 100755 new mode 100644 index 453fb4103c5b..947a9b925f60 --- a/drivers/video/rockchip/rga/RGA_API.c +++ b/drivers/video/rockchip/rga/RGA_API.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include "RGA_API.h" diff --git a/drivers/video/rockchip/rga/RGA_API.h b/drivers/video/rockchip/rga/RGA_API.h old mode 100755 new mode 100644 index 60e5d1f0ce60..f13f666d822f --- a/drivers/video/rockchip/rga/RGA_API.h +++ b/drivers/video/rockchip/rga/RGA_API.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_API_H__ #define __RGA_API_H__ diff --git a/drivers/video/rockchip/rga/rga.h b/drivers/video/rockchip/rga/rga.h old mode 100755 new mode 100644 index 78819cb62c79..4f6ccedf803d --- a/drivers/video/rockchip/rga/rga.h +++ b/drivers/video/rockchip/rga/rga.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RGA_DRIVER_H_ #define _RGA_DRIVER_H_ diff --git a/drivers/video/rockchip/rga/rga_mmu_info.c b/drivers/video/rockchip/rga/rga_mmu_info.c old mode 100755 new mode 100644 index ef53838058aa..e6fa838e511c --- a/drivers/video/rockchip/rga/rga_mmu_info.c +++ b/drivers/video/rockchip/rga/rga_mmu_info.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/video/rockchip/rga/rga_mmu_info.h b/drivers/video/rockchip/rga/rga_mmu_info.h old mode 100755 new mode 100644 index d8e18e2fb15e..d828322613c0 --- a/drivers/video/rockchip/rga/rga_mmu_info.h +++ b/drivers/video/rockchip/rga/rga_mmu_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_MMU_INFO_H__ #define __RGA_MMU_INFO_H__ diff --git a/drivers/video/rockchip/rga/rga_reg_info.c b/drivers/video/rockchip/rga/rga_reg_info.c old mode 100755 new mode 100644 index 607b1b9f1a48..91be208ab49b --- a/drivers/video/rockchip/rga/rga_reg_info.c +++ b/drivers/video/rockchip/rga/rga_reg_info.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //#include #include diff --git a/drivers/video/rockchip/rga/rga_reg_info.h b/drivers/video/rockchip/rga/rga_reg_info.h old mode 100755 new mode 100644 index e3d7dc0ba016..565e8f72d7f0 --- a/drivers/video/rockchip/rga/rga_reg_info.h +++ b/drivers/video/rockchip/rga/rga_reg_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __REG_INFO_H__ #define __REG_INFO_H__ diff --git a/drivers/video/rockchip/rga/rga_rop.h b/drivers/video/rockchip/rga/rga_rop.h old mode 100755 new mode 100644 index 685818fc9e68..ed9758711022 --- a/drivers/video/rockchip/rga/rga_rop.h +++ b/drivers/video/rockchip/rga/rga_rop.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_ROP_H__ #define __RGA_ROP_H__ diff --git a/drivers/video/rockchip/rga/rga_type.h b/drivers/video/rockchip/rga/rga_type.h old mode 100755 new mode 100644 index 38a872034da1..ce3610ab9b67 --- a/drivers/video/rockchip/rga/rga_type.h +++ b/drivers/video/rockchip/rga/rga_type.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_TYPE_H__ #define __RGA_TYPE_H__ diff --git a/drivers/video/rockchip/rga2/Kconfig b/drivers/video/rockchip/rga2/Kconfig index e5258c66315a..efc1ef6dfa85 100644 --- a/drivers/video/rockchip/rga2/Kconfig +++ b/drivers/video/rockchip/rga2/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "RGA2" depends on ARCH_ROCKCHIP diff --git a/drivers/video/rockchip/rga2/Makefile b/drivers/video/rockchip/rga2/Makefile index 6cc0cfc366a4..210981d11f82 100644 --- a/drivers/video/rockchip/rga2/Makefile +++ b/drivers/video/rockchip/rga2/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 rga2-y := rga2_drv.o rga2_mmu_info.o rga2_reg_info.o RGA2_API.o obj-$(CONFIG_ROCKCHIP_RGA2) += rga2.o diff --git a/drivers/video/rockchip/rga2/RGA2_API.c b/drivers/video/rockchip/rga2/RGA2_API.c index 402020affa4a..177bad648b0b 100644 --- a/drivers/video/rockchip/rga2/RGA2_API.c +++ b/drivers/video/rockchip/rga2/RGA2_API.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include "RGA2_API.h" diff --git a/drivers/video/rockchip/rga2/RGA2_API.h b/drivers/video/rockchip/rga2/RGA2_API.h index a8873bd5e0ff..2f15e08e5d51 100644 --- a/drivers/video/rockchip/rga2/RGA2_API.h +++ b/drivers/video/rockchip/rga2/RGA2_API.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_API_H__ #define __RGA_API_H__ diff --git a/drivers/video/rockchip/rga2/rga2.h b/drivers/video/rockchip/rga2/rga2.h old mode 100755 new mode 100644 index 216147e7006b..f6ad0a743e3b --- a/drivers/video/rockchip/rga2/rga2.h +++ b/drivers/video/rockchip/rga2/rga2.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RGA_DRIVER_H_ #define _RGA_DRIVER_H_ diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.c b/drivers/video/rockchip/rga2/rga2_mmu_info.c index 5aef238540e4..72ff0099e356 100644 --- a/drivers/video/rockchip/rga2/rga2_mmu_info.c +++ b/drivers/video/rockchip/rga2/rga2_mmu_info.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.h b/drivers/video/rockchip/rga2/rga2_mmu_info.h index 79b8c2a73f2b..f342b68caf77 100644 --- a/drivers/video/rockchip/rga2/rga2_mmu_info.h +++ b/drivers/video/rockchip/rga2/rga2_mmu_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_MMU_INFO_H__ #define __RGA_MMU_INFO_H__ diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.c b/drivers/video/rockchip/rga2/rga2_reg_info.c old mode 100755 new mode 100644 index 358afbbc83fd..32adc15970e9 --- a/drivers/video/rockchip/rga2/rga2_reg_info.c +++ b/drivers/video/rockchip/rga2/rga2_reg_info.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ //#include #include diff --git a/drivers/video/rockchip/rga2/rga2_reg_info.h b/drivers/video/rockchip/rga2/rga2_reg_info.h old mode 100755 new mode 100644 index 29ba3c686cbd..422c96e33e7f --- a/drivers/video/rockchip/rga2/rga2_reg_info.h +++ b/drivers/video/rockchip/rga2/rga2_reg_info.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __REG2_INFO_H__ #define __REG2_INFO_H__ diff --git a/drivers/video/rockchip/rga2/rga2_rop.h b/drivers/video/rockchip/rga2/rga2_rop.h index 2b9a523b2c1a..9ec974b33d07 100644 --- a/drivers/video/rockchip/rga2/rga2_rop.h +++ b/drivers/video/rockchip/rga2/rga2_rop.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_ROP_H__ #define __RGA_ROP_H__ diff --git a/drivers/video/rockchip/rga2/rga2_type.h b/drivers/video/rockchip/rga2/rga2_type.h index 38a872034da1..ce3610ab9b67 100644 --- a/drivers/video/rockchip/rga2/rga2_type.h +++ b/drivers/video/rockchip/rga2/rga2_type.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RGA_TYPE_H__ #define __RGA_TYPE_H__ diff --git a/drivers/video/rockchip/screen/Kconfig b/drivers/video/rockchip/screen/Kconfig old mode 100755 new mode 100644 index 1502fff601c4..0292045dbff5 --- a/drivers/video/rockchip/screen/Kconfig +++ b/drivers/video/rockchip/screen/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 choice depends on FB_ROCKCHIP || DRM_ROCKCHIP prompt "LCD Panel Select" diff --git a/drivers/video/rockchip/screen/Makefile b/drivers/video/rockchip/screen/Makefile index d5297d06a6be..50df4d986cac 100644 --- a/drivers/video/rockchip/screen/Makefile +++ b/drivers/video/rockchip/screen/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_LCD_GENERAL) += lcd_general.o obj-$(CONFIG_LCD_MIPI) += lcd_mipi.o diff --git a/drivers/video/rockchip/screen/lcd_general.c b/drivers/video/rockchip/screen/lcd_general.c index b57dc2cbb86f..86e394fa822b 100644 --- a/drivers/video/rockchip/screen/lcd_general.c +++ b/drivers/video/rockchip/screen/lcd_general.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LCD_NULL__ #define __LCD_NULL__ diff --git a/drivers/video/rockchip/screen/rk_screen.c b/drivers/video/rockchip/screen/rk_screen.c index 3a4e6c3bb8ac..76676f55d9d4 100644 --- a/drivers/video/rockchip/screen/rk_screen.c +++ b/drivers/video/rockchip/screen/rk_screen.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/Kconfig b/drivers/video/rockchip/transmitter/Kconfig old mode 100755 new mode 100644 index f9320f51cde7..d316af591e75 --- a/drivers/video/rockchip/transmitter/Kconfig +++ b/drivers/video/rockchip/transmitter/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig RK_TRSM bool "RockChip display transmitter support" diff --git a/drivers/video/rockchip/transmitter/Makefile b/drivers/video/rockchip/transmitter/Makefile old mode 100755 new mode 100644 index c4cb48850ac4..c32da28414e5 --- a/drivers/video/rockchip/transmitter/Makefile +++ b/drivers/video/rockchip/transmitter/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for display transmitter like lvds edp mipi # diff --git a/drivers/video/rockchip/transmitter/anx6345.h b/drivers/video/rockchip/transmitter/anx6345.h index dbf6c5d55901..e386665431e8 100644 --- a/drivers/video/rockchip/transmitter/anx6345.h +++ b/drivers/video/rockchip/transmitter/anx6345.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ANX6345_H_ #define __ANX6345_H_ diff --git a/drivers/video/rockchip/transmitter/anx9805.h b/drivers/video/rockchip/transmitter/anx9805.h index e533051b5f06..fb513969a77f 100644 --- a/drivers/video/rockchip/transmitter/anx9805.h +++ b/drivers/video/rockchip/transmitter/anx9805.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DP_ANX9805_H_ #define _DP_ANX9805_H_ /**************register define for anx9805 anx9804********/ diff --git a/drivers/video/rockchip/transmitter/dp501.c b/drivers/video/rockchip/transmitter/dp501.c index 0414ae84e9df..79751296a3bd 100644 --- a/drivers/video/rockchip/transmitter/dp501.c +++ b/drivers/video/rockchip/transmitter/dp501.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/dp_anx6345.c b/drivers/video/rockchip/transmitter/dp_anx6345.c index 7fd0071822af..e460400320f3 100644 --- a/drivers/video/rockchip/transmitter/dp_anx6345.c +++ b/drivers/video/rockchip/transmitter/dp_anx6345.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/dpcd_edid.h b/drivers/video/rockchip/transmitter/dpcd_edid.h index 5cf883d2f7a5..d41dc86ae53c 100644 --- a/drivers/video/rockchip/transmitter/dpcd_edid.h +++ b/drivers/video/rockchip/transmitter/dpcd_edid.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DPCD_EDID_H #define __DPCD_EDID_H #include "../../fbdev/edid.h" diff --git a/drivers/video/rockchip/transmitter/mipi_dsi.h b/drivers/video/rockchip/transmitter/mipi_dsi.h index 0ce69bbf4a57..f3a041cb62eb 100644 --- a/drivers/video/rockchip/transmitter/mipi_dsi.h +++ b/drivers/video/rockchip/transmitter/mipi_dsi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* drivers/video/rockchip/transmitter/mipi_dsi.h */ diff --git a/drivers/video/rockchip/transmitter/rk2928_lvds.c b/drivers/video/rockchip/transmitter/rk2928_lvds.c index 30adbed99121..cb3a2516a7f7 100644 --- a/drivers/video/rockchip/transmitter/rk2928_lvds.c +++ b/drivers/video/rockchip/transmitter/rk2928_lvds.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/rk2928_lvds.h b/drivers/video/rockchip/transmitter/rk2928_lvds.h index 6cd2f889afd6..4c8e06ccdec5 100644 --- a/drivers/video/rockchip/transmitter/rk2928_lvds.h +++ b/drivers/video/rockchip/transmitter/rk2928_lvds.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RK_LVDS_H_ #define RK_LVDS_H diff --git a/drivers/video/rockchip/transmitter/rk3026_lvds.c b/drivers/video/rockchip/transmitter/rk3026_lvds.c old mode 100755 new mode 100644 index a4d5f39dbeb9..eb9a439fc58a --- a/drivers/video/rockchip/transmitter/rk3026_lvds.c +++ b/drivers/video/rockchip/transmitter/rk3026_lvds.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/rk3026_lvds.h b/drivers/video/rockchip/transmitter/rk3026_lvds.h old mode 100755 new mode 100644 index 6c5789e2273b..882759e8bcb8 --- a/drivers/video/rockchip/transmitter/rk3026_lvds.h +++ b/drivers/video/rockchip/transmitter/rk3026_lvds.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include diff --git a/drivers/video/rockchip/transmitter/rk31xx_lvds.h b/drivers/video/rockchip/transmitter/rk31xx_lvds.h old mode 100755 new mode 100644 index 53adcc237cb3..55becf7b1307 --- a/drivers/video/rockchip/transmitter/rk31xx_lvds.h +++ b/drivers/video/rockchip/transmitter/rk31xx_lvds.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK31XX_LVDS_H_ #define _RK31XX_LVDS_H_ diff --git a/drivers/video/rockchip/transmitter/rk32_dp.h b/drivers/video/rockchip/transmitter/rk32_dp.h old mode 100755 new mode 100644 index 2dc41c6b2ec5..7b0764452995 --- a/drivers/video/rockchip/transmitter/rk32_dp.h +++ b/drivers/video/rockchip/transmitter/rk32_dp.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK32_DP_H #define __RK32_DP_H diff --git a/drivers/video/rockchip/transmitter/rk32_lvds.c b/drivers/video/rockchip/transmitter/rk32_lvds.c old mode 100755 new mode 100644 index 3e8394f00543..4a1dc1194ec5 --- a/drivers/video/rockchip/transmitter/rk32_lvds.c +++ b/drivers/video/rockchip/transmitter/rk32_lvds.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/rk32_lvds.h b/drivers/video/rockchip/transmitter/rk32_lvds.h old mode 100755 new mode 100644 index ca424a73f2e0..db434c010b20 --- a/drivers/video/rockchip/transmitter/rk32_lvds.h +++ b/drivers/video/rockchip/transmitter/rk32_lvds.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK32_LVDS__ #define __RK32_LVDS__ diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h index f5682548c872..ad6748d879eb 100644 --- a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h +++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* drivers/video/rockchip/transmitter/rk32_mipi_dsi.h */ diff --git a/drivers/video/rockchip/transmitter/rk610_lcd.c b/drivers/video/rockchip/transmitter/rk610_lcd.c index 3b842915ccea..a8d87450b160 100644 --- a/drivers/video/rockchip/transmitter/rk610_lcd.c +++ b/drivers/video/rockchip/transmitter/rk610_lcd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/rk610_lcd.h b/drivers/video/rockchip/transmitter/rk610_lcd.h index 33a4957b72cf..1f6e5357c619 100644 --- a/drivers/video/rockchip/transmitter/rk610_lcd.h +++ b/drivers/video/rockchip/transmitter/rk610_lcd.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK610_LCD_H #define _RK610_LCD_H #include diff --git a/drivers/video/rockchip/transmitter/rk616_lvds.c b/drivers/video/rockchip/transmitter/rk616_lvds.c old mode 100755 new mode 100644 index f08740f3e831..d70b458b9fbd --- a/drivers/video/rockchip/transmitter/rk616_lvds.c +++ b/drivers/video/rockchip/transmitter/rk616_lvds.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/transmitter/rk616_lvds.h b/drivers/video/rockchip/transmitter/rk616_lvds.h index 2b6b27427ad4..7f57105607ea 100644 --- a/drivers/video/rockchip/transmitter/rk616_lvds.h +++ b/drivers/video/rockchip/transmitter/rk616_lvds.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK616_VIF_H__ #define __RK616_VIF_H__ #include diff --git a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h old mode 100755 new mode 100644 index 987e86ae3e96..9c857453ecc7 --- a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h +++ b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* drivers/video/rockchip/transmitter/rk616_mipi_dsi.h */ diff --git a/drivers/video/rockchip/transmitter/vga.c b/drivers/video/rockchip/transmitter/vga.c index f5a6fc8136b7..b178fd27a9d6 100644 --- a/drivers/video/rockchip/transmitter/vga.c +++ b/drivers/video/rockchip/transmitter/vga.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/tve/Kconfig b/drivers/video/rockchip/tve/Kconfig index 802f8ed1f8a0..b15183806951 100644 --- a/drivers/video/rockchip/tve/Kconfig +++ b/drivers/video/rockchip/tve/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # TV Encoder drivers configuration # diff --git a/drivers/video/rockchip/tve/Makefile b/drivers/video/rockchip/tve/Makefile index d99fb3587dd2..5bccf1e24e0e 100644 --- a/drivers/video/rockchip/tve/Makefile +++ b/drivers/video/rockchip/tve/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for tv encoder. # diff --git a/drivers/video/rockchip/tve/gm7122/Kconfig b/drivers/video/rockchip/tve/gm7122/Kconfig index c047687a263c..40e8058c49c6 100644 --- a/drivers/video/rockchip/tve/gm7122/Kconfig +++ b/drivers/video/rockchip/tve/gm7122/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config GM7122_TV_ENCODER bool "gm7122 tv encoder support" depends on RK_TVENCODER diff --git a/drivers/video/rockchip/tve/gm7122/Makefile b/drivers/video/rockchip/tve/gm7122/Makefile index 580a99b3dc7a..da3f980f460f 100644 --- a/drivers/video/rockchip/tve/gm7122/Makefile +++ b/drivers/video/rockchip/tve/gm7122/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the gm7122 tv encoder control. # diff --git a/drivers/video/rockchip/tve/gm7122/gm7122_tve.h b/drivers/video/rockchip/tve/gm7122/gm7122_tve.h index e03ca9e7f87e..371e0821acf5 100644 --- a/drivers/video/rockchip/tve/gm7122/gm7122_tve.h +++ b/drivers/video/rockchip/tve/gm7122/gm7122_tve.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __GM7122_TVE_H__ #define __GM7122_TVE_H__ diff --git a/drivers/video/rockchip/tve/rk1000/Kconfig b/drivers/video/rockchip/tve/rk1000/Kconfig old mode 100755 new mode 100644 index a708973a5c6c..f4f12932addb --- a/drivers/video/rockchip/tve/rk1000/Kconfig +++ b/drivers/video/rockchip/tve/rk1000/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # TV Encoder RK1000 drivers configuration # diff --git a/drivers/video/rockchip/tve/rk1000/Makefile b/drivers/video/rockchip/tve/rk1000/Makefile old mode 100755 new mode 100644 index d229b49f940a..f11ba60f39a8 --- a/drivers/video/rockchip/tve/rk1000/Makefile +++ b/drivers/video/rockchip/tve/rk1000/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the RK1000 tv control. # diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve.h b/drivers/video/rockchip/tve/rk1000/rk1000_tve.h old mode 100755 new mode 100644 index baf20837b4bc..8d78a2f2de7a --- a/drivers/video/rockchip/tve/rk1000/rk1000_tve.h +++ b/drivers/video/rockchip/tve/rk1000/rk1000_tve.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK1000_TVE_H #define _RK1000_TVE_H #include diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c b/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c old mode 100755 new mode 100644 index 4804d9ea0b7e..adb4cbc0ceb1 --- a/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c +++ b/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c b/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c old mode 100755 new mode 100644 index baa47e5fc40b..aa4189a518f7 --- a/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c +++ b/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include "rk1000_tve.h" diff --git a/drivers/video/rockchip/tve/rk3036/Kconfig b/drivers/video/rockchip/tve/rk3036/Kconfig index eadde36e659d..4727a581e2c4 100644 --- a/drivers/video/rockchip/tve/rk3036/Kconfig +++ b/drivers/video/rockchip/tve/rk3036/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK3036_TV_ENCODER bool "rk3036/3128 tv encoder support" depends on (LCDC_RK3036 || LCDC_RK312X) && RK_TVENCODER diff --git a/drivers/video/rockchip/tve/rk3036/Makefile b/drivers/video/rockchip/tve/rk3036/Makefile index 850404a1bdd3..0f5c85ebaea0 100644 --- a/drivers/video/rockchip/tve/rk3036/Makefile +++ b/drivers/video/rockchip/tve/rk3036/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the rk3036 tv encoder control. # diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h index b0c2a24d3e06..73c42d36e377 100644 --- a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h +++ b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK3036_TVE_H__ #define __RK3036_TVE_H__ diff --git a/drivers/video/rockchip/tve/rk610/Kconfig b/drivers/video/rockchip/tve/rk610/Kconfig index 74eaf28651be..f07e6338117c 100644 --- a/drivers/video/rockchip/tve/rk610/Kconfig +++ b/drivers/video/rockchip/tve/rk610/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config RK610_TVOUT bool "RK610(Jetta) tvout support" depends on MFD_RK610 diff --git a/drivers/video/rockchip/tve/rk610/Makefile b/drivers/video/rockchip/tve/rk610/Makefile index b7d457326d26..83fe50be609d 100644 --- a/drivers/video/rockchip/tve/rk610/Makefile +++ b/drivers/video/rockchip/tve/rk610/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the jetta tv control. # diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv.h b/drivers/video/rockchip/tve/rk610/rk610_tv.h index ead23a8a06a1..3f69bb9e2f5c 100644 --- a/drivers/video/rockchip/tve/rk610/rk610_tv.h +++ b/drivers/video/rockchip/tve/rk610/rk610_tv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK610_TV_H #define _RK610_TV_H #include diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c b/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c index ea0fe8a0d79c..402945378c67 100644 --- a/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c +++ b/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c b/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c index af74126f7604..b6f78edddb33 100644 --- a/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c +++ b/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/drivers/video/rockchip/vcodec/Kconfig b/drivers/video/rockchip/vcodec/Kconfig index 149b2dffcfdf..ea898cc994e9 100644 --- a/drivers/video/rockchip/vcodec/Kconfig +++ b/drivers/video/rockchip/vcodec/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "VCODEC" depends on ARCH_ROCKCHIP diff --git a/drivers/video/rockchip/vcodec/Makefile b/drivers/video/rockchip/vcodec/Makefile index 93a5571e88a1..a327742a271b 100644 --- a/drivers/video/rockchip/vcodec/Makefile +++ b/drivers/video/rockchip/vcodec/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 rk-vcodec-objs := vcodec_service.o vcodec_iommu_ops.o ifdef CONFIG_DRM diff --git a/drivers/video/rockchip/vpu/Kconfig b/drivers/video/rockchip/vpu/Kconfig index 5bb2f4795a4b..8a0c459c9f3c 100644 --- a/drivers/video/rockchip/vpu/Kconfig +++ b/drivers/video/rockchip/vpu/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 menu "ROCKCHIP_MPP" depends on ARCH_ROCKCHIP diff --git a/drivers/video/rockchip/vpu/Makefile b/drivers/video/rockchip/vpu/Makefile index 0dc4780c2407..40a0a0df083e 100644 --- a/drivers/video/rockchip/vpu/Makefile +++ b/drivers/video/rockchip/vpu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += mpp_service.o obj-$(CONFIG_ROCKCHIP_MPP_DEVICE) += mpp_dev_rkvenc.o mpp_dev_vepu.o \ mpp_dev_h265e.o mpp_dev_common.o vpu_iommu_drm.o vpu_iommu_ion.o \ diff --git a/include/dt-bindings/clock/rockchip,rk3368.h b/include/dt-bindings/clock/rockchip,rk3368.h index 9ebf185d8941..76630794b4d9 100644 --- a/include/dt-bindings/clock/rockchip,rk3368.h +++ b/include/dt-bindings/clock/rockchip,rk3368.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H #define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h index a7c8c5cc42ba..b438f7bd4083 100644 --- a/include/dt-bindings/clock/rockchip.h +++ b/include/dt-bindings/clock/rockchip.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_H #define _DT_BINDINGS_CLOCK_ROCKCHIP_H diff --git a/include/dt-bindings/display/mipi_dsi.h b/include/dt-bindings/display/mipi_dsi.h old mode 100755 new mode 100644 index 07a2dce9778f..38aeee0ed51d --- a/include/dt-bindings/display/mipi_dsi.h +++ b/include/dt-bindings/display/mipi_dsi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* drivers/video/rockchip/transmitter/mipi_dsi.h */ diff --git a/include/dt-bindings/display/rk_fb.h b/include/dt-bindings/display/rk_fb.h old mode 100755 new mode 100644 index 81c98558771c..0b4594b2b055 --- a/include/dt-bindings/display/rk_fb.h +++ b/include/dt-bindings/display/rk_fb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DT_BINDINGS_RKFB_H_ #define _DT_BINDINGS_RKFB_H_ #define GPIO 0 diff --git a/include/dt-bindings/display/screen-timing/lcd-86v-rgb1024x600.dtsi b/include/dt-bindings/display/screen-timing/lcd-86v-rgb1024x600.dtsi index bfad8080c9e9..dcca65671ffb 100644 --- a/include/dt-bindings/display/screen-timing/lcd-86v-rgb1024x600.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-86v-rgb1024x600.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_RGB1024x600 FOR 86V * diff --git a/include/dt-bindings/display/screen-timing/lcd-F402.dtsi b/include/dt-bindings/display/screen-timing/lcd-F402.dtsi index a3ad25ffea38..0a7a45ad935e 100644 --- a/include/dt-bindings/display/screen-timing/lcd-F402.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-F402.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. DisplayPort screen LP097QX1 * diff --git a/include/dt-bindings/display/screen-timing/lcd-LP097Qx1.dtsi b/include/dt-bindings/display/screen-timing/lcd-LP097Qx1.dtsi index 18a41459aebf..9a11edbdd84e 100644 --- a/include/dt-bindings/display/screen-timing/lcd-LP097Qx1.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-LP097Qx1.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. DisplayPort screen LP097QX1 * diff --git a/include/dt-bindings/display/screen-timing/lcd-b101ew05.dtsi b/include/dt-bindings/display/screen-timing/lcd-b101ew05.dtsi index 130f5049723f..ff15d837e166 100644 --- a/include/dt-bindings/display/screen-timing/lcd-b101ew05.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-b101ew05.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_B101ew05 * diff --git a/include/dt-bindings/display/screen-timing/lcd-box.dtsi b/include/dt-bindings/display/screen-timing/lcd-box.dtsi index 2109a8963a45..25368db39d29 100644 --- a/include/dt-bindings/display/screen-timing/lcd-box.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-box.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_BOX * diff --git a/include/dt-bindings/display/screen-timing/lcd-ld089wu1-mipi.dtsi b/include/dt-bindings/display/screen-timing/lcd-ld089wu1-mipi.dtsi index 6643da5cc096..a20e51a37d69 100644 --- a/include/dt-bindings/display/screen-timing/lcd-ld089wu1-mipi.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-ld089wu1-mipi.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2014 ROCKCHIP, Inc. * arch/arm/boot/dts/lcd-lq070m1sx01-mipi.dtsi diff --git a/include/dt-bindings/display/screen-timing/lcd-lq070m1sx01-mipi.dtsi b/include/dt-bindings/display/screen-timing/lcd-lq070m1sx01-mipi.dtsi index 2d21964c137e..5f83e3b0d407 100644 --- a/include/dt-bindings/display/screen-timing/lcd-lq070m1sx01-mipi.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-lq070m1sx01-mipi.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2014 ROCKCHIP, Inc. * arch/arm/boot/dts/lcd-lq070m1sx01-mipi.dtsi diff --git a/include/dt-bindings/display/screen-timing/lcd-rk3128-86v-LVDS1024x600.dtsi b/include/dt-bindings/display/screen-timing/lcd-rk3128-86v-LVDS1024x600.dtsi index 3895431d421f..c4cbc6d9c058 100644 --- a/include/dt-bindings/display/screen-timing/lcd-rk3128-86v-LVDS1024x600.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-rk3128-86v-LVDS1024x600.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_LVDS1024x600 FOR rk3128-86V * diff --git a/include/dt-bindings/display/screen-timing/lcd-td043mgeal.dtsi b/include/dt-bindings/display/screen-timing/lcd-td043mgeal.dtsi index db20efa3c769..32583775b084 100644 --- a/include/dt-bindings/display/screen-timing/lcd-td043mgeal.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-td043mgeal.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_TD043MGEA1 FOR FPGA * diff --git a/include/dt-bindings/display/screen-timing/lcd-tv080wum-mipi.dtsi b/include/dt-bindings/display/screen-timing/lcd-tv080wum-mipi.dtsi index 9ae774cccbf7..2bf4ef99b506 100644 --- a/include/dt-bindings/display/screen-timing/lcd-tv080wum-mipi.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-tv080wum-mipi.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2014 ROCKCHIP, Inc. * arch/arm/boot/dts/lcd-lq070m1sx01-mipi.dtsi diff --git a/include/dt-bindings/display/screen-timing/lcd-vga.dtsi b/include/dt-bindings/display/screen-timing/lcd-vga.dtsi index 8f0c8eaafd49..13d214b2e8c8 100644 --- a/include/dt-bindings/display/screen-timing/lcd-vga.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-vga.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. VGA timing * diff --git a/include/dt-bindings/display/screen-timing/lcd-wqxga-mipi.dtsi b/include/dt-bindings/display/screen-timing/lcd-wqxga-mipi.dtsi index 270e98d1972a..e41c7d147747 100644 --- a/include/dt-bindings/display/screen-timing/lcd-wqxga-mipi.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-wqxga-mipi.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2014 ROCKCHIP, Inc. * arch/arm/boot/dts/lcd-lq070m1sx01-mipi.dtsi diff --git a/include/dt-bindings/display/screen-timing/lcd-y81349.dtsi b/include/dt-bindings/display/screen-timing/lcd-y81349.dtsi index fabaf6db9e89..f0db3a36b142 100644 --- a/include/dt-bindings/display/screen-timing/lcd-y81349.dtsi +++ b/include/dt-bindings/display/screen-timing/lcd-y81349.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * RockChip. LCD_Y81349 FOR 86V * diff --git a/include/dt-bindings/input/rk-input.h b/include/dt-bindings/input/rk-input.h index 2b1990d61e7f..00b412927890 100644 --- a/include/dt-bindings/input/rk-input.h +++ b/include/dt-bindings/input/rk-input.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Device properties and quirks */ diff --git a/include/dt-bindings/pinctrl/rockchip-rk3036.h b/include/dt-bindings/pinctrl/rockchip-rk3036.h index 01bf49ed1b09..553c33579065 100644 --- a/include/dt-bindings/pinctrl/rockchip-rk3036.h +++ b/include/dt-bindings/pinctrl/rockchip-rk3036.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_RK3036_H__ #define __DT_BINDINGS_ROCKCHIP_PINCTRL_RK3036_H__ diff --git a/include/dt-bindings/pinctrl/rockchip-rk312x.h b/include/dt-bindings/pinctrl/rockchip-rk312x.h old mode 100755 new mode 100644 index 4bd5a1698d56..e0fa5976c18f --- a/include/dt-bindings/pinctrl/rockchip-rk312x.h +++ b/include/dt-bindings/pinctrl/rockchip-rk312x.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_RK312X_H__ #define __DT_BINDINGS_ROCKCHIP_PINCTRL_RK312X_H__ diff --git a/include/dt-bindings/power/rk3328-power.h b/include/dt-bindings/power/rk3328-power.h index 10c3c3715334..02e3d7fc1cce 100644 --- a/include/dt-bindings/power/rk3328-power.h +++ b/include/dt-bindings/power/rk3328-power.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_POWER_RK3328_POWER_H__ #define __DT_BINDINGS_POWER_RK3328_POWER_H__ diff --git a/include/dt-bindings/power/rk3366-power.h b/include/dt-bindings/power/rk3366-power.h index 223a3dce049a..af912a40b410 100644 --- a/include/dt-bindings/power/rk3366-power.h +++ b/include/dt-bindings/power/rk3366-power.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_POWER_RK3366_POWER_H__ #define __DT_BINDINGS_POWER_RK3366_POWER_H__ diff --git a/include/dt-bindings/power/rk3368-power.h b/include/dt-bindings/power/rk3368-power.h index 93633d57ed84..5e602dbd64ec 100644 --- a/include/dt-bindings/power/rk3368-power.h +++ b/include/dt-bindings/power/rk3368-power.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_POWER_RK3368_POWER_H__ #define __DT_BINDINGS_POWER_RK3368_POWER_H__ diff --git a/include/dt-bindings/power/rk3399-power.h b/include/dt-bindings/power/rk3399-power.h index 168b3bfbd6f5..aedd8b180fe4 100644 --- a/include/dt-bindings/power/rk3399-power.h +++ b/include/dt-bindings/power/rk3399-power.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_POWER_RK3399_POWER_H__ #define __DT_BINDINGS_POWER_RK3399_POWER_H__ diff --git a/include/dt-bindings/sensor-dev.h b/include/dt-bindings/sensor-dev.h old mode 100755 new mode 100644 index 1533243cd892..e03f0027d325 --- a/include/dt-bindings/sensor-dev.h +++ b/include/dt-bindings/sensor-dev.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DT_BINDINGS_ROCKCHIP_SENSORDEV_H__ #define __DT_BINDINGS_ROCKCHIP_SENSORDEV_H__ diff --git a/include/dt-bindings/soc/rockchip,boot-mode.h b/include/dt-bindings/soc/rockchip,boot-mode.h index 1dfc4f4fa759..01e934fbec40 100644 --- a/include/dt-bindings/soc/rockchip,boot-mode.h +++ b/include/dt-bindings/soc/rockchip,boot-mode.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_BOOT_MODE_H #define __ROCKCHIP_BOOT_MODE_H diff --git a/include/linux/akm8963.h b/include/linux/akm8963.h index 431dfdfdfa43..c0914add8c5e 100644 --- a/include/linux/akm8963.h +++ b/include/linux/akm8963.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for akm8963 compass chip. */ diff --git a/include/linux/board-id-hw.h b/include/linux/board-id-hw.h old mode 100755 new mode 100644 index f8909084a2b7..0e5032d18bfc --- a/include/linux/board-id-hw.h +++ b/include/linux/board-id-hw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ enum board_id_hw{ BOARD_ID_INVALID = -1, diff --git a/include/linux/board-id-operator.h b/include/linux/board-id-operator.h old mode 100755 new mode 100644 index e4d2f5ebdec3..316f8cde3dca --- a/include/linux/board-id-operator.h +++ b/include/linux/board-id-operator.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __BOARD_ID_OPERATOR_H #define __BOARD_ID_OPERATOR_H diff --git a/include/linux/board-id.h b/include/linux/board-id.h old mode 100755 new mode 100644 index b121a10dcab7..1794ad5be315 --- a/include/linux/board-id.h +++ b/include/linux/board-id.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __BOARD_ID_H #define __BOARD_ID_H #include diff --git a/include/linux/bp-auto.h b/include/linux/bp-auto.h old mode 100755 new mode 100644 index 602592ff7d19..40d91c7fd128 --- a/include/linux/bp-auto.h +++ b/include/linux/bp-auto.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _BP_AUTO_H #define _BP_AUTO_H #include diff --git a/include/linux/ct36x.h b/include/linux/ct36x.h index c3121ddda92a..ea5535ab097b 100644 --- a/include/linux/ct36x.h +++ b/include/linux/ct36x.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_CT36X__ #define __LINUX_CT36X__ diff --git a/include/linux/display-sys.h b/include/linux/display-sys.h index ac3f3870c16b..328e26aebeec 100644 --- a/include/linux/display-sys.h +++ b/include/linux/display-sys.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_DISPLAY_RK_H #define _LINUX_DISPLAY_RK_H diff --git a/include/linux/dp501.h b/include/linux/dp501.h index 2e9fb4a7bf1d..82cac02b82cd 100644 --- a/include/linux/dp501.h +++ b/include/linux/dp501.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __DP501_H_ #define __DP501_H_ diff --git a/include/linux/goodix_queue.h b/include/linux/goodix_queue.h old mode 100755 new mode 100644 index 85b599af5b58..a298cd4cda9f --- a/include/linux/goodix_queue.h +++ b/include/linux/goodix_queue.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*--------------------------------------------------------------------------------------------------------- * kernel/include/linux/goodix_queue.h * diff --git a/include/linux/goodix_touch.h b/include/linux/goodix_touch.h old mode 100755 new mode 100644 index 989154317f30..b51ad5282769 --- a/include/linux/goodix_touch.h +++ b/include/linux/goodix_touch.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*--------------------------------------------------------------------------------------------------------- * kernel/include/linux/goodix_touch.h * diff --git a/include/linux/goodix_touch_82x.h b/include/linux/goodix_touch_82x.h old mode 100755 new mode 100644 index 2fa45072c4d4..0b8f92fb04f6 --- a/include/linux/goodix_touch_82x.h +++ b/include/linux/goodix_touch_82x.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * * Copyright (C) 2011 Goodix, Inc. diff --git a/include/linux/gps.h b/include/linux/gps.h old mode 100755 new mode 100644 index 4a2a4a3e1e58..3df5d4ecdbbe --- a/include/linux/gps.h +++ b/include/linux/gps.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __GPS_H__ #define __GPS_H__ diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h index 9c5ad498f610..b75b0da280c9 100644 --- a/include/linux/hdmi-notifier.h +++ b/include/linux/hdmi-notifier.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef LINUX_HDMI_NOTIFIER_H #define LINUX_HDMI_NOTIFIER_H diff --git a/include/linux/kxtik.h b/include/linux/kxtik.h old mode 100755 new mode 100644 index 28ef3c732968..6f25dd89bc73 --- a/include/linux/kxtik.h +++ b/include/linux/kxtik.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define KXTIK_DEVID 0x05 //chip id #define KXTIK_RANGE 2000000 diff --git a/include/linux/mfd/rk610_core.h b/include/linux/mfd/rk610_core.h old mode 100755 new mode 100644 index f8415ee5ba57..19f341107db7 --- a/include/linux/mfd/rk610_core.h +++ b/include/linux/mfd/rk610_core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK610_CONTROL_H_ #define __RK610_CONTROL_H_ diff --git a/include/linux/mfd/rk616.h b/include/linux/mfd/rk616.h old mode 100755 new mode 100644 index e0928434f4a4..93125b75bf7b --- a/include/linux/mfd/rk616.h +++ b/include/linux/mfd/rk616.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _RK616_H_ #define _RK616_H_ diff --git a/include/linux/mfd/tlv320aic3262-core.h b/include/linux/mfd/tlv320aic3262-core.h index 165f5e4c9cbf..121d2ab75e4c 100644 --- a/include/linux/mfd/tlv320aic3262-core.h +++ b/include/linux/mfd/tlv320aic3262-core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __MFD_AIC3262_CORE_H__ #define __MFD_AIC3262_CORE_H__ diff --git a/include/linux/mfd/tlv320aic3262-registers.h b/include/linux/mfd/tlv320aic3262-registers.h index 169dba69787b..19e5556932d7 100644 --- a/include/linux/mfd/tlv320aic3262-registers.h +++ b/include/linux/mfd/tlv320aic3262-registers.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __MFD_AIC3262_REGISTERS_H__ #define __MFD_AIC3262_REGISTERS_H__ diff --git a/include/linux/mi700.h b/include/linux/mi700.h index df20b2c9d93a..bfb96abb64e6 100644 --- a/include/linux/mi700.h +++ b/include/linux/mi700.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/mma7660.h b/include/linux/mma7660.h index ea2f68175717..8f30ce6f3d3f 100644 --- a/include/linux/mma7660.h +++ b/include/linux/mma7660.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for mma7660 compass chip. */ diff --git a/include/linux/mma8452.h b/include/linux/mma8452.h old mode 100755 new mode 100644 index ef9e4f607a4c..b97d2900d833 --- a/include/linux/mma8452.h +++ b/include/linux/mma8452.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for mma8452 compass chip. */ diff --git a/include/linux/mpu6500.h b/include/linux/mpu6500.h index e601c300b490..2b45884a724b 100644 --- a/include/linux/mpu6500.h +++ b/include/linux/mpu6500.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for mma8452 compass chip. */ diff --git a/include/linux/mpu6880.h b/include/linux/mpu6880.h index 4e4e6026c89a..a0cb445c531e 100644 --- a/include/linux/mpu6880.h +++ b/include/linux/mpu6880.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for mma8452 compass chip. */ diff --git a/include/linux/mt6229.h b/include/linux/mt6229.h index 35595aede4ed..5f4838695b48 100644 --- a/include/linux/mt6229.h +++ b/include/linux/mt6229.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/mtk23d.h b/include/linux/mtk23d.h old mode 100755 new mode 100644 index 28facec4e825..f48da1a8c343 --- a/include/linux/mtk23d.h +++ b/include/linux/mtk23d.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/mu509.h b/include/linux/mu509.h old mode 100755 new mode 100644 index 65f237f98c81..e32d098cab6e --- a/include/linux/mu509.h +++ b/include/linux/mu509.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/mw100.h b/include/linux/mw100.h index 668fc2f86703..3c05c6d1a3cf 100644 --- a/include/linux/mw100.h +++ b/include/linux/mw100.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/platform_data/sram.h b/include/linux/platform_data/sram.h index 8f5c4bab1860..38db9ae07308 100644 --- a/include/linux/platform_data/sram.h +++ b/include/linux/platform_data/sram.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_SRAM_H #define _LINUX_SRAM_H diff --git a/include/linux/power/bq24296_charger.h b/include/linux/power/bq24296_charger.h old mode 100755 new mode 100644 index 24a53626e6ce..41afe25b35f5 --- a/include/linux/power/bq24296_charger.h +++ b/include/linux/power/bq24296_charger.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Definitions for mma8452 compass chip. */ diff --git a/include/linux/power/rk_usbbc.h b/include/linux/power/rk_usbbc.h index c2113d50d0cb..2372077f24e7 100644 --- a/include/linux/power/rk_usbbc.h +++ b/include/linux/power/rk_usbbc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RK_USBBC_H #define __RK_USBBC_H diff --git a/include/linux/power/rockchip-6200ma-bat.h b/include/linux/power/rockchip-6200ma-bat.h old mode 100755 new mode 100644 index 8cfc32aafd54..6a3106897852 --- a/include/linux/power/rockchip-6200ma-bat.h +++ b/include/linux/power/rockchip-6200ma-bat.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ battery_graph_prop rt5025_battery_param1[] = { {4190, 1000}, diff --git a/include/linux/power/rockchip-general-bat.h b/include/linux/power/rockchip-general-bat.h old mode 100755 new mode 100644 index ae5eb522627c..73236fde2360 --- a/include/linux/power/rockchip-general-bat.h +++ b/include/linux/power/rockchip-general-bat.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ battery_graph_prop rt5025_battery_param1[] = { {4190, 1000}, {4153, 980}, diff --git a/include/linux/rfkill-wlan.h b/include/linux/rfkill-wlan.h index bc14c93b6df2..f529cfd43b78 100644 --- a/include/linux/rfkill-wlan.h +++ b/include/linux/rfkill-wlan.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __PLAT_BOARD_H #define __PLAT_BOARD_H diff --git a/include/linux/rk_board_id.h b/include/linux/rk_board_id.h old mode 100755 new mode 100644 index 0bb112475c3d..c715d3aca238 --- a/include/linux/rk_board_id.h +++ b/include/linux/rk_board_id.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ enum rk_board_id{ BOARD_ID_INVALID = -1, diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h index 67e75c224470..9800bb378a1e 100644 --- a/include/linux/rk_screen.h +++ b/include/linux/rk_screen.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _SCREEN_H #define _SCREEN_H diff --git a/include/linux/rockchip/grf.h b/include/linux/rockchip/grf.h old mode 100755 new mode 100644 index ab033722ef6b..fae51232297c --- a/include/linux/rockchip/grf.h +++ b/include/linux/rockchip/grf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __MACH_ROCKCHIP_GRF_H #define __MACH_ROCKCHIP_GRF_H diff --git a/include/linux/rockchip/pmu.h b/include/linux/rockchip/pmu.h index f05ce7a36a8a..5346ec763b2b 100644 --- a/include/linux/rockchip/pmu.h +++ b/include/linux/rockchip/pmu.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __MACH_ROCKCHIP_PMU_H #define __MACH_ROCKCHIP_PMU_H diff --git a/include/linux/rockchip/psci.h b/include/linux/rockchip/psci.h index 7a3eed6f9853..870da27edf65 100644 --- a/include/linux/rockchip/psci.h +++ b/include/linux/rockchip/psci.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ROCKCHIP_PSCI_H #define __ROCKCHIP_PSCI_H diff --git a/include/linux/sc6610.h b/include/linux/sc6610.h old mode 100755 new mode 100644 index 66414dc203a6..2b2a6529586e --- a/include/linux/sc6610.h +++ b/include/linux/sc6610.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/scaler-core.h b/include/linux/scaler-core.h index 41ed49018fc2..b2b187de72d8 100644 --- a/include/linux/scaler-core.h +++ b/include/linux/scaler-core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __SCALER_CORE_H__ #define __SCALER_CORE_H__ #include diff --git a/include/linux/sew868.h b/include/linux/sew868.h old mode 100755 new mode 100644 index 3d09ccbdd03e..719c976908ce --- a/include/linux/sew868.h +++ b/include/linux/sew868.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/include/linux/soc/rockchip/pvtm.h b/include/linux/soc/rockchip/pvtm.h index 11f99dfa7b0c..32c7341c3ece 100644 --- a/include/linux/soc/rockchip/pvtm.h +++ b/include/linux/soc/rockchip/pvtm.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __SOC_ROCKCHIP_PVTM_H #define __SOC_ROCKCHIP_PVTM_H diff --git a/include/linux/soc/rockchip/rk_fiq_debugger.h b/include/linux/soc/rockchip/rk_fiq_debugger.h index c5ea29302644..0398974d2e13 100644 --- a/include/linux/soc/rockchip/rk_fiq_debugger.h +++ b/include/linux/soc/rockchip/rk_fiq_debugger.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __PLAT_RK_FIQ_DEBUGGER_H #define __PLAT_RK_FIQ_DEBUGGER_H diff --git a/include/linux/ste.h b/include/linux/ste.h index a31d1e9e772c..6f85d81c2ffd 100644 --- a/include/linux/ste.h +++ b/include/linux/ste.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include diff --git a/include/linux/ts-auto.h b/include/linux/ts-auto.h old mode 100755 new mode 100644 index 459a06960d3d..d029328e7005 --- a/include/linux/ts-auto.h +++ b/include/linux/ts-auto.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __TS_AUTO_H #define __TS_AUTO_H #include diff --git a/include/media/camsys_head.h b/include/media/camsys_head.h index 638d567452fd..4b9bcc5dd831 100644 --- a/include/media/camsys_head.h +++ b/include/media/camsys_head.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RKCAMSYS_HEAR_H__ #define __RKCAMSYS_HEAR_H__ diff --git a/include/soc/rockchip/rkfb_dmc.h b/include/soc/rockchip/rkfb_dmc.h index 28b2e3979b6b..5e82b3194dd3 100644 --- a/include/soc/rockchip/rkfb_dmc.h +++ b/include/soc/rockchip/rkfb_dmc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Rockchip devfb driver will probe earlier than devfreq, so it needs to register * dmc_notify after than rk3399 dmc driver. diff --git a/include/trace/events/sync.h b/include/trace/events/sync.h index f31bc63ca65d..a1c58d1c25e9 100644 --- a/include/trace/events/sync.h +++ b/include/trace/events/sync.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #undef TRACE_SYSTEM #define TRACE_SYSTEM sync diff --git a/security/optee_linuxdriver/Makefile b/security/optee_linuxdriver/Makefile index 493734fc6814..59bfa8004fc0 100644 --- a/security/optee_linuxdriver/Makefile +++ b/security/optee_linuxdriver/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TEE_SUPPORT) += core/ obj-$(CONFIG_TEE_SUPPORT) += armtz/ diff --git a/security/optee_linuxdriver/armtz/Makefile b/security/optee_linuxdriver/armtz/Makefile index 5e6987ba62df..ba1b38b1816d 100644 --- a/security/optee_linuxdriver/armtz/Makefile +++ b/security/optee_linuxdriver/armtz/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 ######################################################################### # Set Internal Variables # diff --git a/security/optee_linuxdriver/core/Makefile b/security/optee_linuxdriver/core/Makefile index d216823554ae..a80221dc790e 100644 --- a/security/optee_linuxdriver/core/Makefile +++ b/security/optee_linuxdriver/core/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 CFG_TEE_CORE_CORE_TARGET := armv7 ######################################################################### diff --git a/security/tlk_driver/Kconfig b/security/tlk_driver/Kconfig index 6803cbff98e3..a9abc7791af0 100644 --- a/security/tlk_driver/Kconfig +++ b/security/tlk_driver/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 diff --git a/sound/soc/codecs/aic3262_codec_ops.c b/sound/soc/codecs/aic3262_codec_ops.c index c9483036b60b..d2f4dddbed3e 100644 --- a/sound/soc/codecs/aic3262_codec_ops.c +++ b/sound/soc/codecs/aic3262_codec_ops.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "aic3xxx_cfw.h" #include "aic3xxx_cfw_ops.h" #include diff --git a/sound/soc/codecs/aic3262_codec_ops.h b/sound/soc/codecs/aic3262_codec_ops.h index 54d835b33adc..37c20015a2f0 100644 --- a/sound/soc/codecs/aic3262_codec_ops.h +++ b/sound/soc/codecs/aic3262_codec_ops.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define SYNC_STATE(p) aic3262_reg_read(p->codec->control_data,AIC3262_DAC_PRB) #define AIC3262_COPS_MDSP_A 0x30 diff --git a/sound/soc/codecs/aic3xxx_cfw.h b/sound/soc/codecs/aic3xxx_cfw.h index 7d9a6fbdbd42..77fc2c83e927 100644 --- a/sound/soc/codecs/aic3xxx_cfw.h +++ b/sound/soc/codecs/aic3xxx_cfw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Codec Firmware Declarations */ diff --git a/sound/soc/codecs/aic3xxx_cfw_ops.h b/sound/soc/codecs/aic3xxx_cfw_ops.h index a9306f7438b4..e0deb3043ce0 100644 --- a/sound/soc/codecs/aic3xxx_cfw_ops.h +++ b/sound/soc/codecs/aic3xxx_cfw_ops.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef AIC3XXX_CFW_OPS_H_ #define AIC3XXX_CFW_OPS_H_ diff --git a/sound/soc/codecs/cxpump.h b/sound/soc/codecs/cxpump.h index 825b070a8800..10766aa9af70 100644 --- a/sound/soc/codecs/cxpump.h +++ b/sound/soc/codecs/cxpump.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /**************************************************************************************** ***************************************************************************************** *** *** diff --git a/sound/soc/codecs/pickle.h b/sound/soc/codecs/pickle.h index 488012a603d3..7d39812751ac 100644 --- a/sound/soc/codecs/pickle.h +++ b/sound/soc/codecs/pickle.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef PICKLE_H_ #define PICKLE_H_ diff --git a/sound/soc/codecs/rk3026_codec.c b/sound/soc/codecs/rk3026_codec.c old mode 100755 new mode 100644 index 5a673c21ab56..30d0a620d305 --- a/sound/soc/codecs/rk3026_codec.c +++ b/sound/soc/codecs/rk3026_codec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk3026.c -- RK3026 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk3026_codec.h b/sound/soc/codecs/rk3026_codec.h index af5a4031d46f..2704670ad107 100644 --- a/sound/soc/codecs/rk3026_codec.h +++ b/sound/soc/codecs/rk3026_codec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk3026.h -- RK3026 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk312x_codec.h b/sound/soc/codecs/rk312x_codec.h old mode 100755 new mode 100644 index a4fddd3f70e9..0924088681ba --- a/sound/soc/codecs/rk312x_codec.h +++ b/sound/soc/codecs/rk312x_codec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk3036.h -- RK312x CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk3190_codec.c b/sound/soc/codecs/rk3190_codec.c old mode 100755 new mode 100644 index 068726450655..14ee4e55d2bc --- a/sound/soc/codecs/rk3190_codec.c +++ b/sound/soc/codecs/rk3190_codec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk3190_codec.c -- RK3190 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk3190_codec.h b/sound/soc/codecs/rk3190_codec.h old mode 100755 new mode 100644 index a7847f56f76d..bdac4bf3e852 --- a/sound/soc/codecs/rk3190_codec.h +++ b/sound/soc/codecs/rk3190_codec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk3190_codec.h -- RK3190 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk616_codec.c b/sound/soc/codecs/rk616_codec.c old mode 100755 new mode 100644 index 75fe6e606bef..ab593eee361a --- a/sound/soc/codecs/rk616_codec.c +++ b/sound/soc/codecs/rk616_codec.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk616.c -- RK616 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rk616_codec.h b/sound/soc/codecs/rk616_codec.h old mode 100755 new mode 100644 index f2c151722b2d..dc2b4102618e --- a/sound/soc/codecs/rk616_codec.h +++ b/sound/soc/codecs/rk616_codec.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * rk616.h -- RK616 CODEC ALSA SoC audio driver * diff --git a/sound/soc/codecs/rt5512.c b/sound/soc/codecs/rt5512.c old mode 100755 new mode 100644 index 1a339c0a4b58..96b28b92392b --- a/sound/soc/codecs/rt5512.c +++ b/sound/soc/codecs/rt5512.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include #include #include diff --git a/sound/soc/codecs/rt5512.h b/sound/soc/codecs/rt5512.h old mode 100755 new mode 100644 index 93da472562f3..cb5ce5cad029 --- a/sound/soc/codecs/rt5512.h +++ b/sound/soc/codecs/rt5512.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __SND_SOC_CODEC_RT5512_H #define __SND_SOC_CODEC_RT5512_H diff --git a/sound/soc/codecs/tlv320aic3262_default_fw.h b/sound/soc/codecs/tlv320aic3262_default_fw.h index e51851b6c09b..8f09eb356cdf 100644 --- a/sound/soc/codecs/tlv320aic3262_default_fw.h +++ b/sound/soc/codecs/tlv320aic3262_default_fw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ unsigned char default_firmware[] = { 237,241,209,192,175, 0, 1, 0,219, 19, 0, 0, 28, 84, 36, 37, 0, 0, 0, 0,161, 85,149, 79, 70,105,114,109,119, 97,114,101, From ec33359b7f8a80e447f639fc2b4517651c6d885c Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Tue, 30 Jan 2018 15:48:58 +0800 Subject: [PATCH 165/427] arm64: dts: rockchip: enable vpu_combo for 3326/px30 board Change-Id: I1f4f8800945e9c329b5e5fe87acf032cf5fe163b Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 87f2ebdd1ac6..d8e9ea926e1c 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -395,3 +395,7 @@ &vopl_mmu { status = "okay"; }; + +&vpu_combo { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 96edcec81dbd..92d883c8df01 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -410,3 +410,7 @@ &vopl_mmu { status = "okay"; }; + +&vpu_combo { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 289d0f363cba..ffaba388aa11 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -312,3 +312,7 @@ &vopl_mmu { status = "okay"; }; + +&vpu_combo { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 1e7c22e0a72a..256a1f64a33f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -445,3 +445,7 @@ &vopl_mmu { status = "okay"; }; + +&vpu_combo { + status = "okay"; +}; From 1ee5e73c0e9fd26c938dfa5c5aefb19a605016e2 Mon Sep 17 00:00:00 2001 From: xxh Date: Mon, 29 Jan 2018 09:09:24 +0800 Subject: [PATCH 166/427] net: wireless: rockchip_wlan: fix bcmdhd driver for GTS Change-Id: I63173d9c83a2cd2e722dc279f18b226aff3595bf Signed-off-by: Xu Xuehui --- drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h | 1 + .../wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c | 10 ++++++---- .../net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h index a10a80fb8cbc..6b413b5727a7 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h @@ -806,6 +806,7 @@ typedef struct dhd_pub { #endif #ifdef RTT_SUPPORT void *rtt_state; + bool rtt_supported; #endif bool dongle_isolation; bool is_pcie_watchdog_reset; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c index b77ecac9ba6f..2f9078fba777 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c @@ -14148,8 +14148,10 @@ dhd_dev_get_feature_set(struct net_device *dev) feature_set |= WIFI_FEATURE_D2D_RTT; } #ifdef RTT_SUPPORT - feature_set |= WIFI_FEATURE_D2D_RTT; - feature_set |= WIFI_FEATURE_D2AP_RTT; + if (dhd->rtt_supported) { + feature_set |= WIFI_FEATURE_D2D_RTT; + feature_set |= WIFI_FEATURE_D2AP_RTT; + } #endif /* RTT_SUPPORT */ #ifdef LINKSTAT_SUPPORT feature_set |= WIFI_FEATURE_LINKSTAT; @@ -14159,8 +14161,8 @@ dhd_dev_get_feature_set(struct net_device *dev) if (dhd_is_pno_supported(dhd)) { feature_set |= WIFI_FEATURE_PNO; #ifdef GSCAN_SUPPORT - feature_set |= WIFI_FEATURE_GSCAN; - feature_set |= WIFI_FEATURE_HAL_EPNO; +// feature_set |= WIFI_FEATURE_GSCAN; +// feature_set |= WIFI_FEATURE_HAL_EPNO; #endif /* GSCAN_SUPPORT */ } #endif /* PNO_SUPPORT */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c index c58ca93fc435..cd35624974de 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c @@ -2305,6 +2305,7 @@ dhd_rtt_init(dhd_pub_t *dhd) int32 version; rtt_status_info_t *rtt_status; NULL_CHECK(dhd, "dhd is NULL", err); + dhd->rtt_supported = FALSE; if (dhd->rtt_state) { return err; } @@ -2331,6 +2332,7 @@ dhd_rtt_init(dhd_pub_t *dhd) ret = dhd_rtt_get_version(dhd, &version); if (ret == BCME_OK && (version == WL_PROXD_API_VERSION)) { DHD_ERROR(("%s : FTM is supported\n", __FUNCTION__)); + dhd->rtt_supported = TRUE; /* rtt_status->rtt_capa.proto |= RTT_CAP_ONE_WAY; */ rtt_status->rtt_capa.proto |= RTT_CAP_FTM_WAY; From 8ebe023800526e75f0d6037b707b2fd3eed83522 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 12 Dec 2017 10:30:31 -0800 Subject: [PATCH 167/427] UPSTREAM: usb: dwc2: host: Don't retry NAKed transactions right away On rk3288-veyron devices on Chrome OS it was found that plugging in an Arduino-based USB device could cause the system to lockup, especially if the CPU Frequency was at one of the slower operating points (like 100 MHz / 200 MHz). Upon tracing, I found that the following was happening: * The USB device (full speed) was connected to a high speed hub and then to the rk3288. Thus, we were dealing with split transactions, which is all handled in software on dwc2. * Userspace was initiating a BULK IN transfer * When we sent the SSPLIT (to start the split transaction), we got an ACK. Good. Then we issued the CSPLIT. * When we sent the CSPLIT, we got back a NAK. We immediately (from the interrupt handler) started to retry and sent another SSPLIT. * The device kept NAKing our CSPLIT, so we kept ping-ponging between sending a SSPLIT and a CSPLIT, each time sending from the interrupt handler. * The handling of the interrupts was (because of the low CPU speed and the inefficiency of the dwc2 interrupt handler) was actually taking _longer_ than it took the other side to send the ACK/NAK. Thus we were _always_ in the USB interrupt routine. * The fact that USB interrupts were always going off was preventing other things from happening in the system. This included preventing the system from being able to transition to a higher CPU frequency. As I understand it, there is no requirement to retry super quickly after a NAK, we just have to retry sometime in the future. Thus one solution to the above is to just add a delay between getting a NAK and retrying the transmission. If this delay is sufficiently long to get out of the interrupt routine then the rest of the system will be able to make forward progress. Even a 25 us delay would probably be enough, but we'll be extra conservative and try to delay 1 ms (the exact amount depends on HZ and the accuracy of the jiffy and how close the current jiffy is to ticking, but could be as much as 20 ms or as little as 1 ms). Presumably adding a delay like this could impact the USB throughput, so we only add the delay with repeated NAKs. NOTE: Upon further testing of a pl2303 serial adapter, I found that this fix may help with problems there. Specifically I found that the pl2303 serial adapters tend to respond with a NAK when they have nothing to say and thus we end with this same sequence. Change-Id: Ie9306eeef2694ceb59a07658905223f698b74e9a Signed-off-by: Douglas Anderson Reviewed-by: Julius Werner Tested-by: Stefan Wahren Acked-by: John Youn Signed-off-by: Felipe Balbi Signed-off-by: William Wu (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git next commit 38d2b5fb75c15923fb89c32134516a623515bce4) --- drivers/usb/dwc2/core.h | 1 + drivers/usb/dwc2/hcd.c | 7 +++ drivers/usb/dwc2/hcd.h | 9 ++++ drivers/usb/dwc2/hcd_intr.c | 20 +++++++++ drivers/usb/dwc2/hcd_queue.c | 82 ++++++++++++++++++++++++++++++++++-- 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 3b002e1d0a0a..e632abfd8729 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -912,6 +912,7 @@ struct dwc2_hsotg { } flags; struct list_head non_periodic_sched_inactive; + struct list_head non_periodic_sched_waiting; struct list_head non_periodic_sched_active; struct list_head *non_periodic_qh_ptr; struct list_head periodic_sched_inactive; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index f6a615861d3d..e575539e12f8 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -638,6 +638,10 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, list_for_each_entry(qh, &hsotg->non_periodic_sched_inactive, qh_list_entry) dev_dbg(hsotg->dev, " %p\n", qh); + dev_dbg(hsotg->dev, " NP waiting sched:\n"); + list_for_each_entry(qh, &hsotg->non_periodic_sched_waiting, + qh_list_entry) + dev_dbg(hsotg->dev, " %p\n", qh); dev_dbg(hsotg->dev, " NP active sched:\n"); list_for_each_entry(qh, &hsotg->non_periodic_sched_active, qh_list_entry) @@ -1768,6 +1772,7 @@ static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg, static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg) { dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_inactive); + dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_waiting); dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_active); dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_inactive); dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_ready); @@ -4929,6 +4934,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) /* Free memory for QH/QTD lists */ dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_inactive); + dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_waiting); dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_active); dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_inactive); dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_ready); @@ -5087,6 +5093,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) /* Initialize the non-periodic schedule */ INIT_LIST_HEAD(&hsotg->non_periodic_sched_inactive); + INIT_LIST_HEAD(&hsotg->non_periodic_sched_waiting); INIT_LIST_HEAD(&hsotg->non_periodic_sched_active); /* Initialize the periodic schedule */ diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 7758bfb644ff..b07f547e6355 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -313,12 +313,16 @@ struct dwc2_hs_transfer_time { * descriptor and indicates original XferSize value for the * descriptor * @unreserve_timer: Timer for releasing periodic reservation. + * @wait_timer: Timer used to wait before re-queuing. * @dwc2_tt: Pointer to our tt info (or NULL if no tt). * @ttport: Port number within our tt. * @tt_buffer_dirty True if clear_tt_buffer_complete is pending * @unreserve_pending: True if we planned to unreserve but haven't yet. * @schedule_low_speed: True if we have a low/full speed component (either the * host is in low/full speed mode or do_split). + * @want_wait: We should wait before re-queuing; only matters for non- + * periodic transfers and is ignored for periodic ones. + * @wait_timer_cancel: Set to true to cancel the wait_timer. * * A Queue Head (QH) holds the static characteristics of an endpoint and * maintains a list of transfers (QTDs) for that endpoint. A QH structure may @@ -353,11 +357,14 @@ struct dwc2_qh { u32 desc_list_sz; u32 *n_bytes; struct timer_list unreserve_timer; + struct timer_list wait_timer; struct dwc2_tt *dwc_tt; int ttport; unsigned tt_buffer_dirty:1; unsigned unreserve_pending:1; unsigned schedule_low_speed:1; + unsigned want_wait:1; + unsigned wait_timer_cancel:1; }; /** @@ -388,6 +395,7 @@ struct dwc2_qh { * @n_desc: Number of DMA descriptors for this QTD * @isoc_frame_index_last: Last activated frame (packet) index, used in * descriptor DMA mode only + * @num_naks: Number of NAKs received on this QTD. * @urb: URB for this transfer * @qh: Queue head for this QTD * @qtd_list_entry: For linking to the QH's list of QTDs @@ -418,6 +426,7 @@ struct dwc2_qtd { u8 error_count; u8 n_desc; u16 isoc_frame_index_last; + u16 num_naks; struct dwc2_hcd_urb *urb; struct dwc2_qh *qh; struct list_head qtd_list_entry; diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index cf706c2951f0..ccc8e63a758e 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -52,6 +52,12 @@ #include "core.h" #include "hcd.h" +/* + * If we get this many NAKs on a split transaction we'll slow down + * retransmission. A 1 here means delay after the first NAK. + */ +#define DWC2_NAKS_BEFORE_DELAY 3 + /* This function is for debug only */ static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) { @@ -1200,11 +1206,25 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, /* * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and * interrupt. Re-start the SSPLIT transfer. + * + * Normally for non-periodic transfers we'll retry right away, but to + * avoid interrupt storms we'll wait before retrying if we've got + * several NAKs. If we didn't do this we'd retry directly from the + * interrupt handler and could end up quickly getting another + * interrupt (another NAK), which we'd retry. + * + * Note that in DMA mode software only gets involved to re-send NAKed + * transfers for split transactions, so we only need to apply this + * delaying logic when handling splits. In non-DMA mode presumably we + * might want a similar delay if someone can demonstrate this problem + * affects that code path too. */ if (chan->do_split) { if (chan->complete_split) qtd->error_count = 0; qtd->complete_split = 0; + qtd->num_naks++; + qtd->qh->want_wait = qtd->num_naks >= DWC2_NAKS_BEFORE_DELAY; dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK); goto handle_nak_done; } diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 13754353251f..cf4d1739c5d9 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -57,6 +57,9 @@ /* Wait this long before releasing periodic reservation */ #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) +/* If we get a NAK, wait this long before retrying */ +#define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1)) + /** * dwc2_periodic_channel_available() - Checks that a channel is available for a * periodic transfer @@ -1439,6 +1442,55 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, list_del_init(&qh->qh_list_entry); } +/** + * dwc2_wait_timer_fn() - Timer function to re-queue after waiting + * + * As per the spec, a NAK indicates that "a function is temporarily unable to + * transmit or receive data, but will eventually be able to do so without need + * of host intervention". + * + * That means that when we encounter a NAK we're supposed to retry. + * + * ...but if we retry right away (from the interrupt handler that saw the NAK) + * then we can end up with an interrupt storm (if the other side keeps NAKing + * us) because on slow enough CPUs it could take us longer to get out of the + * interrupt routine than it takes for the device to send another NAK. That + * leads to a constant stream of NAK interrupts and the CPU locks. + * + * ...so instead of retrying right away in the case of a NAK we'll set a timer + * to retry some time later. This function handles that timer and moves the + * qh back to the "inactive" list, then queues transactions. + * + * @t: Pointer to wait_timer in a qh. + */ +static void dwc2_wait_timer_fn(unsigned long data) +{ + struct dwc2_qh *qh = (struct dwc2_qh *)data; + struct dwc2_hsotg *hsotg = qh->hsotg; + unsigned long flags; + + spin_lock_irqsave(&hsotg->lock, flags); + + /* + * We'll set wait_timer_cancel to true if we want to cancel this + * operation in dwc2_hcd_qh_unlink(). + */ + if (!qh->wait_timer_cancel) { + enum dwc2_transaction_type tr_type; + + qh->want_wait = false; + + list_move(&qh->qh_list_entry, + &hsotg->non_periodic_sched_inactive); + + tr_type = dwc2_hcd_select_transactions(hsotg); + if (tr_type != DWC2_TRANSACTION_NONE) + dwc2_hcd_queue_transactions(hsotg, tr_type); + } + + spin_unlock_irqrestore(&hsotg->lock, flags); +} + /** * dwc2_qh_init() - Initializes a QH structure * @@ -1468,6 +1520,8 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, qh->hsotg = hsotg; setup_timer(&qh->unreserve_timer, dwc2_unreserve_timer_fn, (unsigned long)qh); + setup_timer(&qh->wait_timer, dwc2_wait_timer_fn, + (unsigned long)qh); qh->ep_type = ep_type; qh->ep_is_in = ep_is_in; @@ -1629,6 +1683,16 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) dwc2_do_unreserve(hsotg, qh); spin_unlock_irqrestore(&hsotg->lock, flags); } + + /* + * We don't have the lock so we can safely wait until the wait timer + * finishes. Of course, at this point in time we'd better have set + * wait_timer_active to false so if this timer was still pending it + * won't do anything anyway, but we want it to finish before we free + * memory. + */ + del_timer_sync(&qh->wait_timer); + dwc2_host_put_tt_info(hsotg, qh->dwc_tt); if (qh->desc_list) @@ -1664,9 +1728,16 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) qh->start_active_frame = hsotg->frame_number; qh->next_active_frame = qh->start_active_frame; - /* Always start in inactive schedule */ - list_add_tail(&qh->qh_list_entry, - &hsotg->non_periodic_sched_inactive); + if (qh->want_wait) { + list_add_tail(&qh->qh_list_entry, + &hsotg->non_periodic_sched_waiting); + qh->wait_timer_cancel = false; + mod_timer(&qh->wait_timer, + jiffies + DWC2_RETRY_WAIT_DELAY + 1); + } else { + list_add_tail(&qh->qh_list_entry, + &hsotg->non_periodic_sched_inactive); + } return 0; } @@ -1696,6 +1767,9 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) dev_vdbg(hsotg->dev, "%s()\n", __func__); + /* If the wait_timer is pending, this will stop it from acting */ + qh->wait_timer_cancel = true; + if (list_empty(&qh->qh_list_entry)) /* QH is not in a schedule */ return; @@ -1904,7 +1978,7 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, if (dwc2_qh_is_non_per(qh)) { dwc2_hcd_qh_unlink(hsotg, qh); if (!list_empty(&qh->qtd_list)) - /* Add back to inactive non-periodic schedule */ + /* Add back to inactive/waiting non-periodic schedule */ dwc2_hcd_qh_add(hsotg, qh); return; } From 3a61ef4874e182a852df306e49646bd2020bc4c1 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Wed, 31 Jan 2018 18:16:12 +0800 Subject: [PATCH 168/427] drm: bridge: synopsys: update mc_clkdis in dw_hdmi_bind If vop return error when showing kernel logo, connector atomic flush will not be call, and mc_clkdis can not be updated. This patch update mc_clkdis in the dw_hdmi_bind, when phy clock is locked and HPD is connected. Change-Id: I1498d787a993961fe75236c309ecc3c898d611a4 Signed-off-by: Zheng Yang --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 1f705f0d81b4..6227a3c0fce4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2650,7 +2650,6 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) vmode->mtmdsclock /= 2; - hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); hdmi->phy.enabled = true; hdmi->bridge_is_on = true; if (in_bus_format != hdmi->hdmi_data.enc_in_bus_format || @@ -3599,6 +3598,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master, prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", hdmi->phy.name); + ret = hdmi_readb(hdmi, HDMI_PHY_STAT0); + if (ret & (HDMI_PHY_TX_PHY_LOCK | HDMI_PHY_HPD)) + hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); init_hpd_work(hdmi); initialize_hdmi_ih_mutes(hdmi); From 7e0c9d357c7232011b9eca9f363f816dc8c0b14e Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Thu, 1 Feb 2018 11:29:47 +0800 Subject: [PATCH 169/427] =?UTF-8?q?ARM:=20dts=EF=BC=9Ark3126-bnd-d70:=20en?= =?UTF-8?q?abled=20emmc=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id41ec3b9262091775a0494447e2ca8a34763ed8f Signed-off-by: Wu Liangqing --- arch/arm/boot/dts/rk3126-bnd-d708.dts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/rk3126-bnd-d708.dts b/arch/arm/boot/dts/rk3126-bnd-d708.dts index 8e1340d88248..65ee91e2ab5e 100644 --- a/arch/arm/boot/dts/rk3126-bnd-d708.dts +++ b/arch/arm/boot/dts/rk3126-bnd-d708.dts @@ -291,9 +291,7 @@ disable-wp; non-removable; num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; - status = "disabled"; + status = "okay"; }; &gpu { From 793ca73b39520614987172709c5ce74ea6370821 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Wed, 31 Jan 2018 17:10:56 +0800 Subject: [PATCH 170/427] media: cec: Fix crash if HPD is occurred before adapt allocated. Change-Id: I4d546cdbbecfd124c7cd6a985f0843879037b6dc Signed-off-by: Algea Cao --- drivers/media/cec/cec-adap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 2e66ee402801..8c75a51333b2 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -179,6 +179,8 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts) }; struct cec_fh *fh; + if (!adap) + return; /* hdmi HPD may occur before devnode is registered */ if (!adap->devnode.registered) return; From 623a187bd8d2cf4a231f2750ec20b2627830dede Mon Sep 17 00:00:00 2001 From: Weiguo Hu Date: Tue, 30 Jan 2018 18:03:54 +0800 Subject: [PATCH 171/427] net: phy: rockchip: optimize for long cable Change-Id: I125fb3a325946e82ccf021b02df194282b9d60f0 Signed-off-by: Weiguo Hu --- drivers/net/phy/rockchip.c | 264 ++++++++++++++++++++++++++++++++++--- 1 file changed, 246 insertions(+), 18 deletions(-) diff --git a/drivers/net/phy/rockchip.c b/drivers/net/phy/rockchip.c index 6b51741643ac..b63b3448aaa4 100644 --- a/drivers/net/phy/rockchip.c +++ b/drivers/net/phy/rockchip.c @@ -42,12 +42,38 @@ #define TSTMODE_ENABLE 0x400 #define TSTMODE_DISABLE 0x0 +#define DSP_REG_BANK_SEL 0 +#define WOL_REG_BANK_SEL BIT(11) +#define BIST_REG_BANK_SEL GENMASK(12, 11) + +#define WR_ADDR_A3CFG 0x14 #define WR_ADDR_A7CFG 0x18 -static int rockchip_init_tstmode(struct phy_device *phydev) +#define RD_ADDR_A3CFG (0x14 << 5) +#define RD_ADDR_LPISTA (12 << 5) + +#define A3CFG_100M 0xFC00 +#define A3CFG_TAG 0xFFFF + +#define PHY_ABNORMAL_THRESHOLD 15 + +struct rk_int_phy_priv { + int restore_reg0; + int restore_a3_config; + int force_10m_full_mode; + int a3_config_set; + int txrx_counters_done_count; + int last_speed; +}; + +static int rockchip_integrated_phy_init_tstmode(struct phy_device *phydev) { int ret; + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_DISABLE); + if (ret) + return ret; + /* Enable access to Analog and DSP register banks */ ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_ENABLE); if (ret) @@ -60,20 +86,15 @@ static int rockchip_init_tstmode(struct phy_device *phydev) return phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_ENABLE); } -static int rockchip_close_tstmode(struct phy_device *phydev) -{ - /* Back to basic register bank */ - return phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_DISABLE); -} - static int rockchip_integrated_phy_analog_init(struct phy_device *phydev) { int ret; - ret = rockchip_init_tstmode(phydev); + phydev_dbg(phydev, "%s: %d\n", __func__, __LINE__); + + ret = rockchip_integrated_phy_init_tstmode(phydev); if (ret) return ret; - /* * Adjust tx amplitude to make sginal better, * the default value is 0x8. @@ -85,13 +106,15 @@ static int rockchip_integrated_phy_analog_init(struct phy_device *phydev) if (ret) return ret; - return rockchip_close_tstmode(phydev); + return ret; } static int rockchip_integrated_phy_config_init(struct phy_device *phydev) { int val, ret; + phydev_dbg(phydev, "%s: %d\n", __func__, __LINE__); + /* * The auto MIDX has linked problem on some board, * workround to disable auto MDIX. @@ -107,9 +130,70 @@ static int rockchip_integrated_phy_config_init(struct phy_device *phydev) return rockchip_integrated_phy_analog_init(phydev); } -static void rockchip_link_change_notify(struct phy_device *phydev) +static int rockchip_integrated_phy_probe(struct phy_device *phydev) +{ + struct rk_int_phy_priv *priv; + + phydev_dbg(phydev, "%s: %d\n", __func__, __LINE__); + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + return 0; +} + +static void rockchip_integrated_phy_remove(struct phy_device *phydev) +{ + struct rk_int_phy_priv *priv = phydev->priv; + + phydev_dbg(phydev, "%s: %d\n", __func__, __LINE__); + + kfree(priv); +} + +static int rockchip_integrated_phy_adjust_a3_config(struct phy_device *phydev, + int value) +{ + int ret, val; + struct rk_int_phy_priv *priv = phydev->priv; + + phydev_dbg(phydev, "%s: %d: value = %x\n", __func__, __LINE__, value); + + if (value == A3CFG_TAG) { + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, + TSTCNTL_RD | RD_ADDR_A3CFG); + if (ret) + return ret; + val = phy_read(phydev, SMI_ADDR_TSTREAD1); + if (val < 0) + return val; + priv->restore_a3_config = val; + priv->a3_config_set = 1; + + ret = phy_write(phydev, SMI_ADDR_TSTWRITE, A3CFG_100M); + if (ret) + return ret; + } else { + ret = phy_write(phydev, SMI_ADDR_TSTWRITE, value); + if (ret) + return ret; + } + + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTCNTL_WR | WR_ADDR_A3CFG); + if (ret) + return ret; + + return 0; +} + +static +void rockchip_integrated_phy_link_change_notify(struct phy_device *phydev) { int speed = SPEED_10; + struct rk_int_phy_priv *priv = phydev->priv; if (phydev->autoneg == AUTONEG_ENABLE) { int reg = phy_read(phydev, MII_SPECIAL_CONTROL_STATUS); @@ -142,13 +226,18 @@ static void rockchip_link_change_notify(struct phy_device *phydev) * registers are set to default values. So any AFE/DSP * registers have to be re-initialized in this case. */ - if ((phydev->speed == SPEED_10) && (speed == SPEED_100)) { + if (phydev->link && + speed == SPEED_100 && + priv->last_speed == SPEED_10) { int ret = rockchip_integrated_phy_analog_init(phydev); if (ret) phydev_err(phydev, "rockchip_integrated_phy_analog_init err: %d.\n", ret); } + + if (phydev->link) + priv->last_speed = speed; } static int rockchip_set_polarity(struct phy_device *phydev, int polarity) @@ -185,7 +274,7 @@ static int rockchip_set_polarity(struct phy_device *phydev, int polarity) return 0; } -static int rockchip_config_aneg(struct phy_device *phydev) +static int rockchip_integrated_phy_config_aneg(struct phy_device *phydev) { int err; @@ -196,8 +285,145 @@ static int rockchip_config_aneg(struct phy_device *phydev) return genphy_config_aneg(phydev); } -static int rockchip_phy_resume(struct phy_device *phydev) +static int rockchip_integrated_phy_fixup_10M(struct phy_device *phydev) { + int val, ret; + struct rk_int_phy_priv *priv = phydev->priv; + + /* link partner does not have auto-negotiation ability + * setting PHY to 10M full-duplex by force + */ + if (phydev->state == PHY_RUNNING && !priv->force_10m_full_mode && + phydev->link && phydev->speed == SPEED_10) { + int an_expan; + + val = phy_read(phydev, MII_EXPANSION); + if (val < 0) + return val; + + an_expan = val; + if (!(an_expan & 0x1)) { + phydev_dbg(phydev, "%s: force_10m_full_mode\n", + __func__); + + val = phy_read(phydev, MII_BMCR); + if (val < 0) + return val; + priv->restore_reg0 = val; + + val = val & (~BMCR_ANENABLE); + val &= ~BMCR_SPEED100; + val |= BMCR_FULLDPLX; + ret = phy_write(phydev, MII_BMCR, val); + if (ret) + return ret; + priv->force_10m_full_mode = 1; + } + /* restore BMCR register */ + } else if (!phydev->link && priv->force_10m_full_mode) { + phydev_dbg(phydev, "%s: restore force_10m_full_mode\n", + __func__); + priv->force_10m_full_mode = 0; + ret = phy_write(phydev, MII_BMCR, priv->restore_reg0); + if (ret) + return ret; + } + + return 0; +} + +static int rockchip_integrated_phy_fixup_100M(struct phy_device *phydev) +{ + int ret, val; + struct rk_int_phy_priv *priv = phydev->priv; + + /* reset phy when continue detect phy abnormal */ + if (phydev->link && phydev->speed == SPEED_100) { + /* read wol bank reg12 and check bit 12 */ + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTCNTL_RD | + WOL_REG_BANK_SEL | RD_ADDR_LPISTA); + if (ret) + return ret; + + val = phy_read(phydev, SMI_ADDR_TSTREAD1); + if (val < 0) + return val; + + if (val & 0x1000) + priv->txrx_counters_done_count = 0; + if (!(val & 0x1000)) + priv->txrx_counters_done_count++; + + /* phydev_dbg(phydev, "txrx_counters_done_count = %d," + * threshol = %d\n", + * priv->txrx_counters_done_count, + * PHY_ABNORMAL_THRESHOLD); + */ + if (priv->txrx_counters_done_count >= + PHY_ABNORMAL_THRESHOLD) { + phydev_err(phydev, "%s: reset phy\n", __func__); + priv->txrx_counters_done_count = 0; + ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + } else { + priv->txrx_counters_done_count = 0; + } + + /* adjust A3_CONFIG for optimize long cable when 100M link up*/ + if (phydev->link && phydev->speed == SPEED_100 && + !priv->a3_config_set) { + ret = rockchip_integrated_phy_adjust_a3_config + (phydev, + A3CFG_TAG); + if (ret) { + phydev_err(phydev, "adjust_a3_config fail %x\n", + A3CFG_TAG); + return ret; + } + /* restore A3_CONFIG when 100M link down */ + } else if (!phydev->link && priv->a3_config_set) { + priv->a3_config_set = 0; + ret = rockchip_integrated_phy_adjust_a3_config + (phydev, + priv->restore_a3_config); + if (ret) { + phydev_err(phydev, "adjust_a3_config fail %x\n", + priv->restore_a3_config); + return ret; + } + } + + return 0; +} + +static int rockchip_integrated_phy_read_status(struct phy_device *phydev) +{ + int ret; + + ret = genphy_read_status(phydev); + if (ret) + return ret; + + ret = rockchip_integrated_phy_fixup_10M(phydev); + if (ret) + return ret; + + ret = rockchip_integrated_phy_fixup_100M(phydev); + if (ret) + return ret; + + return 0; +} + +static int rockchip_integrated_phy_resume(struct phy_device *phydev) +{ + struct rk_int_phy_priv *priv = phydev->priv; + + if (phydev->link && phydev->speed == SPEED_100) + priv->a3_config_set = 0; + genphy_resume(phydev); return rockchip_integrated_phy_config_init(phydev); @@ -210,13 +436,15 @@ static struct phy_driver rockchip_phy_driver[] = { .name = "Rockchip integrated EPHY", .features = PHY_BASIC_FEATURES, .flags = 0, - .link_change_notify = rockchip_link_change_notify, + .probe = rockchip_integrated_phy_probe, + .remove = rockchip_integrated_phy_remove, + .link_change_notify = rockchip_integrated_phy_link_change_notify, .soft_reset = genphy_soft_reset, .config_init = rockchip_integrated_phy_config_init, - .config_aneg = rockchip_config_aneg, - .read_status = genphy_read_status, + .config_aneg = rockchip_integrated_phy_config_aneg, + .read_status = rockchip_integrated_phy_read_status, .suspend = genphy_suspend, - .resume = rockchip_phy_resume, + .resume = rockchip_integrated_phy_resume, }, }; From 5f049afc2cbe4a39360355a4b20d8196b03a2e17 Mon Sep 17 00:00:00 2001 From: Jung Zhao Date: Wed, 31 Jan 2018 18:00:40 +0800 Subject: [PATCH 172/427] arm64: dts: rockchip: px30: add core reset Change-Id: I7a3bf6d6098fdd12f71d5b2a51e898dc8ed24e12 Signed-off-by: Jung Zhao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index f6237192998c..2c88d7d1102c 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -902,8 +902,10 @@ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>, <&cru SCLK_CORE_VPU>; clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core"; resets = <&cru SRST_VPU_A>, <&cru SRST_VPU_H>, - <&cru SRST_VPU_NIU_A>, <&cru SRST_VPU_NIU_H>; - reset-names = "video_a", "video_h", "niu_a", "niu_h"; + <&cru SRST_VPU_NIU_A>, <&cru SRST_VPU_NIU_H>, + <&cru SRST_VPU_CORE>; + reset-names = "video_a", "video_h", "niu_a", "niu_h", + "video_core"; mode_bit = <15>; mode_ctrl = <0x410>; name = "vpu_combo"; From b503ff5697ecd79ca55428d6c40e417143d80bd8 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 1 Feb 2018 20:12:35 +0800 Subject: [PATCH 173/427] clk: rockchip: rk3368: Add clock id for tsp Change-Id: I79a423f93f991aab43922e58ce34eac1754304e2 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3368.c | 4 ++-- include/dt-bindings/clock/rk3368-cru.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index bce94dc11703..42d426b4b713 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -428,10 +428,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(SCLK_I2S_2CH, "sclk_i2s_2ch", "i2s_2ch_pre", CLK_SET_RATE_PARENT, RK3368_CLKGATE_CON(5), 15, GFLAGS), - COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0, + COMPOSITE(SCLK_TSP, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0, RK3368_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3368_CLKGATE_CON(6), 12, GFLAGS), - GATE(0, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0, + GATE(SCLK_HSADC_TSP, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0, RK3368_CLKGATE_CON(13), 7, GFLAGS), MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0, diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h index 690800da96b0..5d3531686790 100644 --- a/include/dt-bindings/clock/rk3368-cru.h +++ b/include/dt-bindings/clock/rk3368-cru.h @@ -92,6 +92,8 @@ #define SCLK_TIMER14 137 #define SCLK_TIMER15 138 #define SCLK_DDRCLK 139 +#define SCLK_TSP 140 +#define SCLK_HSADC_TSP 141 #define DCLK_VOP 190 #define MCLK_CRYPTO 191 From f1ae3d9c5a5f7ac932094864516a502646940185 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 2 Feb 2018 14:28:58 +0800 Subject: [PATCH 174/427] clk: rockchip: px30: Fix wait boost recovery idle Change-Id: If407926c5fedd1e91b1223a3926f3bb98f4cb17c Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 781a92909a7c..2eb42294f8fa 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -428,7 +428,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, do { ret = readl_relaxed(pll->reg_base + PX30_BOOST_FSM_STATUS); - } while (ret & PX30_BOOST_BUSY_STATE); + } while (!(ret & PX30_BOOST_BUSY_STATE)); writel_relaxed(HIWORD_UPDATE(1, PX30_BOOST_SW_CTRL_MASK, PX30_BOOST_SW_CTRL_SHIFT) | HIWORD_UPDATE(1, PX30_BOOST_LOW_FREQ_EN_MASK, From fe53e623326da494cd536b73441ea22d8550f59f Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 2 Feb 2018 10:04:35 +0800 Subject: [PATCH 175/427] clk: rockchip: px30: Fix boost mask Change-Id: I507efe5bf432556a9e603275f03c81a5a8ef96ed Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 5dd8f16323d8..e958deef3dfb 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -65,11 +65,11 @@ struct clk; #define PX30_BOOST_SWITCH_THRESHOLD 0x8024 #define PX30_BOOST_FSM_STATUS 0x8028 #define PX30_BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x802c) -#define PX30_BOOST_RECOVERY_MASK 0x2 +#define PX30_BOOST_RECOVERY_MASK 0x1 #define PX30_BOOST_RECOVERY_SHIFT 1 -#define PX30_BOOST_SW_CTRL_MASK 0x4 +#define PX30_BOOST_SW_CTRL_MASK 0x1 #define PX30_BOOST_SW_CTRL_SHIFT 2 -#define PX30_BOOST_LOW_FREQ_EN_MASK 0x8 +#define PX30_BOOST_LOW_FREQ_EN_MASK 0x1 #define PX30_BOOST_LOW_FREQ_EN_SHIFT 3 #define PX30_BOOST_BUSY_STATE BIT(8) From 588ae5977e0c7023fd21a03cadaecddd385e0bc8 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 29 Jan 2018 18:05:49 +0800 Subject: [PATCH 176/427] clk: rockchip: Adjust the order of cpu boost Change-Id: I5fe78b451f9afaff276aeb251d68daf780c1eecf Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-cpu.c | 16 ++++++-- drivers/clk/rockchip/clk-pll.c | 75 +++++++++++++++++++++------------- drivers/clk/rockchip/clk.h | 4 ++ 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index cd2b1d87f4a4..4d9f38de342b 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -121,7 +121,8 @@ static void rockchip_cpuclk_set_dividers(struct rockchip_cpuclk *cpuclk, } static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, - struct clk_notifier_data *ndata) + struct clk_notifier_data *ndata, + struct clk_hw *pphw) { const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; const struct rockchip_cpuclk_rate_table *rate; @@ -136,6 +137,8 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, return -EINVAL; } + rockchip_boost_enable_recovery_sw_low(pphw); + alt_prate = clk_get_rate(cpuclk->alt_parent); spin_lock_irqsave(cpuclk->lock, flags); @@ -184,7 +187,8 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, } static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, - struct clk_notifier_data *ndata) + struct clk_notifier_data *ndata, + struct clk_hw *pphw) { const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; const struct rockchip_cpuclk_rate_table *rate; @@ -219,6 +223,8 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, if (ndata->old_rate > ndata->new_rate) rockchip_cpuclk_set_dividers(cpuclk, rate); + rockchip_boost_disable_recovery_sw(pphw); + spin_unlock_irqrestore(cpuclk->lock, flags); return 0; } @@ -234,14 +240,16 @@ static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb, { struct clk_notifier_data *ndata = data; struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_nb(nb); + struct clk_hw *phw = clk_hw_get_parent(__clk_get_hw(ndata->clk)); + struct clk_hw *pphw = clk_hw_get_parent(phw); int ret = 0; pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", __func__, event, ndata->old_rate, ndata->new_rate); if (event == PRE_RATE_CHANGE) - ret = rockchip_cpuclk_pre_rate_change(cpuclk, ndata); + ret = rockchip_cpuclk_pre_rate_change(cpuclk, ndata, pphw); else if (event == POST_RATE_CHANGE) - ret = rockchip_cpuclk_post_rate_change(cpuclk, ndata); + ret = rockchip_cpuclk_post_rate_change(cpuclk, ndata, pphw); return notifier_from_errno(ret); } diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 2eb42294f8fa..80d1d4095f2e 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -330,6 +330,51 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) return -ETIMEDOUT; } +void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + int ret; + + if (pll->type == pll_px30) { + writel_relaxed(HIWORD_UPDATE(1, PX30_BOOST_RECOVERY_MASK, + PX30_BOOST_RECOVERY_SHIFT), + pll->reg_base + PX30_BOOST_BOOST_CON); + do { + ret = readl_relaxed(pll->reg_base + + PX30_BOOST_FSM_STATUS); + } while (!(ret & PX30_BOOST_BUSY_STATE)); + + writel_relaxed(HIWORD_UPDATE(1, PX30_BOOST_SW_CTRL_MASK, + PX30_BOOST_SW_CTRL_SHIFT) | + HIWORD_UPDATE(1, PX30_BOOST_LOW_FREQ_EN_MASK, + PX30_BOOST_LOW_FREQ_EN_SHIFT), + pll->reg_base + PX30_BOOST_BOOST_CON); + } +} + +void rockchip_boost_disable_low(struct rockchip_clk_pll *pll) +{ + if (pll->type == pll_px30) { + writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_LOW_FREQ_EN_MASK, + PX30_BOOST_LOW_FREQ_EN_SHIFT), + pll->reg_base + PX30_BOOST_BOOST_CON); + } +} + +void rockchip_boost_disable_recovery_sw(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + if (pll->type == pll_px30) { + writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_RECOVERY_MASK, + PX30_BOOST_RECOVERY_SHIFT), + pll->reg_base + PX30_BOOST_BOOST_CON); + writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_SW_CTRL_MASK, + PX30_BOOST_SW_CTRL_SHIFT), + pll->reg_base + PX30_BOOST_BOOST_CON); + } +} + /** * PLL used in RK3036 */ @@ -421,21 +466,6 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, rockchip_rk3036_pll_get_params(pll, &cur); cur.rate = 0; - if (pll->type == pll_px30) { - writel_relaxed(HIWORD_UPDATE(1, PX30_BOOST_RECOVERY_MASK, - PX30_BOOST_RECOVERY_SHIFT), - pll->reg_base + PX30_BOOST_BOOST_CON); - do { - ret = readl_relaxed(pll->reg_base + - PX30_BOOST_FSM_STATUS); - } while (!(ret & PX30_BOOST_BUSY_STATE)); - writel_relaxed(HIWORD_UPDATE(1, PX30_BOOST_SW_CTRL_MASK, - PX30_BOOST_SW_CTRL_SHIFT) | - HIWORD_UPDATE(1, PX30_BOOST_LOW_FREQ_EN_MASK, - PX30_BOOST_LOW_FREQ_EN_SHIFT), - pll->reg_base + PX30_BOOST_BOOST_CON); - } - cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); if (cur_parent == PLL_MODE_NORM) { pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); @@ -468,11 +498,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT; writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); - if (pll->type == pll_px30) { - writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_LOW_FREQ_EN_MASK, - PX30_BOOST_LOW_FREQ_EN_SHIFT), - pll->reg_base + PX30_BOOST_BOOST_CON); - } + rockchip_boost_disable_low(pll); /* set pll power up */ writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 13), @@ -489,15 +515,6 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, if (rate_change_remuxed) pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); - if (pll->type == pll_px30) { - writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_RECOVERY_MASK, - PX30_BOOST_RECOVERY_SHIFT), - pll->reg_base + PX30_BOOST_BOOST_CON); - writel_relaxed(HIWORD_UPDATE(0, PX30_BOOST_SW_CTRL_MASK, - PX30_BOOST_SW_CTRL_SHIFT), - pll->reg_base + PX30_BOOST_BOOST_CON); - } - return ret; } diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index e958deef3dfb..4a90b3371f0c 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -303,6 +303,10 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, struct rockchip_pll_rate_table *rate_table, unsigned long flags, u8 clk_pll_flags); +void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw); + +void rockchip_boost_disable_recovery_sw(struct clk_hw *hw); + struct rockchip_cpuclk_clksel { int reg; u32 val; From 3bc1d7d06f549064af621a594312ad03867e261b Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Fri, 2 Feb 2018 09:52:58 +0800 Subject: [PATCH 177/427] arm64: dts: rockchip: Auto match emmc and nand devices for px30/rk3326 Change-Id: I787e0cefdf8bc7d0f5ae1483233017edafa7ee31 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30-android.dtsi | 4 ++-- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 6 ++++-- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 6 ++++-- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 6 ++++-- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 6 ++++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index f6d93afff376..0d80981372c1 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -27,14 +27,14 @@ compatible = "android,fstab"; system { compatible = "android,system"; - dev = "/dev/block/platform/ff390000.dwmmc/by-name/system"; + dev = "/dev/block/by-name/system"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; fsmgr_flags = "wait,verify"; }; vendor { compatible = "android,vendor"; - dev = "/dev/block/platform/ff390000.dwmmc/by-name/vendor"; + dev = "/dev/block/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; fsmgr_flags = "wait,verify"; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index d8e9ea926e1c..505b66d6de85 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -247,8 +247,6 @@ disable-wp; non-removable; num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; status = "okay"; }; @@ -304,6 +302,10 @@ status = "okay"; }; +&nandc0 { + status = "okay"; +}; + &pinctrl { sdio-pwrseq { wifi_enable_h: wifi-enable-h { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 92d883c8df01..bd7bb55ab3d6 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -273,8 +273,6 @@ disable-wp; non-removable; num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; status = "okay"; }; @@ -319,6 +317,10 @@ status = "okay"; }; +&nandc0 { + status = "okay"; +}; + &pinctrl { sdio-pwrseq { wifi_enable_h: wifi-enable-h { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index ffaba388aa11..622a488ac2b4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -192,8 +192,6 @@ disable-wp; non-removable; num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; status = "okay"; }; @@ -229,6 +227,10 @@ status = "okay"; }; +&nandc0 { + status = "okay"; +}; + &pwm1 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 256a1f64a33f..a67a415a93a6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -289,8 +289,6 @@ disable-wp; non-removable; num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; status = "okay"; }; @@ -358,6 +356,10 @@ status = "okay"; }; +&nandc0 { + status = "okay"; +}; + &pwm1 { status = "okay"; }; From 9d155c640fcd64509a9ac8104bf7b0922dfc768b Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 2 Feb 2018 15:01:51 +0800 Subject: [PATCH 178/427] power: avs: rockchip-io-domain: Change the name from vccio0 to vccio6 for px30 Checked with ic colleague, the name should be same as the datasheet, so need to change the name, they also change it at trm. Change-Id: Ie98ba5397cf0e5a2dba4e07fc0ca31a3330f05a6 Signed-off-by: David Wu --- drivers/power/avs/rockchip-io-domain.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c index e3eb9b9b1a74..97d07911cc2a 100644 --- a/drivers/power/avs/rockchip-io-domain.c +++ b/drivers/power/avs/rockchip-io-domain.c @@ -40,8 +40,8 @@ #define MAX_VOLTAGE_3_3 3600000 #define PX30_IO_VSEL 0x180 -#define PX30_IO_VSEL_VCCIO0_SRC BIT(0) -#define PX30_IO_VSEL_VCCIO0_SUPPLY_NUM 1 +#define PX30_IO_VSEL_VCCIO6_SRC BIT(0) +#define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1 #define RK3288_SOC_CON2 0x24c #define RK3288_SOC_CON2_FLASH0 BIT(7) @@ -165,14 +165,14 @@ static void px30_iodomain_init(struct rockchip_iodomain *iod) u32 val; /* if no VCCIO0 supply we should leave things alone */ - if (!iod->supplies[PX30_IO_VSEL_VCCIO0_SUPPLY_NUM].reg) + if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg) return; /* * set vccio0 iodomain to also use this framework * instead of a special gpio. */ - val = PX30_IO_VSEL_VCCIO0_SRC | (PX30_IO_VSEL_VCCIO0_SRC << 16); + val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16); ret = regmap_write(iod->grf, PX30_IO_VSEL, val); if (ret < 0) dev_warn(iod->dev, "couldn't update vccio0 ctrl\n"); @@ -277,7 +277,7 @@ static const struct rockchip_iodomain_soc_data soc_data_px30 = { .grf_offset = 0x180, .supply_names = { NULL, - "vccio0", + "vccio6", "vccio1", "vccio2", "vccio3", From 21c38316b33b3dad91dba329c78433ff80a89641 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Thu, 25 Jan 2018 11:01:50 +0800 Subject: [PATCH 179/427] drm/rockchip: Support tve uboot logo Add tve connector port. If uboot logo is enabled, dac will not be disabled when tve bind. Change-Id: I5d87f9d1afc05481968dc34b0bd09dd82719a933 Signed-off-by: Algea Cao --- drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 31 ++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index 4f91c7e9cc4c..23f2ad73b7bc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -366,6 +366,31 @@ static int tve_parse_dt(struct device_node *np, return 0; } +static void check_uboot_logo(struct rockchip_tve *tve) +{ + int lumafilter0, lumafilter1, lumafilter2, vdac; + + vdac = tve_dac_readl(VDAC_VDAC1); + /* Whether the dac power has been turned down. */ + if (vdac & m_DR_PWR_DOWN) + return; + + lumafilter0 = tve_readl(TV_LUMA_FILTER0); + lumafilter1 = tve_readl(TV_LUMA_FILTER1); + lumafilter2 = tve_readl(TV_LUMA_FILTER2); + + /* + * The default lumafilter value is 0. If lumafilter value + * is equal to the dts value, uboot logo is enabled. + */ + if (lumafilter0 == tve->lumafilter0 && + lumafilter1 == tve->lumafilter1 && + lumafilter2 == tve->lumafilter2) + return; + + dac_init(tve); +} + static const struct of_device_id rockchip_tve_dt_ids[] = { { .compatible = "rockchip,rk3328-tve", @@ -434,10 +459,8 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, return PTR_ERR(tve->vdacbase); } - dac_init(tve); - mutex_init(&tve->suspend_lock); - + check_uboot_logo(tve); tve->tv_format = TVOUT_CVBS_PAL; encoder = &tve->encoder; encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, @@ -455,7 +478,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, connector = &tve->connector; connector->dpms = DRM_MODE_DPMS_OFF; - + connector->port = dev->of_node; connector->interlace_allowed = 1; ret = drm_connector_init(drm_dev, connector, &rockchip_tve_connector_funcs, From 3726b810fe652dbe17bc09500452c94dcb36fbef Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Fri, 2 Feb 2018 15:14:19 +0800 Subject: [PATCH 180/427] drivers: input: sensors: reset sensor rate Change-Id: I3fc1fbe5c054867fe6ce93f64bc2dc14f6abeb9c Signed-off-by: Zorro Liu --- drivers/input/sensors/sensor-dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c index c3861274baf7..f880460620ff 100644 --- a/drivers/input/sensors/sensor-dev.c +++ b/drivers/input/sensors/sensor-dev.c @@ -491,10 +491,10 @@ static int sensor_reset_rate(struct i2c_client *client, int rate) dev_info(&client->dev, "set sensor poll time to %dms\n", rate); /* work queue is always slow, we need more quickly to match hal rate */ - if (sensor->pdata->poll_delay_ms == (rate - 2)) + if (sensor->pdata->poll_delay_ms == (rate - 5)) return 0; - sensor->pdata->poll_delay_ms = rate - 2; + sensor->pdata->poll_delay_ms = rate - 5; if (sensor->status_cur == SENSOR_ON) { if (!sensor->pdata->irq_enable) { From ea568669199f66ad6bba5f6dc6d4b010bb740040 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Fri, 2 Feb 2018 12:21:36 +0800 Subject: [PATCH 181/427] drm: bridge: synopsys: update more hdmi status in dw_hdmi_bind If hdmi is enabled in uboot, hdmi->disabled and bridge_is_on and phy status need to be updated. Change-Id: Ib21d894b673bf12b46a271c91d3e08fe7475ea89 Signed-off-by: Zheng Yang --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 6227a3c0fce4..36efc391626b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2650,8 +2650,6 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector, if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) vmode->mtmdsclock /= 2; - hdmi->phy.enabled = true; - hdmi->bridge_is_on = true; if (in_bus_format != hdmi->hdmi_data.enc_in_bus_format || out_bus_format != hdmi->hdmi_data.enc_out_bus_format) hdmi->hdmi_data.update = true; @@ -3599,8 +3597,12 @@ int dw_hdmi_bind(struct device *dev, struct device *master, hdmi->phy.name); ret = hdmi_readb(hdmi, HDMI_PHY_STAT0); - if (ret & (HDMI_PHY_TX_PHY_LOCK | HDMI_PHY_HPD)) + if (ret & (HDMI_PHY_TX_PHY_LOCK | HDMI_PHY_HPD)) { hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); + hdmi->disabled = false; + hdmi->bridge_is_on = true; + hdmi->phy.enabled = true; + } init_hpd_work(hdmi); initialize_hdmi_ih_mutes(hdmi); From 6cd300f79505b02e610767053bb208ce102685eb Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 2 Feb 2018 16:17:03 +0800 Subject: [PATCH 182/427] clk: rockchip: rk3128: Fix aclk_peri_src parent Change-Id: Id679e7235f78635233dc4d6bd59c75ce05dfc99e Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3128.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c index 73c13560c405..c5f58e8d15e9 100644 --- a/drivers/clk/rockchip/clk-rk3128.c +++ b/drivers/clk/rockchip/clk-rk3128.c @@ -146,7 +146,7 @@ PNAME(mux_pll_src_5plls_p) = { "cpll", "gpll", "gpll_div2", "gpll_div3", "usb480 PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "gpll_div2", "usb480m" }; PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "gpll_div2" }; -PNAME(mux_aclk_peri_src_p) = { "gpll_peri", "cpll_peri", "gpll_div2_peri", "gpll_div3_peri" }; +PNAME(mux_aclk_peri_src_p) = { "gpll", "cpll", "gpll_div2", "gpll_div3" }; PNAME(mux_mmc_src_p) = { "cpll", "gpll", "gpll_div2", "xin24m" }; PNAME(mux_clk_cif_out_src_p) = { "sclk_cif_src", "xin24m" }; PNAME(mux_sclk_vop_src_p) = { "cpll", "gpll", "gpll_div2", "gpll_div3" }; @@ -282,16 +282,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKGATE_CON(0), 11, GFLAGS), /* PD_PERI */ - GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED, + COMPOSITE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0, + RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(2), 0, GFLAGS), - GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED, - RK2928_CLKGATE_CON(2), 0, GFLAGS), - GATE(0, "gpll_div2_peri", "gpll_div2", CLK_IGNORE_UNUSED, - RK2928_CLKGATE_CON(2), 0, GFLAGS), - GATE(0, "gpll_div3_peri", "gpll_div3", CLK_IGNORE_UNUSED, - RK2928_CLKGATE_CON(2), 0, GFLAGS), - COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0, - RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(2), 3, GFLAGS), From 707eebb0c9d7385593959e61d126788798697c80 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 27 Dec 2017 18:57:36 +0800 Subject: [PATCH 183/427] regulator: debugfs: Adding debugfs functions into regulator framework This change allows the user to read and edit regulator information in user space through the debugfs file system. Base on msm work. Change-Id: I4b40d4fd662e3d3d0856127e8e030fa60e938df9 Signed-off-by: Tao Huang Signed-off-by: Finley Xiao --- drivers/regulator/core.c | 299 ++++++++++++++++++++++++++++++- include/linux/regulator/driver.h | 1 + 2 files changed, 299 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b01fe96b14fe..e0a244ab0ef6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -3860,11 +3862,243 @@ static struct class regulator_class = { .dev_groups = regulator_dev_groups, }; +#ifdef CONFIG_DEBUG_FS + +static int reg_debug_enable_set(void *data, u64 val) +{ + struct regulator *regulator = data; + int ret; + + if (val) { + ret = regulator_enable(regulator); + if (ret) + rdev_err(regulator->rdev, "enable failed, ret=%d\n", + ret); + } else { + ret = regulator_disable(regulator); + if (ret) + rdev_err(regulator->rdev, "disable failed, ret=%d\n", + ret); + } + + return ret; +} + +static int reg_debug_enable_get(void *data, u64 *val) +{ + struct regulator *regulator = data; + + *val = regulator_is_enabled(regulator); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(reg_enable_fops, reg_debug_enable_get, + reg_debug_enable_set, "%llu\n"); + +static int reg_debug_force_disable_set(void *data, u64 val) +{ + struct regulator *regulator = data; + int ret = 0; + + if (val > 0) { + ret = regulator_force_disable(regulator); + if (ret) + rdev_err(regulator->rdev, "force_disable failed, ret=%d\n", + ret); + } + + return ret; +} +DEFINE_SIMPLE_ATTRIBUTE(reg_force_disable_fops, reg_debug_enable_get, + reg_debug_force_disable_set, "%llu\n"); + +#define MAX_DEBUG_BUF_LEN 50 + +static ssize_t reg_debug_voltage_write(struct file *file, + const char __user *ubuf, + size_t count, + loff_t *ppos) +{ + struct regulator *regulator = file->private_data; + struct regulator_dev *rdev = regulator->rdev; + struct regulator *reg; + + char buf[MAX_DEBUG_BUF_LEN]; + int ret; + int min_uV, max_uV = -1; + + if (count < MAX_DEBUG_BUF_LEN) { + if (copy_from_user(buf, ubuf, count)) + return -EFAULT; + + buf[count] = '\0'; + ret = kstrtoint(buf, 10, &min_uV); + + /* Check that target voltage were specified. */ + if (ret || min_uV < 0) { + rdev_err(regulator->rdev, "incorrect values specified: \"%s\"; should be: \"target_uV\"\n", + buf); + return -EINVAL; + } + + max_uV = rdev->constraints->max_uV; + + list_for_each_entry(reg, &rdev->consumer_list, list) { + if ((!reg->min_uV && !reg->max_uV) || + (reg == regulator)) + continue; + reg->min_uV = min_uV; + reg->max_uV = max_uV; + } + + ret = regulator_set_voltage(regulator, min_uV, max_uV); + if (ret) { + rdev_err(regulator->rdev, "set voltage(%d, %d) failed, ret=%d\n", + min_uV, max_uV, ret); + return ret; + } + } else { + rdev_err(regulator->rdev, "voltage request string exceeds maximum buffer size\n"); + return -EINVAL; + } + + return count; +} + +static ssize_t reg_debug_voltage_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct regulator *regulator = file->private_data; + char buf[MAX_DEBUG_BUF_LEN]; + int voltage, ret; + + voltage = regulator_get_voltage(regulator); + + ret = snprintf(buf, MAX_DEBUG_BUF_LEN - 1, "%d\n", voltage); + + return simple_read_from_buffer(ubuf, count, ppos, buf, ret); +} + +static int reg_debug_voltage_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + + return 0; +} + +static const struct file_operations reg_voltage_fops = { + .write = reg_debug_voltage_write, + .open = reg_debug_voltage_open, + .read = reg_debug_voltage_read, +}; + +static int reg_debug_mode_set(void *data, u64 val) +{ + struct regulator *regulator = data; + unsigned int mode = val; + int ret; + + ret = regulator_set_mode(regulator, mode); + if (ret) + rdev_err(regulator->rdev, "set mode=%u failed, ret=%d\n", + mode, ret); + + return ret; +} + +static int reg_debug_mode_get(void *data, u64 *val) +{ + struct regulator *regulator = data; + int mode; + + mode = regulator_get_mode(regulator); + if (mode < 0) { + rdev_err(regulator->rdev, "get mode failed, ret=%d\n", mode); + return mode; + } + + *val = mode; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(reg_mode_fops, reg_debug_mode_get, reg_debug_mode_set, + "%llu\n"); + +static int reg_debug_set_load(void *data, u64 val) +{ + struct regulator *regulator = data; + int load = val; + int ret; + + ret = regulator_set_load(regulator, load); + if (ret) + rdev_err(regulator->rdev, "set load=%d failed, ret=%d\n", + load, ret); + + return ret; +} +DEFINE_SIMPLE_ATTRIBUTE(reg_set_load_fops, reg_debug_mode_get, + reg_debug_set_load, "%llu\n"); + +static int reg_debug_consumers_show(struct seq_file *m, void *v) +{ + struct regulator_dev *rdev = m->private; + struct regulator *reg; + char *supply_name; + + mutex_lock(&rdev->mutex); + + /* Print a header if there are consumers. */ + if (rdev->open_count) + seq_printf(m, "%-32s Min_uV Max_uV load_uA\n", + "Device-Supply"); + + list_for_each_entry(reg, &rdev->consumer_list, list) { + if (reg->supply_name) + supply_name = reg->supply_name; + else + supply_name = "(null)-(null)"; + + seq_printf(m, "%-32s %8d %8d %8d\n", supply_name, + reg->min_uV, reg->max_uV, reg->uA_load); + } + + mutex_unlock(&rdev->mutex); + + return 0; +} + +static int reg_debug_consumers_open(struct inode *inode, struct file *file) +{ + return single_open(file, reg_debug_consumers_show, inode->i_private); +} + +static const struct file_operations reg_consumers_fops = { + .owner = THIS_MODULE, + .open = reg_debug_consumers_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void rdev_deinit_debugfs(struct regulator_dev *rdev) +{ + if (!IS_ERR_OR_NULL(rdev)) { + debugfs_remove_recursive(rdev->debugfs); + if (rdev->debug_consumer) + rdev->debug_consumer->debugfs = NULL; + regulator_put(rdev->debug_consumer); + } +} + static void rdev_init_debugfs(struct regulator_dev *rdev) { struct device *parent = rdev->dev.parent; const char *rname = rdev_get_name(rdev); char name[NAME_MAX]; + struct regulator *regulator; + const struct regulator_ops *ops; + mode_t mode; /* Avoid duplicate debugfs directory names */ if (parent && rname == rdev->desc->name) { @@ -3885,8 +4119,71 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->open_count); debugfs_create_u32("bypass_count", 0444, rdev->debugfs, &rdev->bypass_count); + debugfs_create_file("consumers", 0444, rdev->debugfs, rdev, + ®_consumers_fops); + + regulator = regulator_get(NULL, rdev_get_name(rdev)); + if (IS_ERR(regulator)) { + rdev_err(rdev, "regulator get failed, ret=%ld\n", + PTR_ERR(regulator)); + return; + } + rdev->debug_consumer = regulator; + + ops = rdev->desc->ops; + + debugfs_create_file("enable", 0644, rdev->debugfs, regulator, + ®_enable_fops); + + mode = 0; + if (ops->is_enabled) + mode |= 0444; + if (ops->disable) + mode |= 0200; + if (mode) + debugfs_create_file("force_disable", mode, rdev->debugfs, + regulator, ®_force_disable_fops); + + mode = 0; + if (ops->get_voltage || ops->get_voltage_sel) + mode |= 0444; + if (ops->set_voltage || ops->set_voltage_sel) + mode |= 0200; + if (mode) + debugfs_create_file("voltage", mode, rdev->debugfs, regulator, + ®_voltage_fops); + + mode = 0; + if (ops->get_mode) + mode |= 0444; + if (ops->set_mode) + mode |= 0200; + if (mode) + debugfs_create_file("mode", mode, rdev->debugfs, regulator, + ®_mode_fops); + + mode = 0; + if (ops->get_mode) + mode |= 0444; + if (ops->set_load || (ops->get_optimum_mode && ops->set_mode)) + mode |= 0200; + if (mode) + debugfs_create_file("load", mode, rdev->debugfs, regulator, + ®_set_load_fops); } +#else + +static inline void rdev_deinit_debugfs(struct regulator_dev *rdev) +{ +} + +static inline void rdev_init_debugfs(struct regulator_dev *rdev) +{ +} + +#endif + static int regulator_register_resolve_supply(struct device *dev, void *data) { struct regulator_dev *rdev = dev_to_rdev(dev); @@ -4093,8 +4390,8 @@ void regulator_unregister(struct regulator_dev *rdev) regulator_disable(rdev->supply); regulator_put(rdev->supply); } + rdev_deinit_debugfs(rdev); mutex_lock(®ulator_list_mutex); - debugfs_remove_recursive(rdev->debugfs); flush_work(&rdev->disable_work.work); WARN_ON(rdev->open_count); unset_regulator_supplies(rdev); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 5a5afee02dd5..02e98d28de6f 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -414,6 +414,7 @@ struct regulator_dev { /* time when this regulator was disabled last time */ unsigned long last_off_jiffy; + struct regulator *debug_consumer; }; struct regulator_dev * From e7f55d159aaaa928296392568552bea59bdbef2c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 13 Dec 2017 15:19:04 +0800 Subject: [PATCH 184/427] printk: add support show process information on printks Change-Id: I34cf76388ceb2e1f6b6417638c82bf774641ebac Signed-off-by: Tao Huang --- kernel/printk/printk.c | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig.debug | 7 +++++++ 2 files changed, 53 insertions(+) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index f30a876531f0..422180516664 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -236,6 +236,12 @@ struct printk_log { u8 facility; /* syslog facility */ u8 flags:5; /* internal record flags */ u8 level:3; /* syslog level */ +#ifdef CONFIG_PRINTK_PROCESS + char process[16]; /* process name */ + pid_t pid; /* process id */ + u8 cpu; /* cpu id */ + u8 in_interrupt; /* interrupt context */ +#endif }; /* @@ -270,7 +276,11 @@ static enum log_flags console_prev; static u64 clear_seq; static u32 clear_idx; +#ifdef CONFIG_PRINTK_PROCESS +#define PREFIX_MAX 48 +#else #define PREFIX_MAX 32 +#endif #define LOG_LINE_MAX (1024 - PREFIX_MAX) #define LOG_LEVEL(v) ((v) & 0x07) @@ -343,6 +353,25 @@ static u32 log_next(u32 idx) return idx + msg->len; } +#ifdef CONFIG_PRINTK_PROCESS +static bool printk_process = true; +static size_t print_process(const struct printk_log *msg, char *buf) +{ + if (!printk_process) + return 0; + + if (!buf) + return snprintf(NULL, 0, "%c[%1d:%15s:%5d] ", ' ', 0, " ", 0); + + return sprintf(buf, "%c[%1d:%15s:%5d] ", + msg->in_interrupt ? 'I' : ' ', + msg->cpu, + msg->process, + msg->pid); +} +module_param_named(process, printk_process, bool, 0644); +#endif + /* * Check whether there is enough free space for the given message. * @@ -475,6 +504,16 @@ static int log_store(int facility, int level, memset(log_dict(msg) + dict_len, 0, pad_len); msg->len = size; +#ifdef CONFIG_PRINTK_PROCESS + if (printk_process) { + strncpy(msg->process, current->comm, sizeof(msg->process) - 1); + msg->process[sizeof(msg->process) - 1] = '\0'; + msg->pid = task_pid_nr(current); + msg->cpu = raw_smp_processor_id(); + msg->in_interrupt = in_interrupt() ? 1 : 0; + } +#endif + /* insert message */ log_next_idx += msg->len; log_next_seq++; @@ -1077,6 +1116,9 @@ static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf) } len += print_time(msg->ts_nsec, buf ? buf + len : NULL); +#ifdef CONFIG_PRINTK_PROCESS + len += print_process(msg, buf ? buf + len : NULL); +#endif return len; } @@ -1646,6 +1688,10 @@ static size_t cont_print_text(char *text, size_t size) if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) { textlen += print_time(cont.ts_nsec, text); +#ifdef CONFIG_PRINTK_PROCESS + *(text + textlen) = ' '; + textlen += print_process(NULL, NULL); +#endif size -= textlen; } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 6899c7cd7898..7a51dfe5daa3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -15,6 +15,13 @@ config PRINTK_TIME The behavior is also controlled by the kernel command line parameter printk.time=1. See Documentation/kernel-parameters.txt +config PRINTK_PROCESS + bool "Show process information on printks" + depends on PRINTK + help + Selecting this option causes process to be + included in printk output. Or add printk.process=1 at boot-time. + config MESSAGE_LOGLEVEL_DEFAULT int "Default message log level (1-7)" range 1 7 From a198c95b94845eec7bc61cacd1c4bd56717447e9 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Feb 2018 10:04:15 +0800 Subject: [PATCH 185/427] clk: rockchip: rk3228: Fix armclk parent Change-Id: I09830d96b37cca600f1782b9013b25e043467f97 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3228.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index a4d92cd95e64..fb3f34fb449f 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -139,7 +139,7 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" }; -PNAME(mux_armclk_p) = { "apll", "gpll", "dpll" }; +PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; @@ -233,6 +233,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKGATE_CON(7), 0, GFLAGS), /* PD_CORE */ + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, + PX30_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, + PX30_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, + PX30_CLKGATE_CON(0), 6, GFLAGS), COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, RK2928_CLKGATE_CON(4), 1, GFLAGS), From cb3339cafb5973c5dbb7b82c9c899ed8c9194a32 Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 15:48:33 +0800 Subject: [PATCH 186/427] ARM: dts: rk322x: add rockchip,rk3228-grf compatible to grf Change-Id: I8bf76e140150f90bd2656053ab27ddfec6361da3 Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 74061be1307b..3f27991853b9 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -231,7 +231,7 @@ }; grf: syscon@11000000 { - compatible = "syscon", "simple-mfd"; + compatible = "rockchip,rk3228-grf", "syscon", "simple-mfd"; reg = <0x11000000 0x1000>; #address-cells = <1>; #size-cells = <1>; From 151d396a6f64de35d499df9b922dedeb6ec133df Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 15:56:47 +0800 Subject: [PATCH 187/427] ARM: dts: rk322x: Fix typo for pwm3 #pwm-cells Change-Id: Iefdd1b9838b7a6f633476634c7bef53fdcfba923 Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 3f27991853b9..a3111ef348f0 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -494,7 +494,7 @@ pwm3: pwm@110b0030 { compatible = "rockchip,rk3288-pwm"; reg = <0x110b0030 0x10>; - #pwm-cells = <2>; + #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; clock-names = "pwm"; pinctrl-names = "default"; From 05bfe0c86a37a8a4cfe96670435a52b101b4ebdc Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 16:09:58 +0800 Subject: [PATCH 188/427] ARM: dts: rk322x: add capture interrupts for pwm3 Change-Id: I38995345de2401b151e42a0c047ee3d31d72402e Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index a3111ef348f0..683aa153e804 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -494,6 +494,7 @@ pwm3: pwm@110b0030 { compatible = "rockchip,rk3288-pwm"; reg = <0x110b0030 0x10>; + interrupts = ; #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; clock-names = "pwm"; From 0777e17b91d2f424fcc6808d231736816b0ab170 Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 16:12:10 +0800 Subject: [PATCH 189/427] ARM: dts: rk322x: add lable for display-subsystem Change-Id: I05d469eb8da0a9241f0ec3eff039039211c4b656 Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 683aa153e804..7f7fd952c415 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -786,7 +786,7 @@ status = "disabled"; }; - display-subsystem { + display_subsystem: display-subsystem { compatible = "rockchip,display-subsystem"; ports = <&vop_out>; }; From 13e8708f28c86aedd672f8a82a01be4b7fd789b7 Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 16:40:06 +0800 Subject: [PATCH 190/427] ARM: dts: rk322x-android: add partitions specified by fstab in device tree Change-Id: I334ee5e8f4e0cbfa274bc72173aa89ac44a0c727 Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x-android.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rk322x-android.dtsi b/arch/arm/boot/dts/rk322x-android.dtsi index b3d677993ab8..532b27940538 100644 --- a/arch/arm/boot/dts/rk322x-android.dtsi +++ b/arch/arm/boot/dts/rk322x-android.dtsi @@ -59,6 +59,29 @@ pinctrl-0 = <&uart21_xfer>; }; + firmware { + android { + compatible = "android,firmware"; + fstab { + compatible = "android,fstab"; + system { + compatible = "android,system"; + dev = "/dev/block/by-name/system"; + type = "ext4"; + mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; + fsmgr_flags = "wait,verify"; + }; + vendor { + compatible = "android,vendor"; + dev = "/dev/block/by-name/vendor"; + type = "ext4"; + mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; + fsmgr_flags = "wait,verify"; + }; + }; + }; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; From 8c9400b3a131458c333c86eb1994f2e1ecb0284a Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 16:44:33 +0800 Subject: [PATCH 191/427] ARM: dts: rk322x-android: Add ramoops and drm-logo Change-Id: Ia6bf599215ca8639ad7f407743f3868b89782efc Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/rk322x-android.dtsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/rk322x-android.dtsi b/arch/arm/boot/dts/rk322x-android.dtsi index 532b27940538..f19ae5668ca7 100644 --- a/arch/arm/boot/dts/rk322x-android.dtsi +++ b/arch/arm/boot/dts/rk322x-android.dtsi @@ -82,6 +82,30 @@ }; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + drm_logo: drm-logo@00000000 { + compatible = "rockchip,drm-logo"; + reg = <0x0 0x0>; + }; + + ramoops_mem: ramoops@68000000 { + reg = <0x68000000 0xf0000>; + }; + }; + + ramoops { + compatible = "ramoops"; + record-size = <0x0 0x20000>; + console-size = <0x0 0x80000>; + ftrace-size = <0x0 0x00000>; + pmsg-size = <0x0 0x50000>; + memory-region = <&ramoops_mem>; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; From 5e64a923d9abc3f778aed54baa6ad1ff65ccc18a Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 2 Feb 2018 16:48:18 +0800 Subject: [PATCH 192/427] ARM: dts: rockchip: Add android board dts file for rk3229 evb Change-Id: Ic6459c66119e5c8e1785cf2f47dfc12c20560f2e Signed-off-by: Zhangbin Tong --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rk3229-evb-android.dts | 434 +++++++++++++++++++++++ 2 files changed, 435 insertions(+) create mode 100644 arch/arm/boot/dts/rk3229-evb-android.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d8594866e7d5..42f854d05c84 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -526,6 +526,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3229-at-gva.dtb \ rk3229-echo-v10.dtb \ rk3229-evb.dtb \ + rk3229-evb-android.dtb \ rk3229-gva-sdk.dtb \ rk3288-evb-act8846.dtb \ rk3288-evb-android-act8846-edp.dtb \ diff --git a/arch/arm/boot/dts/rk3229-evb-android.dts b/arch/arm/boot/dts/rk3229-evb-android.dts new file mode 100644 index 000000000000..e4f70cfc1e57 --- /dev/null +++ b/arch/arm/boot/dts/rk3229-evb-android.dts @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +/dts-v1/; + +#include "rk322x.dtsi" +#include "rk3229-cpu-opp.dtsi" +#include "rk322x-android.dtsi" +#include + +/ { + model = "Rockchip RK3229 Evaluation board"; + compatible = "rockchip,rk3229-evb", "rockchip,rk3229"; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + + power_key: power-key { + label = "GPIO Key Power"; + gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <100>; + wakeup-source; + }; + }; + + hdmi_sound: hdmi-sound { + status = "okay"; + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "rockchip,hdmi"; + simple-audio-card,cpu { + sound-dai = <&i2s0>; + }; + simple-audio-card,codec { + sound-dai = <&hdmi>; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + vccio_1v8_reg: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vccio_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vccio_3v3_reg: regulator@1 { + compatible = "regulator-fixed"; + regulator-name = "vccio_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>; /* GPIO2_D2 */ + }; + + spdif_out: spdif-out { + status = "okay"; + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif-sound { + status = "okay"; + compatible = "simple-audio-card"; + simple-audio-card,name = "ROCKCHIP,SPDIF"; + simple-audio-card,cpu { + sound-dai = <&spdif>; + }; + simple-audio-card,codec { + sound-dai = <&spdif_out>; + }; + }; + + vcc_host: vcc-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc_host"; + regulator-always-on; + regulator-boot-on; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + enable-active-high; + regulator-name = "vcc_phy"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_arm: vdd-arm-regulator { + compatible = "pwm-regulator"; + rockchip,pwm_id = <1>; + rockchip,pwm_voltage = <1100000>; + pwms = <&pwm1 0 25000 1>; + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_log: vdd-log-regulator { + compatible = "pwm-regulator"; + rockchip,pwm_id = <2>; + rockchip,pwm_voltage = <1200000>; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + wifi_chip_type = "ap6335"; + sdio_vref = <1800>; + WIFI,host_wake_irq = <&gpio0 28 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + logo-memory-region = <&drm_logo>; + status = "okay"; + + route { + route_hdmi: route-hdmi { + status = "okay"; + logo,uboot = "logo.bmp"; + logo,kernel = "logo_kernel.bmp"; + logo,mode = "center"; + charge_logo,mode = "center"; + connect = <&vop_out_hdmi>; + }; + }; +}; + +&gmac { + assigned-clocks = <&cru SCLK_MAC_SRC>; + assigned-clock-rates = <50000000>; + clock_in_out = "output"; + phy-supply = <&vcc_phy>; + phy-mode = "rmii"; + phy-is-integrated; + status = "okay"; +}; + +&gpu { + status = "okay"; + mali-supply = <&vdd_log>; +}; + +&hdmi { + status = "okay"; + #sound-dai-cells = <0>; + ddc-i2c-scl-high-time-ns = <9625>; + ddc-i2c-scl-low-time-ns = <10000>; + rockchip,phy_table = + <165000000 0 0 4 4 4 4>, + <225000000 0 0 6 6 6 6>, + <340000000 1 0 6 10 10 10>, + <594000000 1 0 7 10 10 10>; +}; + +&io_domains { + status = "okay"; + + vccio1-supply = <&vccio_3v3_reg>; + vccio2-supply = <&vccio_1v8_reg>; + vccio4-supply = <&vccio_3v3_reg>; +}; + +&i2c0 { + status = "okay"; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + }; +}; + +&i2s0 { + status = "okay"; + rockchip,bclk-fs = <128>; + #sound-dai-cells = <0>; +}; + +&pinctrl { + keys { + pwr_key: pwr-key { + rockchip,pins = <3 23 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdmmc { + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <1 14 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <2 26 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <3 20 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; + compatible = "rockchip,remotectl-pwm"; + remote_pwm_id = <3>; + handle_cpu_id = <1>; + remote_support_psci = <1>; + + ir_key1 { + rockchip,usercode = <0x4040>; + rockchip,key_table = + <0xf2 KEY_REPLY>, + <0xba KEY_BACK>, + <0xf4 KEY_UP>, + <0xf1 KEY_DOWN>, + <0xef KEY_LEFT>, + <0xee KEY_RIGHT>, + <0xbd KEY_HOME>, + <0xea KEY_VOLUMEUP>, + <0xe3 KEY_VOLUMEDOWN>, + <0xe2 KEY_SEARCH>, + <0xb2 KEY_POWER>, + <0xbc KEY_MUTE>, + <0xec KEY_MENU>, + <0xbf 0x190>, + <0xe0 0x191>, + <0xe1 0x192>, + <0xe9 183>, + <0xe6 248>, + <0xe8 185>, + <0xe7 186>, + <0xf0 388>, + <0xbe 0x175>; + }; + + ir_key2 { + rockchip,usercode = <0xff00>; + rockchip,key_table = + <0xf9 KEY_HOME>, + <0xbf KEY_BACK>, + <0xfb KEY_MENU>, + <0xaa KEY_REPLY>, + <0xb9 KEY_UP>, + <0xe9 KEY_DOWN>, + <0xb8 KEY_LEFT>, + <0xea KEY_RIGHT>, + <0xeb KEY_VOLUMEDOWN>, + <0xef KEY_VOLUMEUP>, + <0xf7 KEY_MUTE>, + <0xe7 KEY_POWER>, + <0xfc KEY_POWER>, + <0xa9 KEY_VOLUMEDOWN>, + <0xa8 KEY_PLAYPAUSE>, + <0xe0 KEY_VOLUMEDOWN>, + <0xa5 KEY_VOLUMEDOWN>, + <0xab 183>, + <0xb7 388>, + <0xe8 388>, + <0xf8 184>, + <0xaf 185>, + <0xed KEY_VOLUMEDOWN>, + <0xee 186>, + <0xb3 KEY_VOLUMEDOWN>, + <0xf1 KEY_VOLUMEDOWN>, + <0xf2 KEY_VOLUMEDOWN>, + <0xf3 KEY_SEARCH>, + <0xb4 KEY_VOLUMEDOWN>, + <0xa4 KEY_SETUP>, + <0xbe KEY_SEARCH>; + }; + + ir_key3 { + rockchip,usercode = <0x1dcc>; + rockchip,key_table = + <0xee KEY_REPLY>, + <0xf0 KEY_BACK>, + <0xf8 KEY_UP>, + <0xbb KEY_DOWN>, + <0xef KEY_LEFT>, + <0xed KEY_RIGHT>, + <0xfc KEY_HOME>, + <0xf1 KEY_VOLUMEUP>, + <0xfd KEY_VOLUMEDOWN>, + <0xb7 KEY_SEARCH>, + <0xff KEY_POWER>, + <0xf3 KEY_MUTE>, + <0xbf KEY_MENU>, + <0xf9 0x191>, + <0xf5 0x192>, + <0xb3 388>, + <0xbe KEY_1>, + <0xba KEY_2>, + <0xb2 KEY_3>, + <0xbd KEY_4>, + <0xf9 KEY_5>, + <0xb1 KEY_6>, + <0xfc KEY_7>, + <0xf8 KEY_8>, + <0xb0 KEY_9>, + <0xb6 KEY_0>, + <0xb5 KEY_BACKSPACE>; + }; +}; + +&sdio { + status = "okay"; + mmc-pwrseq = <&sdio_pwrseq>; +}; + +&sdmmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr &sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; +}; + +&spdif { + status = "okay"; + #sound-dai-cells = <0>; +}; + +&threshold { + temperature = <90000>; /* millicelsius */ +}; + +&target { + temperature = <105000>; /* millicelsius */ +}; + +&soc_crit { + temperature = <110000>; /* millicelsius */ +}; + +&tsadc { + rockchip,hw-tshut-temp = <120000>; + status = "okay"; +}; + +&u2phy0_host { + phy-supply = <&vcc_host>; +}; + +&u2phy1_host { + phy-supply = <&vcc_host>; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host2_ehci { + status = "okay"; +}; + +&usb_host2_ohci { + status = "okay"; +}; From 142f58d54610605ebb3be9254aa6b3e2a8ade8b7 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 17 Jan 2018 14:36:49 +0800 Subject: [PATCH 193/427] MALI: rockchip: add arm release of Bifrost DDK r8p0-01rel0 Change-Id: If8d2c3a903a205e3a7c101c4383735940439c9d0 Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/Kbuild | 174 + drivers/gpu/arm/bifrost/Kconfig | 197 + drivers/gpu/arm/bifrost/Makefile | 42 + drivers/gpu/arm/bifrost/Makefile.kbase | 17 + drivers/gpu/arm/bifrost/backend/gpu/Kbuild | 60 + .../backend/gpu/mali_kbase_backend_config.h | 29 + .../gpu/mali_kbase_cache_policy_backend.c | 29 + .../gpu/mali_kbase_cache_policy_backend.h | 34 + .../gpu/mali_kbase_debug_job_fault_backend.c | 157 + .../bifrost/backend/gpu/mali_kbase_devfreq.c | 413 ++ .../bifrost/backend/gpu/mali_kbase_devfreq.h | 24 + .../backend/gpu/mali_kbase_device_hw.c | 255 + .../backend/gpu/mali_kbase_device_internal.h | 67 + .../arm/bifrost/backend/gpu/mali_kbase_gpu.c | 123 + .../backend/gpu/mali_kbase_gpuprops_backend.c | 110 + .../backend/gpu/mali_kbase_instr_backend.c | 492 ++ .../backend/gpu/mali_kbase_instr_defs.h | 58 + .../backend/gpu/mali_kbase_instr_internal.h | 45 + .../backend/gpu/mali_kbase_irq_internal.h | 39 + .../backend/gpu/mali_kbase_irq_linux.c | 469 ++ .../bifrost/backend/gpu/mali_kbase_jm_as.c | 235 + .../bifrost/backend/gpu/mali_kbase_jm_defs.h | 123 + .../bifrost/backend/gpu/mali_kbase_jm_hw.c | 1512 +++++ .../backend/gpu/mali_kbase_jm_internal.h | 164 + .../bifrost/backend/gpu/mali_kbase_jm_rb.c | 1947 +++++++ .../bifrost/backend/gpu/mali_kbase_jm_rb.h | 76 + .../backend/gpu/mali_kbase_js_affinity.c | 303 + .../backend/gpu/mali_kbase_js_affinity.h | 129 + .../backend/gpu/mali_kbase_js_backend.c | 356 ++ .../backend/gpu/mali_kbase_js_internal.h | 69 + .../backend/gpu/mali_kbase_mmu_hw_direct.c | 401 ++ .../backend/gpu/mali_kbase_mmu_hw_direct.h | 42 + .../backend/gpu/mali_kbase_pm_always_on.c | 63 + .../backend/gpu/mali_kbase_pm_always_on.h | 77 + .../backend/gpu/mali_kbase_pm_backend.c | 478 ++ .../bifrost/backend/gpu/mali_kbase_pm_ca.c | 182 + .../bifrost/backend/gpu/mali_kbase_pm_ca.h | 92 + .../backend/gpu/mali_kbase_pm_ca_devfreq.c | 129 + .../backend/gpu/mali_kbase_pm_ca_devfreq.h | 55 + .../backend/gpu/mali_kbase_pm_ca_fixed.c | 65 + .../backend/gpu/mali_kbase_pm_ca_fixed.h | 40 + .../backend/gpu/mali_kbase_pm_coarse_demand.c | 70 + .../backend/gpu/mali_kbase_pm_coarse_demand.h | 64 + .../bifrost/backend/gpu/mali_kbase_pm_defs.h | 519 ++ .../backend/gpu/mali_kbase_pm_demand.c | 73 + .../backend/gpu/mali_kbase_pm_demand.h | 64 + .../backend/gpu/mali_kbase_pm_driver.c | 1672 ++++++ .../backend/gpu/mali_kbase_pm_internal.h | 548 ++ .../backend/gpu/mali_kbase_pm_metrics.c | 401 ++ .../backend/gpu/mali_kbase_pm_policy.c | 973 ++++ .../backend/gpu/mali_kbase_pm_policy.h | 227 + .../arm/bifrost/backend/gpu/mali_kbase_time.c | 103 + .../arm/bifrost/backend/gpu/mali_kbase_time.h | 52 + drivers/gpu/arm/bifrost/docs/Doxyfile | 126 + .../bifrost/docs/policy_operation_diagram.dot | 112 + .../gpu/arm/bifrost/docs/policy_overview.dot | 63 + drivers/gpu/arm/bifrost/ipa/Kbuild | 27 + drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c | 583 ++ drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h | 165 + .../arm/bifrost/ipa/mali_kbase_ipa_debugfs.c | 219 + .../arm/bifrost/ipa/mali_kbase_ipa_debugfs.h | 49 + .../arm/bifrost/ipa/mali_kbase_ipa_simple.c | 322 ++ .../arm/bifrost/ipa/mali_kbase_ipa_simple.h | 40 + .../ipa/mali_kbase_ipa_vinstr_common.c | 217 + .../ipa/mali_kbase_ipa_vinstr_common.h | 161 + .../bifrost/ipa/mali_kbase_ipa_vinstr_g71.c | 136 + .../arm/bifrost/mali_base_hwconfig_features.h | 282 + .../arm/bifrost/mali_base_hwconfig_issues.h | 1126 ++++ drivers/gpu/arm/bifrost/mali_base_kernel.h | 1822 ++++++ drivers/gpu/arm/bifrost/mali_base_mem_priv.h | 52 + .../bifrost/mali_base_vendor_specific_func.h | 24 + drivers/gpu/arm/bifrost/mali_kbase.h | 616 ++ .../arm/bifrost/mali_kbase_10969_workaround.c | 210 + .../arm/bifrost/mali_kbase_10969_workaround.h | 23 + .../arm/bifrost/mali_kbase_as_fault_debugfs.c | 102 + .../arm/bifrost/mali_kbase_as_fault_debugfs.h | 45 + .../gpu/arm/bifrost/mali_kbase_cache_policy.c | 54 + .../gpu/arm/bifrost/mali_kbase_cache_policy.h | 45 + drivers/gpu/arm/bifrost/mali_kbase_config.c | 51 + drivers/gpu/arm/bifrost/mali_kbase_config.h | 343 ++ .../arm/bifrost/mali_kbase_config_defaults.h | 226 + drivers/gpu/arm/bifrost/mali_kbase_context.c | 362 ++ drivers/gpu/arm/bifrost/mali_kbase_context.h | 90 + .../gpu/arm/bifrost/mali_kbase_core_linux.c | 4979 +++++++++++++++++ .../gpu/arm/bifrost/mali_kbase_ctx_sched.c | 203 + .../gpu/arm/bifrost/mali_kbase_ctx_sched.h | 131 + drivers/gpu/arm/bifrost/mali_kbase_debug.c | 39 + drivers/gpu/arm/bifrost/mali_kbase_debug.h | 164 + .../arm/bifrost/mali_kbase_debug_job_fault.c | 499 ++ .../arm/bifrost/mali_kbase_debug_job_fault.h | 96 + .../arm/bifrost/mali_kbase_debug_mem_view.c | 306 + .../arm/bifrost/mali_kbase_debug_mem_view.h | 25 + drivers/gpu/arm/bifrost/mali_kbase_defs.h | 1639 ++++++ drivers/gpu/arm/bifrost/mali_kbase_device.c | 674 +++ .../arm/bifrost/mali_kbase_disjoint_events.c | 76 + .../gpu/arm/bifrost/mali_kbase_dma_fence.c | 449 ++ .../gpu/arm/bifrost/mali_kbase_dma_fence.h | 131 + drivers/gpu/arm/bifrost/mali_kbase_event.c | 259 + drivers/gpu/arm/bifrost/mali_kbase_fence.c | 196 + drivers/gpu/arm/bifrost/mali_kbase_fence.h | 270 + .../gpu/arm/bifrost/mali_kbase_fence_defs.h | 51 + drivers/gpu/arm/bifrost/mali_kbase_gator.h | 45 + .../gpu/arm/bifrost/mali_kbase_gator_api.c | 334 ++ .../gpu/arm/bifrost/mali_kbase_gator_api.h | 219 + .../bifrost/mali_kbase_gator_hwcnt_names.h | 2167 +++++++ .../mali_kbase_gator_hwcnt_names_thex.h | 291 + .../mali_kbase_gator_hwcnt_names_tmix.h | 291 + .../mali_kbase_gator_hwcnt_names_tsix.h | 291 + drivers/gpu/arm/bifrost/mali_kbase_gpu_id.h | 118 + .../bifrost/mali_kbase_gpu_memory_debugfs.c | 97 + .../bifrost/mali_kbase_gpu_memory_debugfs.h | 37 + drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c | 514 ++ drivers/gpu/arm/bifrost/mali_kbase_gpuprops.h | 84 + .../arm/bifrost/mali_kbase_gpuprops_types.h | 92 + drivers/gpu/arm/bifrost/mali_kbase_hw.c | 446 ++ drivers/gpu/arm/bifrost/mali_kbase_hw.h | 65 + .../arm/bifrost/mali_kbase_hwaccess_backend.h | 54 + .../arm/bifrost/mali_kbase_hwaccess_defs.h | 36 + .../bifrost/mali_kbase_hwaccess_gpuprops.h | 47 + .../arm/bifrost/mali_kbase_hwaccess_instr.h | 116 + .../gpu/arm/bifrost/mali_kbase_hwaccess_jm.h | 381 ++ .../gpu/arm/bifrost/mali_kbase_hwaccess_pm.h | 209 + .../arm/bifrost/mali_kbase_hwaccess_time.h | 53 + .../gpu/arm/bifrost/mali_kbase_hwcnt_reader.h | 66 + drivers/gpu/arm/bifrost/mali_kbase_ioctl.h | 658 +++ drivers/gpu/arm/bifrost/mali_kbase_jd.c | 1847 ++++++ .../gpu/arm/bifrost/mali_kbase_jd_debugfs.c | 235 + .../gpu/arm/bifrost/mali_kbase_jd_debugfs.h | 40 + drivers/gpu/arm/bifrost/mali_kbase_jm.c | 131 + drivers/gpu/arm/bifrost/mali_kbase_jm.h | 110 + drivers/gpu/arm/bifrost/mali_kbase_js.c | 2798 +++++++++ drivers/gpu/arm/bifrost/mali_kbase_js.h | 925 +++ .../gpu/arm/bifrost/mali_kbase_js_ctx_attr.c | 301 + .../gpu/arm/bifrost/mali_kbase_js_ctx_attr.h | 158 + drivers/gpu/arm/bifrost/mali_kbase_js_defs.h | 386 ++ drivers/gpu/arm/bifrost/mali_kbase_linux.h | 43 + drivers/gpu/arm/bifrost/mali_kbase_mem.c | 2871 ++++++++++ drivers/gpu/arm/bifrost/mali_kbase_mem.h | 1142 ++++ .../gpu/arm/bifrost/mali_kbase_mem_linux.c | 2678 +++++++++ .../gpu/arm/bifrost/mali_kbase_mem_linux.h | 240 + .../gpu/arm/bifrost/mali_kbase_mem_lowlevel.h | 89 + drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c | 651 +++ .../arm/bifrost/mali_kbase_mem_pool_debugfs.c | 88 + .../arm/bifrost/mali_kbase_mem_pool_debugfs.h | 40 + .../bifrost/mali_kbase_mem_profile_debugfs.c | 121 + .../bifrost/mali_kbase_mem_profile_debugfs.h | 59 + .../mali_kbase_mem_profile_debugfs_buf_size.h | 33 + drivers/gpu/arm/bifrost/mali_kbase_mmu.c | 2138 +++++++ drivers/gpu/arm/bifrost/mali_kbase_mmu_hw.h | 123 + .../arm/bifrost/mali_kbase_mmu_mode_aarch64.c | 214 + .../arm/bifrost/mali_kbase_mmu_mode_lpae.c | 199 + .../arm/bifrost/mali_kbase_platform_fake.c | 119 + drivers/gpu/arm/bifrost/mali_kbase_pm.c | 205 + drivers/gpu/arm/bifrost/mali_kbase_pm.h | 171 + .../bifrost/mali_kbase_profiling_gator_api.h | 40 + .../bifrost/mali_kbase_regs_history_debugfs.c | 130 + .../bifrost/mali_kbase_regs_history_debugfs.h | 50 + drivers/gpu/arm/bifrost/mali_kbase_replay.c | 1166 ++++ drivers/gpu/arm/bifrost/mali_kbase_smc.c | 74 + drivers/gpu/arm/bifrost/mali_kbase_smc.h | 67 + drivers/gpu/arm/bifrost/mali_kbase_softjobs.c | 1513 +++++ drivers/gpu/arm/bifrost/mali_kbase_strings.c | 23 + drivers/gpu/arm/bifrost/mali_kbase_strings.h | 19 + drivers/gpu/arm/bifrost/mali_kbase_sync.h | 203 + .../gpu/arm/bifrost/mali_kbase_sync_android.c | 537 ++ .../gpu/arm/bifrost/mali_kbase_sync_common.c | 43 + .../gpu/arm/bifrost/mali_kbase_sync_file.c | 348 ++ drivers/gpu/arm/bifrost/mali_kbase_tlstream.c | 2572 +++++++++ drivers/gpu/arm/bifrost/mali_kbase_tlstream.h | 623 +++ .../gpu/arm/bifrost/mali_kbase_trace_defs.h | 264 + .../arm/bifrost/mali_kbase_trace_timeline.c | 236 + .../arm/bifrost/mali_kbase_trace_timeline.h | 363 ++ .../bifrost/mali_kbase_trace_timeline_defs.h | 140 + drivers/gpu/arm/bifrost/mali_kbase_uku.h | 532 ++ drivers/gpu/arm/bifrost/mali_kbase_utility.c | 33 + drivers/gpu/arm/bifrost/mali_kbase_utility.h | 37 + drivers/gpu/arm/bifrost/mali_kbase_vinstr.c | 2072 +++++++ drivers/gpu/arm/bifrost/mali_kbase_vinstr.h | 155 + .../gpu/arm/bifrost/mali_linux_kbase_trace.h | 201 + drivers/gpu/arm/bifrost/mali_linux_trace.h | 189 + drivers/gpu/arm/bifrost/mali_malisw.h | 131 + drivers/gpu/arm/bifrost/mali_midg_coherency.h | 26 + drivers/gpu/arm/bifrost/mali_midg_regmap.h | 611 ++ drivers/gpu/arm/bifrost/mali_timeline.h | 396 ++ drivers/gpu/arm/bifrost/mali_uk.h | 141 + drivers/gpu/arm/bifrost/platform/Kconfig | 24 + .../arm/bifrost/platform/devicetree/Kbuild | 18 + .../devicetree/mali_kbase_config_devicetree.c | 40 + .../devicetree/mali_kbase_config_platform.h | 80 + .../devicetree/mali_kbase_runtime_pm.c | 121 + .../platform/mali_kbase_platform_common.h | 26 + .../gpu/arm/bifrost/platform/vexpress/Kbuild | 19 + .../vexpress/mali_kbase_config_platform.h | 75 + .../vexpress/mali_kbase_config_vexpress.c | 85 + .../vexpress/mali_kbase_cpu_vexpress.c | 279 + .../vexpress/mali_kbase_cpu_vexpress.h | 38 + .../bifrost/platform/vexpress_1xv7_a57/Kbuild | 18 + .../mali_kbase_config_platform.h | 73 + .../mali_kbase_config_vexpress.c | 79 + .../platform/vexpress_6xvirtex7_10mhz/Kbuild | 19 + .../mali_kbase_config_platform.h | 75 + .../mali_kbase_config_vexpress.c | 83 + .../mali_kbase_cpu_vexpress.c | 71 + .../mali_kbase_cpu_vexpress.h | 28 + .../arm/bifrost/platform_dummy/mali_ukk_os.h | 53 + .../gpu/arm/bifrost/protected_mode_switcher.h | 64 + drivers/gpu/arm/bifrost/sconscript | 72 + drivers/gpu/arm/bifrost/tests/Kbuild | 17 + drivers/gpu/arm/bifrost/tests/Kconfig | 17 + .../bifrost/tests/include/kutf/kutf_helpers.h | 216 + .../tests/include/kutf/kutf_helpers_user.h | 179 + .../arm/bifrost/tests/include/kutf/kutf_mem.h | 68 + .../tests/include/kutf/kutf_resultset.h | 121 + .../bifrost/tests/include/kutf/kutf_suite.h | 568 ++ .../bifrost/tests/include/kutf/kutf_utils.h | 55 + drivers/gpu/arm/bifrost/tests/kutf/Kbuild | 20 + drivers/gpu/arm/bifrost/tests/kutf/Kconfig | 22 + drivers/gpu/arm/bifrost/tests/kutf/Makefile | 29 + .../gpu/arm/bifrost/tests/kutf/kutf_helpers.c | 768 +++ .../bifrost/tests/kutf/kutf_helpers_user.c | 460 ++ drivers/gpu/arm/bifrost/tests/kutf/kutf_mem.c | 102 + .../arm/bifrost/tests/kutf/kutf_resultset.c | 95 + .../gpu/arm/bifrost/tests/kutf/kutf_suite.c | 1398 +++++ .../gpu/arm/bifrost/tests/kutf/kutf_utils.c | 71 + drivers/gpu/arm/bifrost/tests/kutf/sconscript | 21 + .../bifrost/tests/mali_kutf_irq_test/Kbuild | 20 + .../bifrost/tests/mali_kutf_irq_test/Kconfig | 23 + .../bifrost/tests/mali_kutf_irq_test/Makefile | 47 + .../mali_kutf_irq_test_main.c | 269 + .../tests/mali_kutf_irq_test/sconscript | 30 + drivers/gpu/arm/bifrost/tests/sconscript | 38 + 231 files changed, 75913 insertions(+) create mode 100644 drivers/gpu/arm/bifrost/Kbuild create mode 100644 drivers/gpu/arm/bifrost/Kconfig create mode 100644 drivers/gpu/arm/bifrost/Makefile create mode 100644 drivers/gpu/arm/bifrost/Makefile.kbase create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/Kbuild create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_backend_config.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_debug_job_fault_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_as.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_defs.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.h create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c create mode 100644 drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h create mode 100644 drivers/gpu/arm/bifrost/docs/Doxyfile create mode 100644 drivers/gpu/arm/bifrost/docs/policy_operation_diagram.dot create mode 100644 drivers/gpu/arm/bifrost/docs/policy_overview.dot create mode 100644 drivers/gpu/arm/bifrost/ipa/Kbuild create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.c create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.h create mode 100644 drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_g71.c create mode 100644 drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h create mode 100644 drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h create mode 100644 drivers/gpu/arm/bifrost/mali_base_kernel.h create mode 100644 drivers/gpu/arm/bifrost/mali_base_mem_priv.h create mode 100644 drivers/gpu/arm/bifrost/mali_base_vendor_specific_func.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_cache_policy.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_cache_policy.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_config.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_config.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_context.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_context.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_core_linux.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_device.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_disjoint_events.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_event.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_fence.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_fence.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_api.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_api.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_thex.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tmix.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tsix.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpu_id.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpuprops.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_gpuprops_types.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hw.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hw.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_backend.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_gpuprops.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_instr.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_jm.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_pm.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_ioctl.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_jd.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_jm.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_jm.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_js.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_js.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_js_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_linux.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_lowlevel.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mmu.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mmu_hw.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_aarch64.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_lpae.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_pm.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_pm.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_profiling_gator_api.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_replay.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_smc.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_smc.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_softjobs.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_strings.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_strings.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_sync.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_sync_android.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_sync_common.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_sync_file.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_tlstream.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_tlstream.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_trace_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_trace_timeline_defs.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_uku.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_utility.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_utility.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_vinstr.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_vinstr.h create mode 100644 drivers/gpu/arm/bifrost/mali_linux_kbase_trace.h create mode 100644 drivers/gpu/arm/bifrost/mali_linux_trace.h create mode 100644 drivers/gpu/arm/bifrost/mali_malisw.h create mode 100644 drivers/gpu/arm/bifrost/mali_midg_coherency.h create mode 100644 drivers/gpu/arm/bifrost/mali_midg_regmap.h create mode 100644 drivers/gpu/arm/bifrost/mali_timeline.h create mode 100644 drivers/gpu/arm/bifrost/mali_uk.h create mode 100644 drivers/gpu/arm/bifrost/platform/Kconfig create mode 100644 drivers/gpu/arm/bifrost/platform/devicetree/Kbuild create mode 100644 drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_devicetree.c create mode 100644 drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h create mode 100644 drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c create mode 100644 drivers/gpu/arm/bifrost/platform/mali_kbase_platform_common.h create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress/Kbuild create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_platform.h create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_vexpress.c create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.c create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.h create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/Kbuild create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/Kbuild create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c create mode 100644 drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.h create mode 100644 drivers/gpu/arm/bifrost/platform_dummy/mali_ukk_os.h create mode 100644 drivers/gpu/arm/bifrost/protected_mode_switcher.h create mode 100644 drivers/gpu/arm/bifrost/sconscript create mode 100644 drivers/gpu/arm/bifrost/tests/Kbuild create mode 100644 drivers/gpu/arm/bifrost/tests/Kconfig create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers.h create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers_user.h create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_mem.h create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_resultset.h create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_suite.h create mode 100644 drivers/gpu/arm/bifrost/tests/include/kutf/kutf_utils.h create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/Kbuild create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/Kconfig create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/Makefile create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_mem.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_resultset.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c create mode 100644 drivers/gpu/arm/bifrost/tests/kutf/sconscript create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kbuild create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript create mode 100644 drivers/gpu/arm/bifrost/tests/sconscript diff --git a/drivers/gpu/arm/bifrost/Kbuild b/drivers/gpu/arm/bifrost/Kbuild new file mode 100644 index 000000000000..49d016ef2582 --- /dev/null +++ b/drivers/gpu/arm/bifrost/Kbuild @@ -0,0 +1,174 @@ +# +# (C) COPYRIGHT 2012-2016, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +# Driver version string which is returned to userspace via an ioctl +MALI_RELEASE_NAME ?= "r8p0-01rel0" + +# Paths required for build +KBASE_PATH = $(src) +KBASE_PLATFORM_PATH = $(KBASE_PATH)/platform_dummy +UMP_PATH = $(src)/../../../base + +ifeq ($(CONFIG_MALI_ERROR_INJECT),y) +MALI_ERROR_INJECT_ON = 1 +endif + +# Set up defaults if not defined by build system +MALI_CUSTOMER_RELEASE ?= 1 +MALI_UNIT_TEST ?= 0 +MALI_KERNEL_TEST_API ?= 0 +MALI_ERROR_INJECT_ON ?= 0 +MALI_MOCK_TEST ?= 0 +MALI_COVERAGE ?= 0 +MALI_INSTRUMENTATION_LEVEL ?= 0 +CONFIG_MALI_PLATFORM_NAME ?= "devicetree" +# This workaround is for what seems to be a compiler bug we observed in +# GCC 4.7 on AOSP 4.3. The bug caused an intermittent failure compiling +# the "_Pragma" syntax, where an error message is returned: +# +# "internal compiler error: unspellable token PRAGMA" +# +# This regression has thus far only been seen on the GCC 4.7 compiler bundled +# with AOSP 4.3.0. So this makefile, intended for in-tree kernel builds +# which are not known to be used with AOSP, is hardcoded to disable the +# workaround, i.e. set the define to 0. +MALI_GCC_WORKAROUND_MIDCOM_4598 ?= 0 + +# Set up our defines, which will be passed to gcc +DEFINES = \ + -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \ + -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \ + -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ + -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \ + -DMALI_MOCK_TEST=$(MALI_MOCK_TEST) \ + -DMALI_COVERAGE=$(MALI_COVERAGE) \ + -DMALI_INSTRUMENTATION_LEVEL=$(MALI_INSTRUMENTATION_LEVEL) \ + -DMALI_RELEASE_NAME=\"$(MALI_RELEASE_NAME)\" \ + -DMALI_GCC_WORKAROUND_MIDCOM_4598=$(MALI_GCC_WORKAROUND_MIDCOM_4598) + +ifeq ($(KBUILD_EXTMOD),) +# in-tree +DEFINES +=-DMALI_KBASE_PLATFORM_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME) +else +# out-of-tree +DEFINES +=-DMALI_KBASE_PLATFORM_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME) +endif + +DEFINES += -I$(srctree)/drivers/staging/android + +# Use our defines when compiling +ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux +subdir-ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(OSK_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux + +SRC := \ + mali_kbase_device.c \ + mali_kbase_cache_policy.c \ + mali_kbase_mem.c \ + mali_kbase_mmu.c \ + mali_kbase_ctx_sched.c \ + mali_kbase_jd.c \ + mali_kbase_jd_debugfs.c \ + mali_kbase_jm.c \ + mali_kbase_gpuprops.c \ + mali_kbase_js.c \ + mali_kbase_js_ctx_attr.c \ + mali_kbase_event.c \ + mali_kbase_context.c \ + mali_kbase_pm.c \ + mali_kbase_config.c \ + mali_kbase_vinstr.c \ + mali_kbase_softjobs.c \ + mali_kbase_10969_workaround.c \ + mali_kbase_hw.c \ + mali_kbase_utility.c \ + mali_kbase_debug.c \ + mali_kbase_trace_timeline.c \ + mali_kbase_gpu_memory_debugfs.c \ + mali_kbase_mem_linux.c \ + mali_kbase_core_linux.c \ + mali_kbase_replay.c \ + mali_kbase_mem_profile_debugfs.c \ + mali_kbase_mmu_mode_lpae.c \ + mali_kbase_mmu_mode_aarch64.c \ + mali_kbase_disjoint_events.c \ + mali_kbase_gator_api.c \ + mali_kbase_debug_mem_view.c \ + mali_kbase_debug_job_fault.c \ + mali_kbase_smc.c \ + mali_kbase_mem_pool.c \ + mali_kbase_mem_pool_debugfs.c \ + mali_kbase_tlstream.c \ + mali_kbase_strings.c \ + mali_kbase_as_fault_debugfs.c \ + mali_kbase_regs_history_debugfs.c + + + + +ifeq ($(MALI_UNIT_TEST),1) + SRC += mali_kbase_tlstream_test.c +endif + +ifeq ($(MALI_CUSTOMER_RELEASE),0) + SRC += mali_kbase_regs_dump_debugfs.c +endif + + +ccflags-y += -I$(KBASE_PATH) + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o + +# Tell the Linux build system to enable building of our .c files +mali_kbase-y := $(SRC:.c=.o) + +# Kconfig passes in the name with quotes for in-tree builds - remove them. +platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_NAME)) +MALI_PLATFORM_DIR := platform/$(platform_name) +ccflags-y += -I$(src)/$(MALI_PLATFORM_DIR) +include $(src)/$(MALI_PLATFORM_DIR)/Kbuild + +ifeq ($(CONFIG_MALI_DEVFREQ),y) + ifeq ($(CONFIG_DEVFREQ_THERMAL),y) + include $(src)/ipa/Kbuild + endif +endif + +mali_kbase-$(CONFIG_MALI_DMA_FENCE) += \ + mali_kbase_dma_fence.o \ + mali_kbase_fence.o +mali_kbase-$(CONFIG_SYNC) += \ + mali_kbase_sync_android.o \ + mali_kbase_sync_common.o +mali_kbase-$(CONFIG_SYNC_FILE) += \ + mali_kbase_sync_file.o \ + mali_kbase_sync_common.o \ + mali_kbase_fence.o + +ifeq ($(MALI_MOCK_TEST),1) +# Test functionality +mali_kbase-y += tests/internal/src/mock/mali_kbase_pm_driver_mock.o +endif + +include $(src)/backend/gpu/Kbuild +mali_kbase-y += $(BACKEND:.c=.o) + + +ccflags-y += -I$(src)/backend/gpu +subdir-ccflags-y += -I$(src)/backend/gpu + +# For kutf and mali_kutf_irq_latency_test +obj-$(CONFIG_MALI_KUTF) += tests/ diff --git a/drivers/gpu/arm/bifrost/Kconfig b/drivers/gpu/arm/bifrost/Kconfig new file mode 100644 index 000000000000..dc78f84b1eb5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/Kconfig @@ -0,0 +1,197 @@ +# +# (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +menuconfig MALI_MIDGARD + tristate "Mali Midgard series support" + select GPU_TRACEPOINTS if ANDROID + default n + help + Enable this option to build support for a ARM Mali Midgard GPU. + + To compile this driver as a module, choose M here: + this will generate a single module, called mali_kbase. + +config MALI_GATOR_SUPPORT + bool "Streamline support via Gator" + depends on MALI_MIDGARD + default n + help + Adds diagnostic support for use with the ARM Streamline Performance Analyzer. + You will need the Gator device driver already loaded before loading this driver when enabling + Streamline debug support. + This is a legacy interface required by older versions of Streamline. + +config MALI_MIDGARD_DVFS + bool "Enable legacy DVFS" + depends on MALI_MIDGARD && !MALI_DEVFREQ + default n + help + Choose this option to enable legacy DVFS in the Mali Midgard DDK. + +config MALI_MIDGARD_ENABLE_TRACE + bool "Enable kbase tracing" + depends on MALI_MIDGARD + default n + help + Enables tracing in kbase. Trace log available through + the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled + +config MALI_DEVFREQ + bool "devfreq support for Mali" + depends on MALI_MIDGARD && PM_DEVFREQ + help + Support devfreq for Mali. + + Using the devfreq framework and, by default, the simpleondemand + governor, the frequency of Mali will be dynamically selected from the + available OPPs. + +config MALI_DMA_FENCE + bool "DMA_BUF fence support for Mali" + depends on MALI_MIDGARD && !KDS + default n + help + Support DMA_BUF fences for Mali. + + This option should only be enabled if KDS is not present and + the Linux Kernel has built in support for DMA_BUF fences. + +config MALI_PLATFORM_NAME + depends on MALI_MIDGARD + string "Platform name" + default "devicetree" + help + Enter the name of the desired platform configuration directory to + include in the build. 'platform/$(MALI_PLATFORM_NAME)/Kbuild' must + exist. + +# MALI_EXPERT configuration options + +menuconfig MALI_EXPERT + depends on MALI_MIDGARD + bool "Enable Expert Settings" + default n + help + Enabling this option and modifying the default settings may produce a driver with performance or + other limitations. + +config MALI_CORESTACK + bool "Support controlling power to the GPU core stack" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Enabling this feature on supported GPUs will let the driver powering + on/off the GPU core stack independently without involving the Power + Domain Controller. This should only be enabled on platforms which + integration of the PDC to the Mali GPU is known to be problematic. + This feature is currently only supported on t-Six and t-HEx GPUs. + + If unsure, say N. + +config MALI_PRFCNT_SET_SECONDARY + bool "Use secondary set of performance counters" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Select this option to use secondary set of performance counters. Kernel + features that depend on an access to the primary set of counters may + become unavailable. Enabling this option will prevent power management + from working optimally and may cause instrumentation tools to return + bogus results. + + If unsure, say N. + +config MALI_DEBUG + bool "Debug build" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Select this option for increased checking and reporting of errors. + +config MALI_FENCE_DEBUG + bool "Debug sync fence usage" + depends on MALI_MIDGARD && MALI_EXPERT && (SYNC || SYNC_FILE) + default y if MALI_DEBUG + help + Select this option to enable additional checking and reporting on the + use of sync fences in the Mali driver. + + This will add a 3s timeout to all sync fence waits in the Mali + driver, so that when work for Mali has been waiting on a sync fence + for a long time a debug message will be printed, detailing what fence + is causing the block, and which dependent Mali atoms are blocked as a + result of this. + + The timeout can be changed at runtime through the js_soft_timeout + device attribute, where the timeout is specified in milliseconds. + +config MALI_NO_MALI + bool "No Mali" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + This can be used to test the driver in a simulated environment + whereby the hardware is not physically present. If the hardware is physically + present it will not be used. This can be used to test the majority of the + driver without needing actual hardware or for software benchmarking. + All calls to the simulated hardware will complete immediately as if the hardware + completed the task. + +config MALI_ERROR_INJECT + bool "Error injection" + depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI + default n + help + Enables insertion of errors to test module failure and recovery mechanisms. + +config MALI_TRACE_TIMELINE + bool "Timeline tracing" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Enables timeline tracing through the kernel tracepoint system. + +config MALI_SYSTEM_TRACE + bool "Enable system event tracing support" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Choose this option to enable system trace events for each + kbase event. This is typically used for debugging but has + minimal overhead when not in use. Enable only if you know what + you are doing. + +config MALI_2MB_ALLOC + bool "Attempt to allocate 2MB pages" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Rather than allocating all GPU memory page-by-page, attempt to + allocate 2MB pages from the kernel. This reduces TLB pressure and + helps to prevent memory fragmentation. + + If in doubt, say N + +config MALI_PWRSOFT_765 + bool "PWRSOFT-765 ticket" + default n + help + PWRSOFT-765 fixes devfreq cooling devices issues. However, they are + not merged in mainline kernel yet. So this define helps to guard those + parts of the code. + +source "drivers/gpu/arm/midgard/platform/Kconfig" +source "drivers/gpu/arm/midgard/tests/Kconfig" diff --git a/drivers/gpu/arm/bifrost/Makefile b/drivers/gpu/arm/bifrost/Makefile new file mode 100644 index 000000000000..26522d566dd0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/Makefile @@ -0,0 +1,42 @@ +# +# (C) COPYRIGHT 2010-2016, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +KDIR ?= /lib/modules/$(shell uname -r)/build + +BUSLOG_PATH_RELATIVE = $(CURDIR)/../../../.. +UMP_PATH_RELATIVE = $(CURDIR)/../../../base/ump +KBASE_PATH_RELATIVE = $(CURDIR) +KDS_PATH_RELATIVE = $(CURDIR)/../../../.. +EXTRA_SYMBOLS = $(UMP_PATH_RELATIVE)/src/Module.symvers + +ifeq ($(MALI_UNIT_TEST), 1) + EXTRA_SYMBOLS += $(KBASE_PATH_RELATIVE)/tests/internal/src/kernel_assert_module/linux/Module.symvers +endif + +ifeq ($(CONFIG_MALI_FPGA_BUS_LOGGER),y) +#Add bus logger symbols +EXTRA_SYMBOLS += $(BUSLOG_PATH_RELATIVE)/drivers/base/bus_logger/Module.symvers +endif + +# GPL driver supports KDS +EXTRA_SYMBOLS += $(KDS_PATH_RELATIVE)/drivers/base/kds/Module.symvers + +# we get the symbols from modules using KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions +all: + $(MAKE) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include -I$(CURDIR)/../../../../tests/include $(SCONS_CFLAGS)" $(SCONS_CONFIGS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules + +clean: + $(MAKE) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/gpu/arm/bifrost/Makefile.kbase b/drivers/gpu/arm/bifrost/Makefile.kbase new file mode 100644 index 000000000000..2bef9c25eaeb --- /dev/null +++ b/drivers/gpu/arm/bifrost/Makefile.kbase @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2010 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH) -I$(OSK_PATH)/src/linux/include -I$(KBASE_PATH)/platform_$(PLATFORM) + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/Kbuild b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild new file mode 100644 index 000000000000..5f700e9b6b44 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild @@ -0,0 +1,60 @@ +# +# (C) COPYRIGHT 2014,2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +BACKEND += \ + backend/gpu/mali_kbase_cache_policy_backend.c \ + backend/gpu/mali_kbase_device_hw.c \ + backend/gpu/mali_kbase_gpu.c \ + backend/gpu/mali_kbase_gpuprops_backend.c \ + backend/gpu/mali_kbase_debug_job_fault_backend.c \ + backend/gpu/mali_kbase_irq_linux.c \ + backend/gpu/mali_kbase_instr_backend.c \ + backend/gpu/mali_kbase_jm_as.c \ + backend/gpu/mali_kbase_jm_hw.c \ + backend/gpu/mali_kbase_jm_rb.c \ + backend/gpu/mali_kbase_js_affinity.c \ + backend/gpu/mali_kbase_js_backend.c \ + backend/gpu/mali_kbase_mmu_hw_direct.c \ + backend/gpu/mali_kbase_pm_backend.c \ + backend/gpu/mali_kbase_pm_driver.c \ + backend/gpu/mali_kbase_pm_metrics.c \ + backend/gpu/mali_kbase_pm_ca.c \ + backend/gpu/mali_kbase_pm_ca_fixed.c \ + backend/gpu/mali_kbase_pm_always_on.c \ + backend/gpu/mali_kbase_pm_coarse_demand.c \ + backend/gpu/mali_kbase_pm_demand.c \ + backend/gpu/mali_kbase_pm_policy.c \ + backend/gpu/mali_kbase_time.c + +ifeq ($(MALI_CUSTOMER_RELEASE),0) +BACKEND += \ + backend/gpu/mali_kbase_pm_ca_random.c \ + backend/gpu/mali_kbase_pm_demand_always_powered.c \ + backend/gpu/mali_kbase_pm_fast_start.c +endif + +ifeq ($(CONFIG_MALI_DEVFREQ),y) +BACKEND += \ + backend/gpu/mali_kbase_devfreq.c \ + backend/gpu/mali_kbase_pm_ca_devfreq.c +endif + +ifeq ($(CONFIG_MALI_NO_MALI),y) + # Dummy model + BACKEND += backend/gpu/mali_kbase_model_dummy.c + BACKEND += backend/gpu/mali_kbase_model_linux.c + # HW error simulation + BACKEND += backend/gpu/mali_kbase_model_error_generator.c +endif diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_backend_config.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_backend_config.h new file mode 100644 index 000000000000..c8ae87eb84a2 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_backend_config.h @@ -0,0 +1,29 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Backend specific configuration + */ + +#ifndef _KBASE_BACKEND_CONFIG_H_ +#define _KBASE_BACKEND_CONFIG_H_ + +/* Enable GPU reset API */ +#define KBASE_GPU_RESET_EN 1 + +#endif /* _KBASE_BACKEND_CONFIG_H_ */ + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c new file mode 100644 index 000000000000..fef9a2cb743e --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c @@ -0,0 +1,29 @@ +/* + * + * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "backend/gpu/mali_kbase_cache_policy_backend.h" +#include + +void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, + u32 mode) +{ + kbdev->current_gpu_coherency_mode = mode; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_COHERENCY_REG)) + kbase_reg_write(kbdev, COHERENCY_ENABLE, mode, NULL); +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h new file mode 100644 index 000000000000..fe9869109a82 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h @@ -0,0 +1,34 @@ +/* + * + * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _KBASE_CACHE_POLICY_BACKEND_H_ +#define _KBASE_CACHE_POLICY_BACKEND_H_ + +#include "mali_kbase.h" +#include "mali_base_kernel.h" + +/** + * kbase_cache_set_coherency_mode() - Sets the system coherency mode + * in the GPU. + * @kbdev: Device pointer + * @mode: Coherency mode. COHERENCY_ACE/ACE_LITE + */ +void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, + u32 mode); + +#endif /* _KBASE_CACHE_POLICY_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_debug_job_fault_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_debug_job_fault_backend.c new file mode 100644 index 000000000000..7851ea6466c7 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_debug_job_fault_backend.c @@ -0,0 +1,157 @@ +/* + * + * (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include "mali_kbase_debug_job_fault.h" + +#ifdef CONFIG_DEBUG_FS + +/*GPU_CONTROL_REG(r)*/ +static int gpu_control_reg_snapshot[] = { + GPU_ID, + SHADER_READY_LO, + SHADER_READY_HI, + TILER_READY_LO, + TILER_READY_HI, + L2_READY_LO, + L2_READY_HI +}; + +/* JOB_CONTROL_REG(r) */ +static int job_control_reg_snapshot[] = { + JOB_IRQ_MASK, + JOB_IRQ_STATUS +}; + +/* JOB_SLOT_REG(n,r) */ +static int job_slot_reg_snapshot[] = { + JS_HEAD_LO, + JS_HEAD_HI, + JS_TAIL_LO, + JS_TAIL_HI, + JS_AFFINITY_LO, + JS_AFFINITY_HI, + JS_CONFIG, + JS_STATUS, + JS_HEAD_NEXT_LO, + JS_HEAD_NEXT_HI, + JS_AFFINITY_NEXT_LO, + JS_AFFINITY_NEXT_HI, + JS_CONFIG_NEXT +}; + +/*MMU_REG(r)*/ +static int mmu_reg_snapshot[] = { + MMU_IRQ_MASK, + MMU_IRQ_STATUS +}; + +/* MMU_AS_REG(n,r) */ +static int as_reg_snapshot[] = { + AS_TRANSTAB_LO, + AS_TRANSTAB_HI, + AS_MEMATTR_LO, + AS_MEMATTR_HI, + AS_FAULTSTATUS, + AS_FAULTADDRESS_LO, + AS_FAULTADDRESS_HI, + AS_STATUS +}; + +bool kbase_debug_job_fault_reg_snapshot_init(struct kbase_context *kctx, + int reg_range) +{ + int i, j; + int offset = 0; + int slot_number; + int as_number; + + if (kctx->reg_dump == NULL) + return false; + + slot_number = kctx->kbdev->gpu_props.num_job_slots; + as_number = kctx->kbdev->gpu_props.num_address_spaces; + + /* get the GPU control registers*/ + for (i = 0; i < sizeof(gpu_control_reg_snapshot)/4; i++) { + kctx->reg_dump[offset] = + GPU_CONTROL_REG(gpu_control_reg_snapshot[i]); + offset += 2; + } + + /* get the Job control registers*/ + for (i = 0; i < sizeof(job_control_reg_snapshot)/4; i++) { + kctx->reg_dump[offset] = + JOB_CONTROL_REG(job_control_reg_snapshot[i]); + offset += 2; + } + + /* get the Job Slot registers*/ + for (j = 0; j < slot_number; j++) { + for (i = 0; i < sizeof(job_slot_reg_snapshot)/4; i++) { + kctx->reg_dump[offset] = + JOB_SLOT_REG(j, job_slot_reg_snapshot[i]); + offset += 2; + } + } + + /* get the MMU registers*/ + for (i = 0; i < sizeof(mmu_reg_snapshot)/4; i++) { + kctx->reg_dump[offset] = MMU_REG(mmu_reg_snapshot[i]); + offset += 2; + } + + /* get the Address space registers*/ + for (j = 0; j < as_number; j++) { + for (i = 0; i < sizeof(as_reg_snapshot)/4; i++) { + kctx->reg_dump[offset] = + MMU_AS_REG(j, as_reg_snapshot[i]); + offset += 2; + } + } + + WARN_ON(offset >= (reg_range*2/4)); + + /* set the termination flag*/ + kctx->reg_dump[offset] = REGISTER_DUMP_TERMINATION_FLAG; + kctx->reg_dump[offset + 1] = REGISTER_DUMP_TERMINATION_FLAG; + + dev_dbg(kctx->kbdev->dev, "kbase_job_fault_reg_snapshot_init:%d\n", + offset); + + return true; +} + +bool kbase_job_fault_get_reg_snapshot(struct kbase_context *kctx) +{ + int offset = 0; + + if (kctx->reg_dump == NULL) + return false; + + while (kctx->reg_dump[offset] != REGISTER_DUMP_TERMINATION_FLAG) { + kctx->reg_dump[offset+1] = + kbase_reg_read(kctx->kbdev, + kctx->reg_dump[offset], NULL); + offset += 2; + } + return true; +} + + +#endif diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c new file mode 100644 index 000000000000..e280322e223d --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -0,0 +1,413 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_DEVFREQ_THERMAL +#include +#endif + +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) +#include +#else /* Linux >= 3.13 */ +/* In 3.13 the OPP include header file, types, and functions were all + * renamed. Use the old filename for the include, and define the new names to + * the old, when an old kernel is detected. + */ +#include +#define dev_pm_opp opp +#define dev_pm_opp_get_voltage opp_get_voltage +#define dev_pm_opp_get_opp_count opp_get_opp_count +#define dev_pm_opp_find_freq_ceil opp_find_freq_ceil +#define dev_pm_opp_find_freq_floor opp_find_freq_floor +#endif /* Linux >= 3.13 */ + +/** + * opp_translate - Translate nominal OPP frequency from devicetree into real + * frequency and core mask + * @kbdev: Device pointer + * @freq: Nominal frequency + * @core_mask: Pointer to u64 to store core mask to + * + * Return: Real target frequency + * + * This function will only perform translation if an operating-points-v2-mali + * table is present in devicetree. If one is not present then it will return an + * untranslated frequency and all cores enabled. + */ +static unsigned long opp_translate(struct kbase_device *kbdev, + unsigned long freq, u64 *core_mask) +{ + int i; + + for (i = 0; i < kbdev->num_opps; i++) { + if (kbdev->opp_table[i].opp_freq == freq) { + *core_mask = kbdev->opp_table[i].core_mask; + return kbdev->opp_table[i].real_freq; + } + } + + /* Failed to find OPP - return all cores enabled & nominal frequency */ + *core_mask = kbdev->gpu_props.props.raw_props.shader_present; + + return freq; +} + +static int +kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct dev_pm_opp *opp; + unsigned long nominal_freq; + unsigned long freq = 0; + unsigned long voltage; + int err; + u64 core_mask; + + freq = *target_freq; + + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, &freq, flags); + voltage = dev_pm_opp_get_voltage(opp); + rcu_read_unlock(); + if (IS_ERR_OR_NULL(opp)) { + dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp)); + return PTR_ERR(opp); + } + + nominal_freq = freq; + + /* + * Only update if there is a change of frequency + */ + if (kbdev->current_nominal_freq == nominal_freq) { + *target_freq = nominal_freq; + return 0; + } + + freq = opp_translate(kbdev, nominal_freq, &core_mask); +#ifdef CONFIG_REGULATOR + if (kbdev->regulator && kbdev->current_voltage != voltage + && kbdev->current_freq < freq) { + err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + if (err) { + dev_err(dev, "Failed to increase voltage (%d)\n", err); + return err; + } + } +#endif + + err = clk_set_rate(kbdev->clock, freq); + if (err) { + dev_err(dev, "Failed to set clock %lu (target %lu)\n", + freq, *target_freq); + return err; + } + +#ifdef CONFIG_REGULATOR + if (kbdev->regulator && kbdev->current_voltage != voltage + && kbdev->current_freq > freq) { + err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + if (err) { + dev_err(dev, "Failed to decrease voltage (%d)\n", err); + return err; + } + } +#endif + + if (kbdev->pm.backend.ca_current_policy->id == + KBASE_PM_CA_POLICY_ID_DEVFREQ) + kbase_devfreq_set_core_mask(kbdev, core_mask); + + *target_freq = nominal_freq; + kbdev->current_voltage = voltage; + kbdev->current_nominal_freq = nominal_freq; + kbdev->current_freq = freq; + kbdev->current_core_mask = core_mask; + + KBASE_TLSTREAM_AUX_DEVFREQ_TARGET((u64)nominal_freq); + + kbase_pm_reset_dvfs_utilisation(kbdev); + + return err; +} + +static int +kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + *freq = kbdev->current_nominal_freq; + + return 0; +} + +static int +kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + stat->current_frequency = kbdev->current_nominal_freq; + + kbase_pm_get_dvfs_utilisation(kbdev, + &stat->total_time, &stat->busy_time); + + stat->private_data = NULL; + + return 0; +} + +static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev, + struct devfreq_dev_profile *dp) +{ + int count; + int i = 0; + unsigned long freq; + struct dev_pm_opp *opp; + + rcu_read_lock(); + count = dev_pm_opp_get_opp_count(kbdev->dev); + if (count < 0) { + rcu_read_unlock(); + return count; + } + rcu_read_unlock(); + + dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]), + GFP_KERNEL); + if (!dp->freq_table) + return -ENOMEM; + + rcu_read_lock(); + for (i = 0, freq = ULONG_MAX; i < count; i++, freq--) { + opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq); + if (IS_ERR(opp)) + break; + + dp->freq_table[i] = freq; + } + rcu_read_unlock(); + + if (count != i) + dev_warn(kbdev->dev, "Unable to enumerate all OPPs (%d!=%d\n", + count, i); + + dp->max_state = i; + + return 0; +} + +static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp = kbdev->devfreq->profile; + + kfree(dp->freq_table); +} + +static void kbase_devfreq_exit(struct device *dev) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + kbase_devfreq_term_freq_table(kbdev); +} + +static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev) +{ + struct device_node *opp_node = of_parse_phandle(kbdev->dev->of_node, + "operating-points-v2", 0); + struct device_node *node; + int i = 0; + int count; + + if (!opp_node) + return 0; + if (!of_device_is_compatible(opp_node, "operating-points-v2-mali")) + return 0; + + count = dev_pm_opp_get_opp_count(kbdev->dev); + kbdev->opp_table = kmalloc_array(count, + sizeof(struct kbase_devfreq_opp), GFP_KERNEL); + if (!kbdev->opp_table) + return -ENOMEM; + + for_each_available_child_of_node(opp_node, node) { + u64 core_mask; + u64 opp_freq, real_freq; + const void *core_count_p; + + if (of_property_read_u64(node, "opp-hz", &opp_freq)) { + dev_warn(kbdev->dev, "OPP is missing required opp-hz property\n"); + continue; + } + if (of_property_read_u64(node, "opp-hz-real", &real_freq)) + real_freq = opp_freq; + if (of_property_read_u64(node, "opp-core-mask", &core_mask)) + core_mask = + kbdev->gpu_props.props.raw_props.shader_present; + core_count_p = of_get_property(node, "opp-core-count", NULL); + if (core_count_p) { + u64 remaining_core_mask = + kbdev->gpu_props.props.raw_props.shader_present; + int core_count = be32_to_cpup(core_count_p); + + core_mask = 0; + + for (; core_count > 0; core_count--) { + int core = ffs(remaining_core_mask); + + if (!core) { + dev_err(kbdev->dev, "OPP has more cores than GPU\n"); + return -ENODEV; + } + + core_mask |= (1ull << (core-1)); + remaining_core_mask &= ~(1ull << (core-1)); + } + } + + if (!core_mask) { + dev_err(kbdev->dev, "OPP has invalid core mask of 0\n"); + return -ENODEV; + } + + kbdev->opp_table[i].opp_freq = opp_freq; + kbdev->opp_table[i].real_freq = real_freq; + kbdev->opp_table[i].core_mask = core_mask; + + dev_info(kbdev->dev, "OPP %d : opp_freq=%llu real_freq=%llu core_mask=%llx\n", + i, opp_freq, real_freq, core_mask); + + i++; + } + + kbdev->num_opps = i; + + return 0; +} + +int kbase_devfreq_init(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp; + int err; + + if (!kbdev->clock) { + dev_err(kbdev->dev, "Clock not available for devfreq\n"); + return -ENODEV; + } + + kbdev->current_freq = clk_get_rate(kbdev->clock); + kbdev->current_nominal_freq = kbdev->current_freq; + + dp = &kbdev->devfreq_profile; + + dp->initial_freq = kbdev->current_freq; + dp->polling_ms = 100; + dp->target = kbase_devfreq_target; + dp->get_dev_status = kbase_devfreq_status; + dp->get_cur_freq = kbase_devfreq_cur_freq; + dp->exit = kbase_devfreq_exit; + + if (kbase_devfreq_init_freq_table(kbdev, dp)) + return -EFAULT; + + err = kbase_devfreq_init_core_mask_table(kbdev); + if (err) + return err; + + kbdev->devfreq = devfreq_add_device(kbdev->dev, dp, + "simple_ondemand", NULL); + if (IS_ERR(kbdev->devfreq)) { + kbase_devfreq_term_freq_table(kbdev); + return PTR_ERR(kbdev->devfreq); + } + + /* devfreq_add_device only copies a few of kbdev->dev's fields, so + * set drvdata explicitly so IPA models can access kbdev. */ + dev_set_drvdata(&kbdev->devfreq->dev, kbdev); + + err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq); + if (err) { + dev_err(kbdev->dev, + "Failed to register OPP notifier (%d)\n", err); + goto opp_notifier_failed; + } + +#ifdef CONFIG_DEVFREQ_THERMAL + err = kbase_ipa_init(kbdev); + if (err) { + dev_err(kbdev->dev, "IPA initialization failed\n"); + goto cooling_failed; + } + + kbdev->devfreq_cooling = of_devfreq_cooling_register_power( + kbdev->dev->of_node, + kbdev->devfreq, + &kbase_ipa_power_model_ops); + if (IS_ERR_OR_NULL(kbdev->devfreq_cooling)) { + err = PTR_ERR(kbdev->devfreq_cooling); + dev_err(kbdev->dev, + "Failed to register cooling device (%d)\n", + err); + goto cooling_failed; + } +#endif + + return 0; + +#ifdef CONFIG_DEVFREQ_THERMAL +cooling_failed: + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); +#endif /* CONFIG_DEVFREQ_THERMAL */ +opp_notifier_failed: + if (devfreq_remove_device(kbdev->devfreq)) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; + + return err; +} + +void kbase_devfreq_term(struct kbase_device *kbdev) +{ + int err; + + dev_dbg(kbdev->dev, "Term Mali devfreq\n"); + +#ifdef CONFIG_DEVFREQ_THERMAL + if (kbdev->devfreq_cooling) + devfreq_cooling_unregister(kbdev->devfreq_cooling); + + kbase_ipa_term(kbdev); +#endif + + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); + + err = devfreq_remove_device(kbdev->devfreq); + if (err) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; + + kfree(kbdev->opp_table); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h new file mode 100644 index 000000000000..c0bf8b15b3bc --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h @@ -0,0 +1,24 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _BASE_DEVFREQ_H_ +#define _BASE_DEVFREQ_H_ + +int kbase_devfreq_init(struct kbase_device *kbdev); +void kbase_devfreq_term(struct kbase_device *kbdev); + +#endif /* _BASE_DEVFREQ_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c new file mode 100644 index 000000000000..dcdf15cdc3e8 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c @@ -0,0 +1,255 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * + */ +#include +#include +#include + +#include + +#if !defined(CONFIG_MALI_NO_MALI) + + +#ifdef CONFIG_DEBUG_FS + + +int kbase_io_history_resize(struct kbase_io_history *h, u16 new_size) +{ + struct kbase_io_access *old_buf; + struct kbase_io_access *new_buf; + unsigned long flags; + + if (!new_size) + goto out_err; /* The new size must not be 0 */ + + new_buf = vmalloc(new_size * sizeof(*h->buf)); + if (!new_buf) + goto out_err; + + spin_lock_irqsave(&h->lock, flags); + + old_buf = h->buf; + + /* Note: we won't bother with copying the old data over. The dumping + * logic wouldn't work properly as it relies on 'count' both as a + * counter and as an index to the buffer which would have changed with + * the new array. This is a corner case that we don't need to support. + */ + h->count = 0; + h->size = new_size; + h->buf = new_buf; + + spin_unlock_irqrestore(&h->lock, flags); + + vfree(old_buf); + + return 0; + +out_err: + return -1; +} + + +int kbase_io_history_init(struct kbase_io_history *h, u16 n) +{ + h->enabled = false; + spin_lock_init(&h->lock); + h->count = 0; + h->size = 0; + h->buf = NULL; + if (kbase_io_history_resize(h, n)) + return -1; + + return 0; +} + + +void kbase_io_history_term(struct kbase_io_history *h) +{ + vfree(h->buf); + h->buf = NULL; +} + + +/* kbase_io_history_add - add new entry to the register access history + * + * @h: Pointer to the history data structure + * @addr: Register address + * @value: The value that is either read from or written to the register + * @write: 1 if it's a register write, 0 if it's a read + */ +static void kbase_io_history_add(struct kbase_io_history *h, + void __iomem const *addr, u32 value, u8 write) +{ + struct kbase_io_access *io; + unsigned long flags; + + spin_lock_irqsave(&h->lock, flags); + + io = &h->buf[h->count % h->size]; + io->addr = (uintptr_t)addr | write; + io->value = value; + ++h->count; + /* If count overflows, move the index by the buffer size so the entire + * buffer will still be dumped later */ + if (unlikely(!h->count)) + h->count = h->size; + + spin_unlock_irqrestore(&h->lock, flags); +} + + +void kbase_io_history_dump(struct kbase_device *kbdev) +{ + struct kbase_io_history *const h = &kbdev->io_history; + u16 i; + size_t iters; + unsigned long flags; + + if (!unlikely(h->enabled)) + return; + + spin_lock_irqsave(&h->lock, flags); + + dev_err(kbdev->dev, "Register IO History:"); + iters = (h->size > h->count) ? h->count : h->size; + dev_err(kbdev->dev, "Last %zu register accesses of %zu total:\n", iters, + h->count); + for (i = 0; i < iters; ++i) { + struct kbase_io_access *io = + &h->buf[(h->count - iters + i) % h->size]; + char const access = (io->addr & 1) ? 'w' : 'r'; + + dev_err(kbdev->dev, "%6i: %c: reg 0x%p val %08x\n", i, access, + (void *)(io->addr & ~0x1), io->value); + } + + spin_unlock_irqrestore(&h->lock, flags); +} + + +#endif /* CONFIG_DEBUG_FS */ + + +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, + struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + + writel(value, kbdev->reg + offset); + +#ifdef CONFIG_DEBUG_FS + if (unlikely(kbdev->io_history.enabled)) + kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset, + value, 1); +#endif /* CONFIG_DEBUG_FS */ + dev_dbg(kbdev->dev, "w: reg %04x val %08x", offset, value); + + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_WRITE, offset, + value); +} + +KBASE_EXPORT_TEST_API(kbase_reg_write); + +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, + struct kbase_context *kctx) +{ + u32 val; + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + + val = readl(kbdev->reg + offset); + +#ifdef CONFIG_DEBUG_FS + if (unlikely(kbdev->io_history.enabled)) + kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset, + val, 0); +#endif /* CONFIG_DEBUG_FS */ + dev_dbg(kbdev->dev, "r: reg %04x val %08x", offset, val); + + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_READ, offset, val); + return val; +} + +KBASE_EXPORT_TEST_API(kbase_reg_read); +#endif /* !defined(CONFIG_MALI_NO_MALI) */ + +/** + * kbase_report_gpu_fault - Report a GPU fault. + * @kbdev: Kbase device pointer + * @multiple: Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS + * was also set + * + * This function is called from the interrupt handler when a GPU fault occurs. + * It reports the details of the fault using dev_warn(). + */ +static void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple) +{ + u32 status; + u64 address; + + status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL); + address = (u64) kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_FAULTADDRESS_HI), NULL) << 32; + address |= kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_FAULTADDRESS_LO), NULL); + + dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx", + status & 0xFF, + kbase_exception_name(kbdev, status), + address); + if (multiple) + dev_warn(kbdev->dev, "There were multiple GPU faults - some have not been reported\n"); +} + +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) +{ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, NULL, 0u, val); + if (val & GPU_FAULT) + kbase_report_gpu_fault(kbdev, val & MULTIPLE_GPU_FAULTS); + + if (val & RESET_COMPLETED) + kbase_pm_reset_done(kbdev); + + if (val & PRFCNT_SAMPLE_COMPLETED) + kbase_instr_hwcnt_sample_done(kbdev); + + if (val & CLEAN_CACHES_COMPLETED) + kbase_clean_caches_done(kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, val); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val, NULL); + + /* kbase_pm_check_transitions must be called after the IRQ has been + * cleared. This is because it might trigger further power transitions + * and we don't want to miss the interrupt raised to notify us that + * these further transitions have finished. + */ + if (val & POWER_CHANGED_ALL) + kbase_pm_power_changed(kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, NULL, 0u, val); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_internal.h new file mode 100644 index 000000000000..5b20445932fb --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_internal.h @@ -0,0 +1,67 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Backend-specific HW access device APIs + */ + +#ifndef _KBASE_DEVICE_INTERNAL_H_ +#define _KBASE_DEVICE_INTERNAL_H_ + +/** + * kbase_reg_write - write to GPU register + * @kbdev: Kbase device pointer + * @offset: Offset of register + * @value: Value to write + * @kctx: Kbase context pointer. May be NULL + * + * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false). If + * @kctx is not NULL then the caller must ensure it is scheduled (@kctx->as_nr + * != KBASEP_AS_NR_INVALID). + */ +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, + struct kbase_context *kctx); + +/** + * kbase_reg_read - read from GPU register + * @kbdev: Kbase device pointer + * @offset: Offset of register + * @kctx: Kbase context pointer. May be NULL + * + * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false). If + * @kctx is not NULL then the caller must ensure it is scheduled (@kctx->as_nr + * != KBASEP_AS_NR_INVALID). + * + * Return: Value in desired register + */ +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, + struct kbase_context *kctx); + + +/** + * kbase_gpu_interrupt - GPU interrupt handler + * @kbdev: Kbase device pointer + * @val: The value of the GPU IRQ status register which triggered the call + * + * This function is called from the interrupt handler when a GPU irq is to be + * handled. + */ +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val); + +#endif /* _KBASE_DEVICE_INTERNAL_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c new file mode 100644 index 000000000000..3b78100ec6df --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c @@ -0,0 +1,123 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend APIs + */ +#include +#include +#include +#include +#include +#include + +int kbase_backend_early_init(struct kbase_device *kbdev) +{ + int err; + + err = kbasep_platform_device_init(kbdev); + if (err) + return err; + + /* Ensure we can access the GPU registers */ + kbase_pm_register_access_enable(kbdev); + + /* Find out GPU properties based on the GPU feature registers */ + kbase_gpuprops_set(kbdev); + + /* We're done accessing the GPU registers for now. */ + kbase_pm_register_access_disable(kbdev); + + err = kbase_install_interrupts(kbdev); + if (err) + goto fail_interrupts; + + err = kbase_hwaccess_pm_init(kbdev); + if (err) + goto fail_pm; + + return 0; + +fail_pm: + kbase_release_interrupts(kbdev); +fail_interrupts: + kbasep_platform_device_term(kbdev); + + return err; +} + +void kbase_backend_early_term(struct kbase_device *kbdev) +{ + kbase_hwaccess_pm_term(kbdev); + kbase_release_interrupts(kbdev); + kbasep_platform_device_term(kbdev); +} + +int kbase_backend_late_init(struct kbase_device *kbdev) +{ + int err; + + err = kbase_hwaccess_pm_powerup(kbdev, PM_HW_ISSUES_DETECT); + if (err) + return err; + + err = kbase_backend_timer_init(kbdev); + if (err) + goto fail_timer; + +#ifdef CONFIG_MALI_DEBUG +#ifndef CONFIG_MALI_NO_MALI + if (kbasep_common_test_interrupt_handlers(kbdev) != 0) { + dev_err(kbdev->dev, "Interrupt assigment check failed.\n"); + err = -EINVAL; + goto fail_interrupt_test; + } +#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_DEBUG */ + + err = kbase_job_slot_init(kbdev); + if (err) + goto fail_job_slot; + + init_waitqueue_head(&kbdev->hwaccess.backend.reset_wait); + + return 0; + +fail_job_slot: + +#ifdef CONFIG_MALI_DEBUG +#ifndef CONFIG_MALI_NO_MALI +fail_interrupt_test: +#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_DEBUG */ + + kbase_backend_timer_term(kbdev); +fail_timer: + kbase_hwaccess_pm_halt(kbdev); + + return err; +} + +void kbase_backend_late_term(struct kbase_device *kbdev) +{ + kbase_job_slot_halt(kbdev); + kbase_job_slot_term(kbdev); + kbase_backend_timer_term(kbdev); + kbase_hwaccess_pm_halt(kbdev); +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c new file mode 100644 index 000000000000..b395325b556b --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c @@ -0,0 +1,110 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel property query backend APIs + */ + +#include +#include +#include +#include + +void kbase_backend_gpuprops_get(struct kbase_device *kbdev, + struct kbase_gpuprops_regdump *regdump) +{ + int i; + + /* Fill regdump with the content of the relevant registers */ + regdump->gpu_id = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID), NULL); + + regdump->l2_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_FEATURES), NULL); + regdump->suspend_size = kbase_reg_read(kbdev, + GPU_CONTROL_REG(SUSPEND_SIZE), NULL); + regdump->tiler_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_FEATURES), NULL); + regdump->mem_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(MEM_FEATURES), NULL); + regdump->mmu_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(MMU_FEATURES), NULL); + regdump->as_present = kbase_reg_read(kbdev, + GPU_CONTROL_REG(AS_PRESENT), NULL); + regdump->js_present = kbase_reg_read(kbdev, + GPU_CONTROL_REG(JS_PRESENT), NULL); + + for (i = 0; i < GPU_MAX_JOB_SLOTS; i++) + regdump->js_features[i] = kbase_reg_read(kbdev, + GPU_CONTROL_REG(JS_FEATURES_REG(i)), NULL); + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + regdump->texture_features[i] = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TEXTURE_FEATURES_REG(i)), NULL); + + regdump->thread_max_threads = kbase_reg_read(kbdev, + GPU_CONTROL_REG(THREAD_MAX_THREADS), NULL); + regdump->thread_max_workgroup_size = kbase_reg_read(kbdev, + GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE), + NULL); + regdump->thread_max_barrier_size = kbase_reg_read(kbdev, + GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE), NULL); + regdump->thread_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(THREAD_FEATURES), NULL); + + regdump->shader_present_lo = kbase_reg_read(kbdev, + GPU_CONTROL_REG(SHADER_PRESENT_LO), NULL); + regdump->shader_present_hi = kbase_reg_read(kbdev, + GPU_CONTROL_REG(SHADER_PRESENT_HI), NULL); + + regdump->tiler_present_lo = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_PRESENT_LO), NULL); + regdump->tiler_present_hi = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_PRESENT_HI), NULL); + + regdump->l2_present_lo = kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_PRESENT_LO), NULL); + regdump->l2_present_hi = kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_PRESENT_HI), NULL); + + regdump->stack_present_lo = kbase_reg_read(kbdev, + GPU_CONTROL_REG(STACK_PRESENT_LO), NULL); + regdump->stack_present_hi = kbase_reg_read(kbdev, + GPU_CONTROL_REG(STACK_PRESENT_HI), NULL); +} + +void kbase_backend_gpuprops_get_features(struct kbase_device *kbdev, + struct kbase_gpuprops_regdump *regdump) +{ + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_COHERENCY_REG)) { + /* Ensure we can access the GPU registers */ + kbase_pm_register_access_enable(kbdev); + + regdump->coherency_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(COHERENCY_FEATURES), NULL); + + /* We're done accessing the GPU registers for now. */ + kbase_pm_register_access_disable(kbdev); + } else { + /* Pre COHERENCY_FEATURES we only supported ACE_LITE */ + regdump->coherency_features = + COHERENCY_FEATURE_BIT(COHERENCY_NONE) | + COHERENCY_FEATURE_BIT(COHERENCY_ACE_LITE); + } +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c new file mode 100644 index 000000000000..7ad309e8d7f4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c @@ -0,0 +1,492 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * GPU backend instrumentation APIs. + */ + +#include +#include +#include +#include +#include +#include + +/** + * kbasep_instr_hwcnt_cacheclean - Issue Cache Clean & Invalidate command to + * hardware + * + * @kbdev: Kbase device + */ +static void kbasep_instr_hwcnt_cacheclean(struct kbase_device *kbdev) +{ + unsigned long flags; + unsigned long pm_flags; + u32 irq_mask; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_REQUEST_CLEAN); + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), + irq_mask | CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); + + /* clean&invalidate the caches so we're sure the mmu tables for the dump + * buffer is valid */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CLEAN_INV_CACHES, NULL); + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_CLEANING; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbase_uk_hwcnt_setup *setup) +{ + unsigned long flags, pm_flags; + int err = -EINVAL; + u32 irq_mask; + int ret; + u64 shader_cores_needed; + u32 prfcnt_config; + + shader_cores_needed = kbase_pm_get_present_cores(kbdev, + KBASE_PM_CORE_SHADER); + + /* alignment failure */ + if ((setup->dump_buffer == 0ULL) || (setup->dump_buffer & (2048 - 1))) + goto out_err; + + /* Override core availability policy to ensure all cores are available + */ + kbase_pm_ca_instr_enable(kbdev); + + /* Request the cores early on synchronously - we'll release them on any + * errors (e.g. instrumentation already active) */ + kbase_pm_request_cores_sync(kbdev, true, shader_cores_needed); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is already enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out_unrequest_cores; + } + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | + PRFCNT_SAMPLE_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); + + /* In use, this context is the owner */ + kbdev->hwcnt.kctx = kctx; + /* Remember the dump address so we can reprogram it later */ + kbdev->hwcnt.addr = setup->dump_buffer; + + /* Request the clean */ + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + kbdev->hwcnt.backend.triggered = 0; + /* Clean&invalidate the caches so we're sure the mmu tables for the dump + * buffer is valid */ + ret = queue_work(kbdev->hwcnt.backend.cache_clean_wq, + &kbdev->hwcnt.backend.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Wait for cacheclean to complete */ + wait_event(kbdev->hwcnt.backend.wait, + kbdev->hwcnt.backend.triggered != 0); + + KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_IDLE); + + kbase_pm_request_l2_caches(kbdev); + + /* Configure */ + prfcnt_config = kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT; +#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY + { + u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + u32 product_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) + >> GPU_ID_VERSION_PRODUCT_ID_SHIFT; + int arch_v6 = GPU_ID_IS_NEW_FORMAT(product_id); + + if (arch_v6) + prfcnt_config |= 1 << PRFCNT_CONFIG_SETSELECT_SHIFT; + } +#endif + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), + prfcnt_config | PRFCNT_CONFIG_MODE_OFF, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), + setup->dump_buffer & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), + setup->dump_buffer >> 32, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), + setup->jm_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), + setup->shader_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), + setup->mmu_l2_bm, kctx); + /* Due to PRLAM-8186 we need to disable the Tiler before we enable the + * HW counter dump. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, + kctx); + else + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), + setup->tiler_bm, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), + prfcnt_config | PRFCNT_CONFIG_MODE_MANUAL, kctx); + + /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), + setup->tiler_bm, kctx); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.backend.triggered = 1; + wake_up(&kbdev->hwcnt.backend.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + err = 0; + + dev_dbg(kbdev->dev, "HW counters dumping set-up for context %p", kctx); + return err; + out_unrequest_cores: + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_unrequest_cores(kbdev, true, shader_cores_needed); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + out_err: + return err; +} + +int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx) +{ + unsigned long flags, pm_flags; + int err = -EINVAL; + u32 irq_mask; + struct kbase_device *kbdev = kctx->kbdev; + + while (1) { + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is not enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.kctx != kctx) { + /* Instrumentation has been setup for another context */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_IDLE) + break; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ongoing dump/setup - wait for its completion */ + wait_event(kbdev->hwcnt.backend.wait, + kbdev->hwcnt.backend.triggered != 0); + } + + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED; + kbdev->hwcnt.backend.triggered = 0; + + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), + irq_mask & ~PRFCNT_SAMPLE_COMPLETED, NULL); + + /* Disable the counters */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), 0, kctx); + + kbdev->hwcnt.kctx = NULL; + kbdev->hwcnt.addr = 0ULL; + + kbase_pm_ca_instr_disable(kbdev); + + kbase_pm_unrequest_cores(kbdev, true, + kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER)); + + kbase_pm_release_l2_caches(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p", + kctx); + + err = 0; + + out: + return err; +} + +int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx) +{ + unsigned long flags; + int err = -EINVAL; + struct kbase_device *kbdev = kctx->kbdev; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.kctx != kctx) { + /* The instrumentation has been setup for another context */ + goto unlock; + } + + if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_IDLE) { + /* HW counters are disabled or another dump is ongoing, or we're + * resetting */ + goto unlock; + } + + kbdev->hwcnt.backend.triggered = 0; + + /* Mark that we're dumping - the PF handler can signal that we faulted + */ + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DUMPING; + + /* Reconfigure the dump address */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), + kbdev->hwcnt.addr & 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), + kbdev->hwcnt.addr >> 32, NULL); + + /* Start dumping */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL, NULL, + kbdev->hwcnt.addr, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_PRFCNT_SAMPLE, kctx); + + dev_dbg(kbdev->dev, "HW counters dumping done for context %p", kctx); + + err = 0; + + unlock: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_request_dump); + +bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, + bool * const success) +{ + unsigned long flags; + bool complete = false; + struct kbase_device *kbdev = kctx->kbdev; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_IDLE) { + *success = true; + complete = true; + } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { + *success = false; + complete = true; + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + return complete; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete); + +void kbasep_cache_clean_worker(struct work_struct *data) +{ + struct kbase_device *kbdev; + unsigned long flags; + + kbdev = container_of(data, struct kbase_device, + hwcnt.backend.cache_clean_work); + + mutex_lock(&kbdev->cacheclean_lock); + kbasep_instr_hwcnt_cacheclean(kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Wait for our condition, and any reset to complete */ + while (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_CLEANING) { + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.backend.cache_clean_wait, + kbdev->hwcnt.backend.state != + KBASE_INSTR_STATE_CLEANING); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_CLEANED); + + /* All finished and idle */ + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.backend.triggered = 1; + wake_up(&kbdev->hwcnt.backend.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + mutex_unlock(&kbdev->cacheclean_lock); +} + +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { + kbdev->hwcnt.backend.triggered = 1; + wake_up(&kbdev->hwcnt.backend.wait); + } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING) { + int ret; + /* Always clean and invalidate the cache after a successful dump + */ + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + ret = queue_work(kbdev->hwcnt.backend.cache_clean_wq, + &kbdev->hwcnt.backend.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +void kbase_clean_caches_done(struct kbase_device *kbdev) +{ + u32 irq_mask; + + if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_DISABLED) { + unsigned long flags; + unsigned long pm_flags; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), + NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), + irq_mask & ~CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); + + /* Wakeup... */ + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_CLEANING) { + /* Only wake if we weren't resetting */ + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_CLEANED; + wake_up(&kbdev->hwcnt.backend.cache_clean_wait); + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + } +} + +int kbase_instr_hwcnt_wait_for_dump(struct kbase_context *kctx) +{ + struct kbase_device *kbdev = kctx->kbdev; + unsigned long flags; + int err; + + /* Wait for dump & cacheclean to complete */ + wait_event(kbdev->hwcnt.backend.wait, + kbdev->hwcnt.backend.triggered != 0); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { + err = -EINVAL; + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; + } else { + /* Dump done */ + KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_IDLE); + err = 0; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + return err; +} + +int kbase_instr_hwcnt_clear(struct kbase_context *kctx) +{ + unsigned long flags; + int err = -EINVAL; + struct kbase_device *kbdev = kctx->kbdev; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + /* Check it's the context previously set up and we're not already + * dumping */ + if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.backend.state != + KBASE_INSTR_STATE_IDLE) + goto out; + + /* Clear the counters */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_PRFCNT_CLEAR, kctx); + + err = 0; + +out: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear); + +int kbase_instr_backend_init(struct kbase_device *kbdev) +{ + int ret = 0; + + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED; + + init_waitqueue_head(&kbdev->hwcnt.backend.wait); + init_waitqueue_head(&kbdev->hwcnt.backend.cache_clean_wait); + INIT_WORK(&kbdev->hwcnt.backend.cache_clean_work, + kbasep_cache_clean_worker); + kbdev->hwcnt.backend.triggered = 0; + + kbdev->hwcnt.backend.cache_clean_wq = + alloc_workqueue("Mali cache cleaning workqueue", 0, 1); + if (NULL == kbdev->hwcnt.backend.cache_clean_wq) + ret = -EINVAL; + + return ret; +} + +void kbase_instr_backend_term(struct kbase_device *kbdev) +{ + destroy_workqueue(kbdev->hwcnt.backend.cache_clean_wq); +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h new file mode 100644 index 000000000000..4794672da8f0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h @@ -0,0 +1,58 @@ +/* + * + * (C) COPYRIGHT 2014, 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Backend-specific instrumentation definitions + */ + +#ifndef _KBASE_INSTR_DEFS_H_ +#define _KBASE_INSTR_DEFS_H_ + +/* + * Instrumentation State Machine States + */ +enum kbase_instr_state { + /* State where instrumentation is not active */ + KBASE_INSTR_STATE_DISABLED = 0, + /* State machine is active and ready for a command. */ + KBASE_INSTR_STATE_IDLE, + /* Hardware is currently dumping a frame. */ + KBASE_INSTR_STATE_DUMPING, + /* We've requested a clean to occur on a workqueue */ + KBASE_INSTR_STATE_REQUEST_CLEAN, + /* Hardware is currently cleaning and invalidating caches. */ + KBASE_INSTR_STATE_CLEANING, + /* Cache clean completed, and either a) a dump is complete, or + * b) instrumentation can now be setup. */ + KBASE_INSTR_STATE_CLEANED, + /* An error has occured during DUMPING (page fault). */ + KBASE_INSTR_STATE_FAULT +}; + +/* Structure used for instrumentation and HW counters dumping */ +struct kbase_instr_backend { + wait_queue_head_t wait; + int triggered; + + enum kbase_instr_state state; + wait_queue_head_t cache_clean_wait; + struct workqueue_struct *cache_clean_wq; + struct work_struct cache_clean_work; +}; + +#endif /* _KBASE_INSTR_DEFS_H_ */ + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_internal.h new file mode 100644 index 000000000000..e96aeae786e1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_internal.h @@ -0,0 +1,45 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Backend-specific HW access instrumentation APIs + */ + +#ifndef _KBASE_INSTR_INTERNAL_H_ +#define _KBASE_INSTR_INTERNAL_H_ + +/** + * kbasep_cache_clean_worker() - Workqueue for handling cache cleaning + * @data: a &struct work_struct + */ +void kbasep_cache_clean_worker(struct work_struct *data); + +/** + * kbase_clean_caches_done() - Cache clean interrupt received + * @kbdev: Kbase device + */ +void kbase_clean_caches_done(struct kbase_device *kbdev); + +/** + * kbase_instr_hwcnt_sample_done() - Dump complete interrupt received + * @kbdev: Kbase device + */ +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev); + +#endif /* _KBASE_INSTR_INTERNAL_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_internal.h new file mode 100644 index 000000000000..8781561e73d0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_internal.h @@ -0,0 +1,39 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Backend specific IRQ APIs + */ + +#ifndef _KBASE_IRQ_INTERNAL_H_ +#define _KBASE_IRQ_INTERNAL_H_ + +int kbase_install_interrupts(struct kbase_device *kbdev); + +void kbase_release_interrupts(struct kbase_device *kbdev); + +/** + * kbase_synchronize_irqs - Ensure that all IRQ handlers have completed + * execution + * @kbdev: The kbase device + */ +void kbase_synchronize_irqs(struct kbase_device *kbdev); + +int kbasep_common_test_interrupt_handlers( + struct kbase_device * const kbdev); + +#endif /* _KBASE_IRQ_INTERNAL_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c new file mode 100644 index 000000000000..8416b80e8b77 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c @@ -0,0 +1,469 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include + +#include + +#if !defined(CONFIG_MALI_NO_MALI) + +/* GPU IRQ Tags */ +#define JOB_IRQ_TAG 0 +#define MMU_IRQ_TAG 1 +#define GPU_IRQ_TAG 2 + +static void *kbase_tag(void *ptr, u32 tag) +{ + return (void *)(((uintptr_t) ptr) | tag); +} + +static void *kbase_untag(void *ptr) +{ + return (void *)(((uintptr_t) ptr) & ~3); +} + +static irqreturn_t kbase_job_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!kbdev->pm.backend.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.backend.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_job_done(kbdev, val); + + return IRQ_HANDLED; +} + +KBASE_EXPORT_TEST_API(kbase_job_irq_handler); + +static irqreturn_t kbase_mmu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!kbdev->pm.backend.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return IRQ_NONE; + } + + atomic_inc(&kbdev->faults_pending); + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.backend.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!val) { + atomic_dec(&kbdev->faults_pending); + return IRQ_NONE; + } + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_mmu_interrupt(kbdev, val); + + atomic_dec(&kbdev->faults_pending); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!kbdev->pm.backend.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.backend.driver_ready_for_irqs) + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_gpu_interrupt(kbdev, val); + + return IRQ_HANDLED; +} + +KBASE_EXPORT_TEST_API(kbase_gpu_irq_handler); + +static irq_handler_t kbase_handler_table[] = { + [JOB_IRQ_TAG] = kbase_job_irq_handler, + [MMU_IRQ_TAG] = kbase_mmu_irq_handler, + [GPU_IRQ_TAG] = kbase_gpu_irq_handler, +}; + +#ifdef CONFIG_MALI_DEBUG +#define JOB_IRQ_HANDLER JOB_IRQ_TAG +#define MMU_IRQ_HANDLER MMU_IRQ_TAG +#define GPU_IRQ_HANDLER GPU_IRQ_TAG + +/** + * kbase_set_custom_irq_handler - Set a custom IRQ handler + * @kbdev: Device for which the handler is to be registered + * @custom_handler: Handler to be registered + * @irq_type: Interrupt type + * + * Registers given interrupt handler for requested interrupt type + * In the case where irq handler is not specified, the default handler shall be + * registered + * + * Return: 0 case success, error code otherwise + */ +int kbase_set_custom_irq_handler(struct kbase_device *kbdev, + irq_handler_t custom_handler, + int irq_type) +{ + int result = 0; + irq_handler_t requested_irq_handler = NULL; + + KBASE_DEBUG_ASSERT((JOB_IRQ_HANDLER <= irq_type) && + (GPU_IRQ_HANDLER >= irq_type)); + + /* Release previous handler */ + if (kbdev->irqs[irq_type].irq) + free_irq(kbdev->irqs[irq_type].irq, kbase_tag(kbdev, irq_type)); + + requested_irq_handler = (NULL != custom_handler) ? custom_handler : + kbase_handler_table[irq_type]; + + if (0 != request_irq(kbdev->irqs[irq_type].irq, + requested_irq_handler, + kbdev->irqs[irq_type].flags | IRQF_SHARED, + dev_name(kbdev->dev), kbase_tag(kbdev, irq_type))) { + result = -EINVAL; + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", + kbdev->irqs[irq_type].irq, irq_type); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_set_custom_irq_handler); + +/* test correct interrupt assigment and reception by cpu */ +struct kbasep_irq_test { + struct hrtimer timer; + wait_queue_head_t wait; + int triggered; + u32 timeout; +}; + +static struct kbasep_irq_test kbasep_irq_test_data; + +#define IRQ_TEST_TIMEOUT 500 + +static irqreturn_t kbase_job_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!kbdev->pm.backend.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_mmu_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!kbdev->pm.backend.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static enum hrtimer_restart kbasep_test_interrupt_timeout(struct hrtimer *timer) +{ + struct kbasep_irq_test *test_data = container_of(timer, + struct kbasep_irq_test, timer); + + test_data->timeout = 1; + test_data->triggered = 1; + wake_up(&test_data->wait); + return HRTIMER_NORESTART; +} + +static int kbasep_common_test_interrupt( + struct kbase_device * const kbdev, u32 tag) +{ + int err = 0; + irq_handler_t test_handler; + + u32 old_mask_val; + u16 mask_offset; + u16 rawstat_offset; + + switch (tag) { + case JOB_IRQ_TAG: + test_handler = kbase_job_irq_test_handler; + rawstat_offset = JOB_CONTROL_REG(JOB_IRQ_RAWSTAT); + mask_offset = JOB_CONTROL_REG(JOB_IRQ_MASK); + break; + case MMU_IRQ_TAG: + test_handler = kbase_mmu_irq_test_handler; + rawstat_offset = MMU_REG(MMU_IRQ_RAWSTAT); + mask_offset = MMU_REG(MMU_IRQ_MASK); + break; + case GPU_IRQ_TAG: + /* already tested by pm_driver - bail out */ + default: + return 0; + } + + /* store old mask */ + old_mask_val = kbase_reg_read(kbdev, mask_offset, NULL); + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + if (kbdev->irqs[tag].irq) { + /* release original handler and install test handler */ + if (kbase_set_custom_irq_handler(kbdev, test_handler, tag) != 0) { + err = -EINVAL; + } else { + kbasep_irq_test_data.timeout = 0; + hrtimer_init(&kbasep_irq_test_data.timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbasep_irq_test_data.timer.function = + kbasep_test_interrupt_timeout; + + /* trigger interrupt */ + kbase_reg_write(kbdev, mask_offset, 0x1, NULL); + kbase_reg_write(kbdev, rawstat_offset, 0x1, NULL); + + hrtimer_start(&kbasep_irq_test_data.timer, + HR_TIMER_DELAY_MSEC(IRQ_TEST_TIMEOUT), + HRTIMER_MODE_REL); + + wait_event(kbasep_irq_test_data.wait, + kbasep_irq_test_data.triggered != 0); + + if (kbasep_irq_test_data.timeout != 0) { + dev_err(kbdev->dev, "Interrupt %d (index %d) didn't reach CPU.\n", + kbdev->irqs[tag].irq, tag); + err = -EINVAL; + } else { + dev_dbg(kbdev->dev, "Interrupt %d (index %d) reached CPU.\n", + kbdev->irqs[tag].irq, tag); + } + + hrtimer_cancel(&kbasep_irq_test_data.timer); + kbasep_irq_test_data.triggered = 0; + + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + /* release test handler */ + free_irq(kbdev->irqs[tag].irq, kbase_tag(kbdev, tag)); + } + + /* restore original interrupt */ + if (request_irq(kbdev->irqs[tag].irq, kbase_handler_table[tag], + kbdev->irqs[tag].flags | IRQF_SHARED, + dev_name(kbdev->dev), kbase_tag(kbdev, tag))) { + dev_err(kbdev->dev, "Can't restore original interrupt %d (index %d)\n", + kbdev->irqs[tag].irq, tag); + err = -EINVAL; + } + } + /* restore old mask */ + kbase_reg_write(kbdev, mask_offset, old_mask_val, NULL); + + return err; +} + +int kbasep_common_test_interrupt_handlers( + struct kbase_device * const kbdev) +{ + int err; + + init_waitqueue_head(&kbasep_irq_test_data.wait); + kbasep_irq_test_data.triggered = 0; + + /* A suspend won't happen during startup/insmod */ + kbase_pm_context_active(kbdev); + + err = kbasep_common_test_interrupt(kbdev, JOB_IRQ_TAG); + if (err) { + dev_err(kbdev->dev, "Interrupt JOB_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + err = kbasep_common_test_interrupt(kbdev, MMU_IRQ_TAG); + if (err) { + dev_err(kbdev->dev, "Interrupt MMU_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + dev_dbg(kbdev->dev, "Interrupts are correctly assigned.\n"); + + out: + kbase_pm_context_idle(kbdev); + + return err; +} +#endif /* CONFIG_MALI_DEBUG */ + +int kbase_install_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + int err; + u32 i; + + for (i = 0; i < nr; i++) { + err = request_irq(kbdev->irqs[i].irq, kbase_handler_table[i], + kbdev->irqs[i].flags | IRQF_SHARED, + dev_name(kbdev->dev), + kbase_tag(kbdev, i)); + if (err) { + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", + kbdev->irqs[i].irq, i); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + goto release; + } + } + + return 0; + + release: + while (i-- > 0) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + + return err; +} + +void kbase_release_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + } +} + +void kbase_synchronize_irqs(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + synchronize_irq(kbdev->irqs[i].irq); + } +} + +#endif /* !defined(CONFIG_MALI_NO_MALI) */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_as.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_as.c new file mode 100644 index 000000000000..c660c80341f4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_as.c @@ -0,0 +1,235 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register backend context / address space management + */ + +#include +#include +#include + +/** + * assign_and_activate_kctx_addr_space - Assign an AS to a context + * @kbdev: Kbase device + * @kctx: Kbase context + * @current_as: Address Space to assign + * + * Assign an Address Space (AS) to a context, and add the context to the Policy. + * + * This includes + * setting up the global runpool_irq structure and the context on the AS, + * Activating the MMU on the AS, + * Allowing jobs to be submitted on the AS. + * + * Context: + * kbasep_js_kctx_info.jsctx_mutex held, + * kbasep_js_device_data.runpool_mutex held, + * AS transaction mutex held, + * Runpool IRQ lock held + */ +static void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbase_as *current_as) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* Attribute handling */ + kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx); + + /* Allow it to run jobs */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + + kbase_js_runpool_inc_context_count(kbdev, kctx); +} + +bool kbase_backend_use_ctx_sched(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + int i; + + if (kbdev->hwaccess.active_kctx == kctx) { + /* Context is already active */ + return true; + } + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + if (kbdev->as_to_kctx[i] == kctx) { + /* Context already has ASID - mark as active */ + return true; + } + } + + /* Context does not have address space assigned */ + return false; +} + +void kbase_backend_release_ctx_irq(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + int as_nr = kctx->as_nr; + + if (as_nr == KBASEP_AS_NR_INVALID) { + WARN(1, "Attempting to release context without ASID\n"); + return; + } + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (atomic_read(&kctx->refcount) != 1) { + WARN(1, "Attempting to release active ASID\n"); + return; + } + + kbasep_js_clear_submit_allowed(&kbdev->js_data, kctx); + + kbase_ctx_sched_release_ctx(kctx); + kbase_js_runpool_dec_context_count(kbdev, kctx); +} + +void kbase_backend_release_ctx_noirq(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ +} + +int kbase_backend_find_and_release_free_address_space( + struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + unsigned long flags; + int i; + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + struct kbasep_js_kctx_info *as_js_kctx_info; + struct kbase_context *as_kctx; + + as_kctx = kbdev->as_to_kctx[i]; + as_js_kctx_info = &as_kctx->jctx.sched_info; + + /* Don't release privileged or active contexts, or contexts with + * jobs running. + * Note that a context will have at least 1 reference (which + * was previously taken by kbasep_js_schedule_ctx()) until + * descheduled. + */ + if (as_kctx && !kbase_ctx_flag(as_kctx, KCTX_PRIVILEGED) && + atomic_read(&as_kctx->refcount) == 1) { + if (!kbasep_js_runpool_retain_ctx_nolock(kbdev, + as_kctx)) { + WARN(1, "Failed to retain active context\n"); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, + flags); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + return KBASEP_AS_NR_INVALID; + } + + kbasep_js_clear_submit_allowed(js_devdata, as_kctx); + + /* Drop and retake locks to take the jsctx_mutex on the + * context we're about to release without violating lock + * ordering + */ + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + + /* Release context from address space */ + mutex_lock(&as_js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + kbasep_js_runpool_release_ctx_nolock(kbdev, as_kctx); + + if (!kbase_ctx_flag(as_kctx, KCTX_SCHEDULED)) { + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, + as_kctx, + true); + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex); + + return i; + } + + /* Context was retained while locks were dropped, + * continue looking for free AS */ + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + } + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + return KBASEP_AS_NR_INVALID; +} + +bool kbase_backend_use_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx, + int as_nr) +{ + struct kbasep_js_device_data *js_devdata; + struct kbase_as *new_address_space = NULL; + + js_devdata = &kbdev->js_data; + + if (kbdev->hwaccess.active_kctx == kctx) { + WARN(1, "Context is already scheduled in\n"); + return false; + } + + new_address_space = &kbdev->as[as_nr]; + + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&kbdev->mmu_hw_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + assign_and_activate_kctx_addr_space(kbdev, kctx, new_address_space); + + if (kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) { + /* We need to retain it to keep the corresponding address space + */ + kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + } + + return true; +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_defs.h new file mode 100644 index 000000000000..08a7400e66d5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_defs.h @@ -0,0 +1,123 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend specific definitions + */ + +#ifndef _KBASE_HWACCESS_GPU_DEFS_H_ +#define _KBASE_HWACCESS_GPU_DEFS_H_ + +/* SLOT_RB_SIZE must be < 256 */ +#define SLOT_RB_SIZE 2 +#define SLOT_RB_MASK (SLOT_RB_SIZE - 1) + +/** + * struct rb_entry - Ringbuffer entry + * @katom: Atom associated with this entry + */ +struct rb_entry { + struct kbase_jd_atom *katom; +}; + +/** + * struct slot_rb - Slot ringbuffer + * @entries: Ringbuffer entries + * @last_context: The last context to submit a job on this slot + * @read_idx: Current read index of buffer + * @write_idx: Current write index of buffer + * @job_chain_flag: Flag used to implement jobchain disambiguation + */ +struct slot_rb { + struct rb_entry entries[SLOT_RB_SIZE]; + + struct kbase_context *last_context; + + u8 read_idx; + u8 write_idx; + + u8 job_chain_flag; +}; + +/** + * struct kbase_backend_data - GPU backend specific data for HW access layer + * @slot_rb: Slot ringbuffers + * @rmu_workaround_flag: When PRLAM-8987 is present, this flag determines + * whether slots 0/1 or slot 2 are currently being + * pulled from + * @scheduling_timer: The timer tick used for rescheduling jobs + * @timer_running: Is the timer running? The runpool_mutex must be + * held whilst modifying this. + * @suspend_timer: Is the timer suspended? Set when a suspend + * occurs and cleared on resume. The runpool_mutex + * must be held whilst modifying this. + * @reset_gpu: Set to a KBASE_RESET_xxx value (see comments) + * @reset_workq: Work queue for performing the reset + * @reset_work: Work item for performing the reset + * @reset_wait: Wait event signalled when the reset is complete + * @reset_timer: Timeout for soft-stops before the reset + * @timeouts_updated: Have timeout values just been updated? + * + * The hwaccess_lock (a spinlock) must be held when accessing this structure + */ +struct kbase_backend_data { + struct slot_rb slot_rb[BASE_JM_MAX_NR_SLOTS]; + + bool rmu_workaround_flag; + + struct hrtimer scheduling_timer; + + bool timer_running; + bool suspend_timer; + + atomic_t reset_gpu; + +/* The GPU reset isn't pending */ +#define KBASE_RESET_GPU_NOT_PENDING 0 +/* kbase_prepare_to_reset_gpu has been called */ +#define KBASE_RESET_GPU_PREPARED 1 +/* kbase_reset_gpu has been called - the reset will now definitely happen + * within the timeout period */ +#define KBASE_RESET_GPU_COMMITTED 2 +/* The GPU reset process is currently occuring (timeout has expired or + * kbasep_try_reset_gpu_early was called) */ +#define KBASE_RESET_GPU_HAPPENING 3 +/* Reset the GPU silently, used when resetting the GPU as part of normal + * behavior (e.g. when exiting protected mode). */ +#define KBASE_RESET_GPU_SILENT 4 + struct workqueue_struct *reset_workq; + struct work_struct reset_work; + wait_queue_head_t reset_wait; + struct hrtimer reset_timer; + + bool timeouts_updated; +}; + +/** + * struct kbase_jd_atom_backend - GPU backend specific katom data + */ +struct kbase_jd_atom_backend { +}; + +/** + * struct kbase_context_backend - GPU backend specific context data + */ +struct kbase_context_backend { +}; + +#endif /* _KBASE_HWACCESS_GPU_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c new file mode 100644 index 000000000000..be88ec8eb0d7 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c @@ -0,0 +1,1512 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Base kernel job manager APIs + */ + +#include +#include +#include +#if defined(CONFIG_MALI_GATOR_SUPPORT) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define beenthere(kctx, f, a...) \ + dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#if KBASE_GPU_RESET_EN +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev); +static void kbasep_reset_timeout_worker(struct work_struct *data); +static enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer); +#endif /* KBASE_GPU_RESET_EN */ + +static inline int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js, + struct kbase_context *kctx) +{ + return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), kctx); +} + +void kbase_job_hw_submit(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + int js) +{ + struct kbase_context *kctx; + u32 cfg; + u64 jc_head = katom->jc; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + /* Command register must be available */ + KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx)); + /* Affinity is not violating */ + kbase_js_debug_log_current_affinities(kbdev); + KBASE_DEBUG_ASSERT(!kbase_js_affinity_would_violate(kbdev, js, + katom->affinity)); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), + jc_head & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), + jc_head >> 32, kctx); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO), + katom->affinity & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_HI), + katom->affinity >> 32, kctx); + + /* start MMU, medium priority, cache clean/flush on end, clean/flush on + * start */ + cfg = kctx->as_nr; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION) && + !(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET)) + cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION; + + if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START)) + cfg |= JS_CONFIG_START_FLUSH_NO_ACTION; + else + cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE; + + if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_END) && + !(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET)) + cfg |= JS_CONFIG_END_FLUSH_NO_ACTION; + else + cfg |= JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10649)) + cfg |= JS_CONFIG_START_MMU; + + cfg |= JS_CONFIG_THREAD_PRI(8); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE) && + (katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED)) + cfg |= JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK; + + if (kbase_hw_has_feature(kbdev, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + if (!kbdev->hwaccess.backend.slot_rb[js].job_chain_flag) { + cfg |= JS_CONFIG_JOB_CHAIN_FLAG; + katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->hwaccess.backend.slot_rb[js].job_chain_flag = + true; + } else { + katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->hwaccess.backend.slot_rb[js].job_chain_flag = + false; + } + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_CONFIG_NEXT), cfg, kctx); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION)) + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_FLUSH_ID_NEXT), + katom->flush_id, kctx); + + /* Write an approximate start timestamp. + * It's approximate because there might be a job in the HEAD register. + */ + katom->start_timestamp = ktime_get(); + + /* GO ! */ + dev_dbg(kbdev->dev, "JS: Submitting atom %p from ctx %p to js[%d] with head=0x%llx, affinity=0x%llx", + katom, kctx, js, jc_head, katom->affinity); + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, + (u32) katom->affinity); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_job_slots_event( + GATOR_MAKE_EVENT(GATOR_JOB_SLOT_START, js), + kctx, kbase_jd_atom_id(kctx, katom)); +#endif + KBASE_TLSTREAM_TL_ATTRIB_ATOM_CONFIG(katom, jc_head, + katom->affinity, cfg); + KBASE_TLSTREAM_TL_RET_CTX_LPU( + kctx, + &kbdev->gpu_props.props.raw_props.js_features[ + katom->slot_nr]); + KBASE_TLSTREAM_TL_RET_ATOM_AS(katom, &kbdev->as[kctx->as_nr]); + KBASE_TLSTREAM_TL_RET_ATOM_LPU( + katom, + &kbdev->gpu_props.props.raw_props.js_features[js], + "ctx_nr,atom_nr"); +#ifdef CONFIG_GPU_TRACEPOINTS + if (!kbase_backend_nr_atoms_submitted(kbdev, js)) { + /* If this is the only job on the slot, trace it as starting */ + char js_string[16]; + + trace_gpu_sched_switch( + kbasep_make_job_slot_string(js, js_string, + sizeof(js_string)), + ktime_to_ns(katom->start_timestamp), + (u32)katom->kctx->id, 0, katom->work_id); + kbdev->hwaccess.backend.slot_rb[js].last_context = katom->kctx; + } +#endif + kbase_timeline_job_slot_submit(kbdev, kctx, katom, js); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), + JS_COMMAND_START, katom->kctx); +} + +/** + * kbasep_job_slot_update_head_start_timestamp - Update timestamp + * @kbdev: kbase device + * @js: job slot + * @end_timestamp: timestamp + * + * Update the start_timestamp of the job currently in the HEAD, based on the + * fact that we got an IRQ for the previous set of completed jobs. + * + * The estimate also takes into account the time the job was submitted, to + * work out the best estimate (which might still result in an over-estimate to + * the calculated time spent) + */ +static void kbasep_job_slot_update_head_start_timestamp( + struct kbase_device *kbdev, + int js, + ktime_t end_timestamp) +{ + if (kbase_backend_nr_atoms_on_slot(kbdev, js) > 0) { + struct kbase_jd_atom *katom; + ktime_t timestamp_diff; + /* The atom in the HEAD */ + katom = kbase_gpu_inspect(kbdev, js, 0); + + KBASE_DEBUG_ASSERT(katom != NULL); + + timestamp_diff = ktime_sub(end_timestamp, + katom->start_timestamp); + if (ktime_to_ns(timestamp_diff) >= 0) { + /* Only update the timestamp if it's a better estimate + * than what's currently stored. This is because our + * estimate that accounts for the throttle time may be + * too much of an overestimate */ + katom->start_timestamp = end_timestamp; + } + } +} + +/** + * kbasep_trace_tl_event_lpu_softstop - Call event_lpu_softstop timeline + * tracepoint + * @kbdev: kbase device + * @js: job slot + * + * Make a tracepoint call to the instrumentation module informing that + * softstop happened on given lpu (job slot). + */ +static void kbasep_trace_tl_event_lpu_softstop(struct kbase_device *kbdev, + int js) +{ + KBASE_TLSTREAM_TL_EVENT_LPU_SOFTSTOP( + &kbdev->gpu_props.props.raw_props.js_features[js]); +} + +void kbase_job_done(struct kbase_device *kbdev, u32 done) +{ + unsigned long flags; + int i; + u32 count = 0; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JM_IRQ, NULL, NULL, 0, done); + + memset(&kbdev->slot_submit_count_irq[0], 0, + sizeof(kbdev->slot_submit_count_irq)); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + while (done) { + u32 failed = done >> 16; + + /* treat failed slots as finished slots */ + u32 finished = (done & 0xFFFF) | failed; + + /* Note: This is inherently unfair, as we always check + * for lower numbered interrupts before the higher + * numbered ones.*/ + i = ffs(finished) - 1; + KBASE_DEBUG_ASSERT(i >= 0); + + do { + int nr_done; + u32 active; + u32 completion_code = BASE_JD_EVENT_DONE;/* assume OK */ + u64 job_tail = 0; + + if (failed & (1u << i)) { + /* read out the job slot status code if the job + * slot reported failure */ + completion_code = kbase_reg_read(kbdev, + JOB_SLOT_REG(i, JS_STATUS), NULL); + + switch (completion_code) { + case BASE_JD_EVENT_STOPPED: +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_job_slots_event( + GATOR_MAKE_EVENT( + GATOR_JOB_SLOT_SOFT_STOPPED, i), + NULL, 0); +#endif + + kbasep_trace_tl_event_lpu_softstop( + kbdev, i); + + /* Soft-stopped job - read the value of + * JS_TAIL so that the job chain can + * be resumed */ + job_tail = (u64)kbase_reg_read(kbdev, + JOB_SLOT_REG(i, JS_TAIL_LO), + NULL) | + ((u64)kbase_reg_read(kbdev, + JOB_SLOT_REG(i, JS_TAIL_HI), + NULL) << 32); + break; + case BASE_JD_EVENT_NOT_STARTED: + /* PRLAM-10673 can cause a TERMINATED + * job to come back as NOT_STARTED, but + * the error interrupt helps us detect + * it */ + completion_code = + BASE_JD_EVENT_TERMINATED; + /* fall through */ + default: + dev_warn(kbdev->dev, "error detected from slot %d, job status 0x%08x (%s)", + i, completion_code, + kbase_exception_name + (kbdev, + completion_code)); + } + + kbase_gpu_irq_evict(kbdev, i); + } + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), + done & ((1 << i) | (1 << (i + 16))), + NULL); + active = kbase_reg_read(kbdev, + JOB_CONTROL_REG(JOB_IRQ_JS_STATE), + NULL); + + if (((active >> i) & 1) == 0 && + (((done >> (i + 16)) & 1) == 0)) { + /* There is a potential race we must work + * around: + * + * 1. A job slot has a job in both current and + * next registers + * 2. The job in current completes + * successfully, the IRQ handler reads + * RAWSTAT and calls this function with the + * relevant bit set in "done" + * 3. The job in the next registers becomes the + * current job on the GPU + * 4. Sometime before the JOB_IRQ_CLEAR line + * above the job on the GPU _fails_ + * 5. The IRQ_CLEAR clears the done bit but not + * the failed bit. This atomically sets + * JOB_IRQ_JS_STATE. However since both jobs + * have now completed the relevant bits for + * the slot are set to 0. + * + * If we now did nothing then we'd incorrectly + * assume that _both_ jobs had completed + * successfully (since we haven't yet observed + * the fail bit being set in RAWSTAT). + * + * So at this point if there are no active jobs + * left we check to see if RAWSTAT has a failure + * bit set for the job slot. If it does we know + * that there has been a new failure that we + * didn't previously know about, so we make sure + * that we record this in active (but we wait + * for the next loop to deal with it). + * + * If we were handling a job failure (i.e. done + * has the relevant high bit set) then we know + * that the value read back from + * JOB_IRQ_JS_STATE is the correct number of + * remaining jobs because the failed job will + * have prevented any futher jobs from starting + * execution. + */ + u32 rawstat = kbase_reg_read(kbdev, + JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if ((rawstat >> (i + 16)) & 1) { + /* There is a failed job that we've + * missed - add it back to active */ + active |= (1u << i); + } + } + + dev_dbg(kbdev->dev, "Job ended with status 0x%08X\n", + completion_code); + + nr_done = kbase_backend_nr_atoms_submitted(kbdev, i); + nr_done -= (active >> i) & 1; + nr_done -= (active >> (i + 16)) & 1; + + if (nr_done <= 0) { + dev_warn(kbdev->dev, "Spurious interrupt on slot %d", + i); + + goto spurious; + } + + count += nr_done; + + while (nr_done) { + if (nr_done == 1) { + kbase_gpu_complete_hw(kbdev, i, + completion_code, + job_tail, + &end_timestamp); + kbase_jm_try_kick_all(kbdev); + } else { + /* More than one job has completed. + * Since this is not the last job being + * reported this time it must have + * passed. This is because the hardware + * will not allow further jobs in a job + * slot to complete until the failed job + * is cleared from the IRQ status. + */ + kbase_gpu_complete_hw(kbdev, i, + BASE_JD_EVENT_DONE, + 0, + &end_timestamp); + } + nr_done--; + } + spurious: + done = kbase_reg_read(kbdev, + JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10883)) { + /* Workaround for missing interrupt caused by + * PRLAM-10883 */ + if (((active >> i) & 1) && (0 == + kbase_reg_read(kbdev, + JOB_SLOT_REG(i, + JS_STATUS), NULL))) { + /* Force job slot to be processed again + */ + done |= (1u << i); + } + } + + failed = done >> 16; + finished = (done & 0xFFFF) | failed; + if (done) + end_timestamp = ktime_get(); + } while (finished & (1 << i)); + + kbasep_job_slot_update_head_start_timestamp(kbdev, i, + end_timestamp); + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +#if KBASE_GPU_RESET_EN + if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == + KBASE_RESET_GPU_COMMITTED) { + /* If we're trying to reset the GPU then we might be able to do + * it early (without waiting for a timeout) because some jobs + * have completed + */ + kbasep_try_reset_gpu_early(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + KBASE_TRACE_ADD(kbdev, JM_IRQ_END, NULL, NULL, 0, count); +} +KBASE_EXPORT_TEST_API(kbase_job_done); + +static bool kbasep_soft_stop_allowed(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + bool soft_stops_allowed = true; + + if (kbase_jd_katom_is_protected(katom)) { + soft_stops_allowed = false; + } else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) { + if ((katom->core_req & BASE_JD_REQ_T) != 0) + soft_stops_allowed = false; + } + return soft_stops_allowed; +} + +static bool kbasep_hard_stop_allowed(struct kbase_device *kbdev, + base_jd_core_req core_reqs) +{ + bool hard_stops_allowed = true; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8394)) { + if ((core_reqs & BASE_JD_REQ_T) != 0) + hard_stops_allowed = false; + } + return hard_stops_allowed; +} + +void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, + int js, + u32 action, + base_jd_core_req core_reqs, + struct kbase_jd_atom *target_katom) +{ + struct kbase_context *kctx = target_katom->kctx; +#if KBASE_TRACE_ENABLE + u32 status_reg_before; + u64 job_in_head_before; + u32 status_reg_after; + + KBASE_DEBUG_ASSERT(!(action & (~JS_COMMAND_MASK))); + + /* Check the head pointer */ + job_in_head_before = ((u64) kbase_reg_read(kbdev, + JOB_SLOT_REG(js, JS_HEAD_LO), NULL)) + | (((u64) kbase_reg_read(kbdev, + JOB_SLOT_REG(js, JS_HEAD_HI), NULL)) + << 32); + status_reg_before = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), + NULL); +#endif + + if (action == JS_COMMAND_SOFT_STOP) { + bool soft_stop_allowed = kbasep_soft_stop_allowed(kbdev, + target_katom); + + if (!soft_stop_allowed) { +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kbdev->dev, + "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%X", + (unsigned int)core_reqs); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + + /* We are about to issue a soft stop, so mark the atom as having + * been soft stopped */ + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED; + + /* Mark the point where we issue the soft-stop command */ + KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_ISSUE(target_katom); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + int i; + + for (i = 0; + i < kbase_backend_nr_atoms_submitted(kbdev, js); + i++) { + struct kbase_jd_atom *katom; + + katom = kbase_gpu_inspect(kbdev, js, i); + + KBASE_DEBUG_ASSERT(katom); + + /* For HW_ISSUE_8316, only 'bad' jobs attacking + * the system can cause this issue: normally, + * all memory should be allocated in multiples + * of 4 pages, and growable memory should be + * changed size in multiples of 4 pages. + * + * Whilst such 'bad' jobs can be cleared by a + * GPU reset, the locking up of a uTLB entry + * caused by the bad job could also stall other + * ASs, meaning that other ASs' jobs don't + * complete in the 'grace' period before the + * reset. We don't want to lose other ASs' jobs + * when they would normally complete fine, so we + * must 'poke' the MMU regularly to help other + * ASs complete */ + kbase_as_poking_timer_retain_atom( + kbdev, katom->kctx, katom); + } + } + + if (kbase_hw_has_feature( + kbdev, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + action = (target_katom->atom_flags & + KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_SOFT_STOP_1 : + JS_COMMAND_SOFT_STOP_0; + } + } else if (action == JS_COMMAND_HARD_STOP) { + bool hard_stop_allowed = kbasep_hard_stop_allowed(kbdev, + core_reqs); + + if (!hard_stop_allowed) { + /* Jobs can be hard-stopped for the following reasons: + * * CFS decides the job has been running too long (and + * soft-stop has not occurred). In this case the GPU + * will be reset by CFS if the job remains on the + * GPU. + * + * * The context is destroyed, kbase_jd_zap_context + * will attempt to hard-stop the job. However it also + * has a watchdog which will cause the GPU to be + * reset if the job remains on the GPU. + * + * * An (unhandled) MMU fault occurred. As long as + * BASE_HW_ISSUE_8245 is defined then the GPU will be + * reset. + * + * All three cases result in the GPU being reset if the + * hard-stop fails, so it is safe to just return and + * ignore the hard-stop request. + */ + dev_warn(kbdev->dev, + "Attempt made to hard-stop a job that cannot be hard-stopped. core_reqs = 0x%X", + (unsigned int)core_reqs); + return; + } + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_HARD_STOPPED; + + if (kbase_hw_has_feature( + kbdev, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + action = (target_katom->atom_flags & + KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_HARD_STOP_1 : + JS_COMMAND_HARD_STOP_0; + } + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND), action, kctx); + +#if KBASE_TRACE_ENABLE + status_reg_after = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), + NULL); + if (status_reg_after == BASE_JD_EVENT_ACTIVE) { + struct kbase_jd_atom *head; + struct kbase_context *head_kctx; + + head = kbase_gpu_inspect(kbdev, js, 0); + head_kctx = head->kctx; + + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, head_kctx, + head, job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, + 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, head_kctx, + head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, head_kctx, + head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, head_kctx, + head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, head_kctx, + head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, head_kctx, + head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, + head, head->jc, js); + break; + default: + BUG(); + break; + } + } else { + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, + job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, + 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, NULL, NULL, 0, + js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, NULL, NULL, + 0, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, NULL, NULL, + 0, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, NULL, NULL, 0, + js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, NULL, NULL, + 0, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, + 0, js); + break; + default: + BUG(); + break; + } + } +#endif +} + +void kbase_backend_jm_kill_jobs_from_kctx(struct kbase_context *kctx) +{ + unsigned long flags; + struct kbase_device *kbdev; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Cancel any remaining running jobs for this kctx */ + mutex_lock(&kctx->jctx.lock); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Invalidate all jobs in context, to prevent re-submitting */ + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) { + if (!work_pending(&kctx->jctx.atoms[i].work)) + kctx->jctx.atoms[i].event_code = + BASE_JD_EVENT_JOB_CANCELLED; + } + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_hardstop(kctx, i, NULL); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kctx->jctx.lock); +} + +void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, + struct kbase_jd_atom *target_katom) +{ + struct kbase_device *kbdev; + int js = target_katom->slot_nr; + int priority = target_katom->sched_priority; + int i; + bool stop_sent = false; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (i = 0; i < kbase_backend_nr_atoms_on_slot(kbdev, js); i++) { + struct kbase_jd_atom *katom; + + katom = kbase_gpu_inspect(kbdev, js, i); + if (!katom) + continue; + + if (katom->kctx != kctx) + continue; + + if (katom->sched_priority > priority) { + if (!stop_sent) + KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY_CHANGE( + target_katom); + + kbase_job_slot_softstop(kbdev, js, katom); + stop_sent = true; + } + } +} + +struct zap_reset_data { + /* The stages are: + * 1. The timer has never been called + * 2. The zap has timed out, all slots are soft-stopped - the GPU reset + * will happen. The GPU has been reset when + * kbdev->hwaccess.backend.reset_waitq is signalled + * + * (-1 - The timer has been cancelled) + */ + int stage; + struct kbase_device *kbdev; + struct hrtimer timer; + spinlock_t lock; /* protects updates to stage member */ +}; + +static enum hrtimer_restart zap_timeout_callback(struct hrtimer *timer) +{ + struct zap_reset_data *reset_data = container_of(timer, + struct zap_reset_data, timer); + struct kbase_device *kbdev = reset_data->kbdev; + unsigned long flags; + + spin_lock_irqsave(&reset_data->lock, flags); + + if (reset_data->stage == -1) + goto out; + +#if KBASE_GPU_RESET_EN + if (kbase_prepare_to_reset_gpu(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", + ZAP_TIMEOUT); + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + reset_data->stage = 2; + + out: + spin_unlock_irqrestore(&reset_data->lock, flags); + + return HRTIMER_NORESTART; +} + +void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx) +{ + struct kbase_device *kbdev = kctx->kbdev; + struct zap_reset_data reset_data; + unsigned long flags; + + hrtimer_init_on_stack(&reset_data.timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + reset_data.timer.function = zap_timeout_callback; + + spin_lock_init(&reset_data.lock); + + reset_data.kbdev = kbdev; + reset_data.stage = 1; + + hrtimer_start(&reset_data.timer, HR_TIMER_DELAY_MSEC(ZAP_TIMEOUT), + HRTIMER_MODE_REL); + + /* Wait for all jobs to finish, and for the context to be not-scheduled + * (due to kbase_job_zap_context(), we also guarentee it's not in the JS + * policy queue either */ + wait_event(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0); + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, + !kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + spin_lock_irqsave(&reset_data.lock, flags); + if (reset_data.stage == 1) { + /* The timer hasn't run yet - so cancel it */ + reset_data.stage = -1; + } + spin_unlock_irqrestore(&reset_data.lock, flags); + + hrtimer_cancel(&reset_data.timer); + + if (reset_data.stage == 2) { + /* The reset has already started. + * Wait for the reset to complete + */ + wait_event(kbdev->hwaccess.backend.reset_wait, + atomic_read(&kbdev->hwaccess.backend.reset_gpu) + == KBASE_RESET_GPU_NOT_PENDING); + } + destroy_hrtimer_on_stack(&reset_data.timer); + + dev_dbg(kbdev->dev, "Zap: Finished Context %p", kctx); + + /* Ensure that the signallers of the waitqs have finished */ + mutex_lock(&kctx->jctx.lock); + mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.lock); +} + +u32 kbase_backend_get_current_flush_id(struct kbase_device *kbdev) +{ + u32 flush_id = 0; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION)) { + mutex_lock(&kbdev->pm.lock); + if (kbdev->pm.backend.gpu_powered) + flush_id = kbase_reg_read(kbdev, + GPU_CONTROL_REG(LATEST_FLUSH), NULL); + mutex_unlock(&kbdev->pm.lock); + } + + return flush_id; +} + +int kbase_job_slot_init(struct kbase_device *kbdev) +{ +#if KBASE_GPU_RESET_EN + kbdev->hwaccess.backend.reset_workq = alloc_workqueue( + "Mali reset workqueue", 0, 1); + if (NULL == kbdev->hwaccess.backend.reset_workq) + return -EINVAL; + + KBASE_DEBUG_ASSERT(0 == + object_is_on_stack(&kbdev->hwaccess.backend.reset_work)); + INIT_WORK(&kbdev->hwaccess.backend.reset_work, + kbasep_reset_timeout_worker); + + hrtimer_init(&kbdev->hwaccess.backend.reset_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + kbdev->hwaccess.backend.reset_timer.function = + kbasep_reset_timer_callback; +#endif + + return 0; +} +KBASE_EXPORT_TEST_API(kbase_job_slot_init); + +void kbase_job_slot_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_job_slot_term(struct kbase_device *kbdev) +{ +#if KBASE_GPU_RESET_EN + destroy_workqueue(kbdev->hwaccess.backend.reset_workq); +#endif +} +KBASE_EXPORT_TEST_API(kbase_job_slot_term); + +#if KBASE_GPU_RESET_EN +/** + * kbasep_check_for_afbc_on_slot() - Check whether AFBC is in use on this slot + * @kbdev: kbase device pointer + * @kctx: context to check against + * @js: slot to check + * @target_katom: An atom to check, or NULL if all atoms from @kctx on + * slot @js should be checked + * + * This checks are based upon parameters that would normally be passed to + * kbase_job_slot_hardstop(). + * + * In the event of @target_katom being NULL, this will check the last jobs that + * are likely to be running on the slot to see if a) they belong to kctx, and + * so would be stopped, and b) whether they have AFBC + * + * In that case, It's guaranteed that a job currently executing on the HW with + * AFBC will be detected. However, this is a conservative check because it also + * detects jobs that have just completed too. + * + * Return: true when hard-stop _might_ stop an afbc atom, else false. + */ +static bool kbasep_check_for_afbc_on_slot(struct kbase_device *kbdev, + struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom) +{ + bool ret = false; + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* When we have an atom the decision can be made straight away. */ + if (target_katom) + return !!(target_katom->core_req & BASE_JD_REQ_FS_AFBC); + + /* Otherwise, we must chweck the hardware to see if it has atoms from + * this context with AFBC. */ + for (i = 0; i < kbase_backend_nr_atoms_on_slot(kbdev, js); i++) { + struct kbase_jd_atom *katom; + + katom = kbase_gpu_inspect(kbdev, js, i); + if (!katom) + continue; + + /* Ignore atoms from other contexts, they won't be stopped when + * we use this for checking if we should hard-stop them */ + if (katom->kctx != kctx) + continue; + + /* An atom on this slot and this context: check for AFBC */ + if (katom->core_req & BASE_JD_REQ_FS_AFBC) { + ret = true; + break; + } + } + + return ret; +} +#endif /* KBASE_GPU_RESET_EN */ + +/** + * kbase_job_slot_softstop_swflags - Soft-stop a job with flags + * @kbdev: The kbase device + * @js: The job slot to soft-stop + * @target_katom: The job that should be soft-stopped (or NULL for any job) + * @sw_flags: Flags to pass in about the soft-stop + * + * Context: + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Soft-stop the specified job slot, with extra information about the stop + * + * Where possible any job in the next register is evicted before the soft-stop. + */ +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags) +{ + KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK)); + kbase_backend_soft_hard_stop_slot(kbdev, NULL, js, target_katom, + JS_COMMAND_SOFT_STOP | sw_flags); +} + +/** + * kbase_job_slot_softstop - Soft-stop the specified job slot + * @kbdev: The kbase device + * @js: The job slot to soft-stop + * @target_katom: The job that should be soft-stopped (or NULL for any job) + * Context: + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Where possible any job in the next register is evicted before the soft-stop. + */ +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom) +{ + kbase_job_slot_softstop_swflags(kbdev, js, target_katom, 0u); +} + +/** + * kbase_job_slot_hardstop - Hard-stop the specified job slot + * @kctx: The kbase context that contains the job(s) that should + * be hard-stopped + * @js: The job slot to hard-stop + * @target_katom: The job that should be hard-stopped (or NULL for all + * jobs from the context) + * Context: + * The job slot lock must be held when calling this function. + */ +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom) +{ + struct kbase_device *kbdev = kctx->kbdev; + bool stopped; +#if KBASE_GPU_RESET_EN + /* We make the check for AFBC before evicting/stopping atoms. Note + * that no other thread can modify the slots whilst we have the + * hwaccess_lock. */ + int needs_workaround_for_afbc = + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3542) + && kbasep_check_for_afbc_on_slot(kbdev, kctx, js, + target_katom); +#endif + + stopped = kbase_backend_soft_hard_stop_slot(kbdev, kctx, js, + target_katom, + JS_COMMAND_HARD_STOP); +#if KBASE_GPU_RESET_EN + if (stopped && (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_8401) || + kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_9510) || + needs_workaround_for_afbc)) { + /* MIDBASE-2916 if a fragment job with AFBC encoding is + * hardstopped, ensure to do a soft reset also in order to + * clear the GPU status. + * Workaround for HW issue 8401 has an issue,so after + * hard-stopping just reset the GPU. This will ensure that the + * jobs leave the GPU.*/ + if (kbase_prepare_to_reset_gpu_locked(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU soft-reset after hard stopping due to hardware issue"); + kbase_reset_gpu_locked(kbdev); + } + } +#endif +} + +/** + * kbase_job_check_enter_disjoint - potentiall enter disjoint mode + * @kbdev: kbase device + * @action: the event which has occurred + * @core_reqs: core requirements of the atom + * @target_katom: the atom which is being affected + * + * For a certain soft/hard-stop action, work out whether to enter disjoint + * state. + * + * This does not register multiple disjoint events if the atom has already + * started a disjoint period + * + * @core_reqs can be supplied as 0 if the atom had not started on the hardware + * (and so a 'real' soft/hard-stop was not required, but it still interrupted + * flow, perhaps on another context) + * + * kbase_job_check_leave_disjoint() should be used to end the disjoint + * state when the soft/hard-stop action is complete + */ +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom) +{ + u32 hw_action = action & JS_COMMAND_MASK; + + /* For hard-stop, don't enter if hard-stop not allowed */ + if (hw_action == JS_COMMAND_HARD_STOP && + !kbasep_hard_stop_allowed(kbdev, core_reqs)) + return; + + /* For soft-stop, don't enter if soft-stop not allowed, or isn't + * causing disjoint */ + if (hw_action == JS_COMMAND_SOFT_STOP && + !(kbasep_soft_stop_allowed(kbdev, target_katom) && + (action & JS_COMMAND_SW_CAUSES_DISJOINT))) + return; + + /* Nothing to do if already logged disjoint state on this atom */ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) + return; + + target_katom->atom_flags |= KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_up(kbdev); +} + +/** + * kbase_job_check_enter_disjoint - potentially leave disjoint state + * @kbdev: kbase device + * @target_katom: atom which is finishing + * + * Work out whether to leave disjoint state when finishing an atom that was + * originated by kbase_job_check_enter_disjoint(). + */ +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom) +{ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) { + target_katom->atom_flags &= ~KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_down(kbdev); + } +} + + +#if KBASE_GPU_RESET_EN +static void kbase_debug_dump_registers(struct kbase_device *kbdev) +{ + int i; + + kbase_io_history_dump(kbdev); + + dev_err(kbdev->dev, "Register state:"); + dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS), NULL)); + dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x", + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL)); + for (i = 0; i < 3; i++) { + dev_err(kbdev->dev, " JS%d_STATUS=0x%08x JS%d_HEAD_LO=0x%08x", + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), + NULL), + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_HEAD_LO), + NULL)); + } + dev_err(kbdev->dev, " MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x", + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL)); + dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), NULL), + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL)); + dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE0), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1), NULL)); + dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL)); + dev_err(kbdev->dev, " TILER_CONFIG=0x%08x JM_CONFIG=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(JM_CONFIG), NULL)); +} + +static void kbasep_reset_timeout_worker(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + bool try_schedule = false; + bool silent = false; + u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; + + KBASE_DEBUG_ASSERT(data); + + kbdev = container_of(data, struct kbase_device, + hwaccess.backend.reset_work); + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == + KBASE_RESET_GPU_SILENT) + silent = true; + + KBASE_TRACE_ADD(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); + + /* Suspend vinstr. + * This call will block until vinstr is suspended. */ + kbase_vinstr_suspend(kbdev->vinstr_ctx); + + /* Make sure the timer has completed - this cannot be done from + * interrupt context, so this cannot be done within + * kbasep_try_reset_gpu_early. */ + hrtimer_cancel(&kbdev->hwaccess.backend.reset_timer); + + if (kbase_pm_context_active_handle_suspend(kbdev, + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + /* This would re-activate the GPU. Since it's already idle, + * there's no need to reset it */ + atomic_set(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_NOT_PENDING); + kbase_disjoint_state_down(kbdev); + wake_up(&kbdev->hwaccess.backend.reset_wait); + kbase_vinstr_resume(kbdev->vinstr_ctx); + return; + } + + KBASE_DEBUG_ASSERT(kbdev->irq_reset_flush == false); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + spin_lock(&kbdev->hwaccess_lock); + spin_lock(&kbdev->mmu_mask_change); + /* We're about to flush out the IRQs and their bottom half's */ + kbdev->irq_reset_flush = true; + + /* Disable IRQ to avoid IRQ handlers to kick in after releasing the + * spinlock; this also clears any outstanding interrupts */ + kbase_pm_disable_interrupts_nolock(kbdev); + + spin_unlock(&kbdev->mmu_mask_change); + spin_unlock(&kbdev->hwaccess_lock); + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ensure that any IRQ handlers have finished + * Must be done without any locks IRQ handlers will take */ + kbase_synchronize_irqs(kbdev); + + /* Flush out any in-flight work items */ + kbase_flush_mmu_wqs(kbdev); + + /* The flush has completed so reset the active indicator */ + kbdev->irq_reset_flush = false; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8463)) { + /* Ensure that L2 is not transitioning when we send the reset + * command */ + while (--max_loops && kbase_pm_get_trans_cores(kbdev, + KBASE_PM_CORE_L2)) + ; + + WARN(!max_loops, "L2 power transition timed out while trying to reset\n"); + } + + mutex_lock(&kbdev->pm.lock); + /* We hold the pm lock, so there ought to be a current policy */ + KBASE_DEBUG_ASSERT(kbdev->pm.backend.pm_current_policy); + + /* All slot have been soft-stopped and we've waited + * SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point we + * assume that anything that is still left on the GPU is stuck there and + * we'll kill it when we reset the GPU */ + + if (!silent) + dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", + RESET_TIMEOUT); + + /* Output the state of some interesting registers to help in the + * debugging of GPU resets */ + if (!silent) + kbase_debug_dump_registers(kbdev); + + /* Complete any jobs that were still on the GPU */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->protected_mode = false; + kbase_backend_reset(kbdev, &end_timestamp); + kbase_pm_metrics_update(kbdev, NULL); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + /* Reset the GPU */ + kbase_pm_init_hw(kbdev, 0); + + mutex_unlock(&kbdev->pm.lock); + + mutex_lock(&js_devdata->runpool_mutex); + + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_ctx_sched_restore_all_as(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + kbase_pm_enable_interrupts(kbdev); + + atomic_set(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_NOT_PENDING); + + kbase_disjoint_state_down(kbdev); + + wake_up(&kbdev->hwaccess.backend.reset_wait); + if (!silent) + dev_err(kbdev->dev, "Reset complete"); + + if (js_devdata->nr_contexts_pullable > 0 && !kbdev->poweroff_pending) + try_schedule = true; + + mutex_unlock(&js_devdata->runpool_mutex); + + mutex_lock(&kbdev->pm.lock); + + /* Find out what cores are required now */ + kbase_pm_update_cores_state(kbdev); + + /* Synchronously request and wait for those cores, because if + * instrumentation is enabled it would need them immediately. */ + kbase_pm_check_transitions_sync(kbdev); + + mutex_unlock(&kbdev->pm.lock); + + /* Try submitting some jobs to restart processing */ + if (try_schedule) { + KBASE_TRACE_ADD(kbdev, JM_SUBMIT_AFTER_RESET, NULL, NULL, 0u, + 0); + kbase_js_sched_all(kbdev); + } + + /* Process any pending slot updates */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_backend_slot_update(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + kbase_pm_context_idle(kbdev); + + /* Release vinstr */ + kbase_vinstr_resume(kbdev->vinstr_ctx); + + KBASE_TRACE_ADD(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0); +} + +static enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev = container_of(timer, struct kbase_device, + hwaccess.backend.reset_timer); + + KBASE_DEBUG_ASSERT(kbdev); + + /* Reset still pending? */ + if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == + KBASE_RESET_GPU_COMMITTED) + queue_work(kbdev->hwaccess.backend.reset_workq, + &kbdev->hwaccess.backend.reset_work); + + return HRTIMER_NORESTART; +} + +/* + * If all jobs are evicted from the GPU then we can reset the GPU + * immediately instead of waiting for the timeout to elapse + */ + +static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) +{ + int i; + int pending_jobs = 0; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Count the number of jobs */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + pending_jobs += kbase_backend_nr_atoms_submitted(kbdev, i); + + if (pending_jobs > 0) { + /* There are still jobs on the GPU - wait */ + return; + } + + /* To prevent getting incorrect registers when dumping failed job, + * skip early reset. + */ + if (kbdev->job_fault_debug != false) + return; + + /* Check that the reset has been committed to (i.e. kbase_reset_gpu has + * been called), and that no other thread beat this thread to starting + * the reset */ + if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) != + KBASE_RESET_GPU_COMMITTED) { + /* Reset has already occurred */ + return; + } + + queue_work(kbdev->hwaccess.backend.reset_workq, + &kbdev->hwaccess.backend.reset_work); +} + +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbasep_try_reset_gpu_early_locked(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +/** + * kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU + * @kbdev: kbase device + * + * This function just soft-stops all the slots to ensure that as many jobs as + * possible are saved. + * + * Return: + * The function returns a boolean which should be interpreted as follows: + * true - Prepared for reset, kbase_reset_gpu_locked should be called. + * false - Another thread is performing a reset, kbase_reset_gpu should + * not be called. + */ +bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev) +{ + int i; + + KBASE_DEBUG_ASSERT(kbdev); + + if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_NOT_PENDING, + KBASE_RESET_GPU_PREPARED) != + KBASE_RESET_GPU_NOT_PENDING) { + /* Some other thread is already resetting the GPU */ + return false; + } + + kbase_disjoint_state_up(kbdev); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_softstop(kbdev, i, NULL); + + return true; +} + +bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + ret = kbase_prepare_to_reset_gpu_locked(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return ret; +} +KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu); + +/* + * This function should be called after kbase_prepare_to_reset_gpu if it + * returns true. It should never be called without a corresponding call to + * kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu + * returned false), the caller should wait for + * kbdev->hwaccess.backend.reset_waitq to be signalled to know when the reset + * has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for + * a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == + KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_COMMITTED); + + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", + kbdev->reset_timeout_ms); + + hrtimer_start(&kbdev->hwaccess.backend.reset_timer, + HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), + HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early(kbdev); +} +KBASE_EXPORT_TEST_API(kbase_reset_gpu); + +void kbase_reset_gpu_locked(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for + * a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == + KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_COMMITTED); + + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", + kbdev->reset_timeout_ms); + hrtimer_start(&kbdev->hwaccess.backend.reset_timer, + HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), + HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early_locked(kbdev); +} + +void kbase_reset_gpu_silent(struct kbase_device *kbdev) +{ + if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, + KBASE_RESET_GPU_NOT_PENDING, + KBASE_RESET_GPU_SILENT) != + KBASE_RESET_GPU_NOT_PENDING) { + /* Some other thread is already resetting the GPU */ + return; + } + + kbase_disjoint_state_up(kbdev); + + queue_work(kbdev->hwaccess.backend.reset_workq, + &kbdev->hwaccess.backend.reset_work); +} + +bool kbase_reset_gpu_active(struct kbase_device *kbdev) +{ + if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == + KBASE_RESET_GPU_NOT_PENDING) + return false; + + return true; +} +#endif /* KBASE_GPU_RESET_EN */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h new file mode 100644 index 000000000000..1f382b3c1af4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h @@ -0,0 +1,164 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Manager backend-specific low-level APIs. + */ + +#ifndef _KBASE_JM_HWACCESS_H_ +#define _KBASE_JM_HWACCESS_H_ + +#include +#include +#include + +#include + +/** + * kbase_job_submit_nolock() - Submit a job to a certain job-slot + * @kbdev: Device pointer + * @katom: Atom to submit + * @js: Job slot to submit on + * + * The caller must check kbasep_jm_is_submit_slots_free() != false before + * calling this. + * + * The following locking conditions are made on the caller: + * - it must hold the hwaccess_lock + */ +void kbase_job_submit_nolock(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, int js); + +/** + * kbase_job_done_slot() - Complete the head job on a particular job-slot + * @kbdev: Device pointer + * @s: Job slot + * @completion_code: Completion code of job reported by GPU + * @job_tail: Job tail address reported by GPU + * @end_timestamp: Timestamp of job completion + */ +void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, + u64 job_tail, ktime_t *end_timestamp); + +#ifdef CONFIG_GPU_TRACEPOINTS +static inline char *kbasep_make_job_slot_string(int js, char *js_string, + size_t js_size) +{ + snprintf(js_string, js_size, "job_slot_%i", js); + return js_string; +} +#endif + +/** + * kbase_job_hw_submit() - Submit a job to the GPU + * @kbdev: Device pointer + * @katom: Atom to submit + * @js: Job slot to submit on + * + * The caller must check kbasep_jm_is_submit_slots_free() != false before + * calling this. + * + * The following locking conditions are made on the caller: + * - it must hold the hwaccess_lock + */ +void kbase_job_hw_submit(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + int js); + +/** + * kbasep_job_slot_soft_or_hard_stop_do_action() - Perform a soft or hard stop + * on the specified atom + * @kbdev: Device pointer + * @js: Job slot to stop on + * @action: The action to perform, either JSn_COMMAND_HARD_STOP or + * JSn_COMMAND_SOFT_STOP + * @core_reqs: Core requirements of atom to stop + * @target_katom: Atom to stop + * + * The following locking conditions are made on the caller: + * - it must hold the hwaccess_lock + */ +void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, + int js, + u32 action, + base_jd_core_req core_reqs, + struct kbase_jd_atom *target_katom); + +/** + * kbase_backend_soft_hard_stop_slot() - Soft or hard stop jobs on a given job + * slot belonging to a given context. + * @kbdev: Device pointer + * @kctx: Context pointer. May be NULL + * @katom: Specific atom to stop. May be NULL + * @js: Job slot to hard stop + * @action: The action to perform, either JSn_COMMAND_HARD_STOP or + * JSn_COMMAND_SOFT_STOP + * + * If no context is provided then all jobs on the slot will be soft or hard + * stopped. + * + * If a katom is provided then only that specific atom will be stopped. In this + * case the kctx parameter is ignored. + * + * Jobs that are on the slot but are not yet on the GPU will be unpulled and + * returned to the job scheduler. + * + * Return: true if an atom was stopped, false otherwise + */ +bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js, + struct kbase_jd_atom *katom, + u32 action); + +/** + * kbase_job_slot_init - Initialise job slot framework + * @kbdev: Device pointer + * + * Called on driver initialisation + * + * Return: 0 on success + */ +int kbase_job_slot_init(struct kbase_device *kbdev); + +/** + * kbase_job_slot_halt - Halt the job slot framework + * @kbdev: Device pointer + * + * Should prevent any further job slot processing + */ +void kbase_job_slot_halt(struct kbase_device *kbdev); + +/** + * kbase_job_slot_term - Terminate job slot framework + * @kbdev: Device pointer + * + * Called on driver termination + */ +void kbase_job_slot_term(struct kbase_device *kbdev); + +/** + * kbase_gpu_cacheclean - Cause a GPU cache clean & flush + * @kbdev: Device pointer + * + * Caller must not be in IRQ context + */ +void kbase_gpu_cacheclean(struct kbase_device *kbdev); + +#endif /* _KBASE_JM_HWACCESS_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c new file mode 100644 index 000000000000..a41e7b5b7afb --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c @@ -0,0 +1,1947 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend specific APIs + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Return whether the specified ringbuffer is empty. HW access lock must be + * held */ +#define SLOT_RB_EMPTY(rb) (rb->write_idx == rb->read_idx) +/* Return number of atoms currently in the specified ringbuffer. HW access lock + * must be held */ +#define SLOT_RB_ENTRIES(rb) (int)(s8)(rb->write_idx - rb->read_idx) + +static void kbase_gpu_release_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + ktime_t *end_timestamp); + +/** + * kbase_gpu_enqueue_atom - Enqueue an atom in the HW access ringbuffer + * @kbdev: Device pointer + * @katom: Atom to enqueue + * + * Context: Caller must hold the HW access lock + */ +static void kbase_gpu_enqueue_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[katom->slot_nr]; + + WARN_ON(SLOT_RB_ENTRIES(rb) >= SLOT_RB_SIZE); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + rb->entries[rb->write_idx & SLOT_RB_MASK].katom = katom; + rb->write_idx++; + + katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_BLOCKED; +} + +/** + * kbase_gpu_dequeue_atom - Remove an atom from the HW access ringbuffer, once + * it has been completed + * @kbdev: Device pointer + * @js: Job slot to remove atom from + * @end_timestamp: Pointer to timestamp of atom completion. May be NULL, in + * which case current time will be used. + * + * Context: Caller must hold the HW access lock + * + * Return: Atom removed from ringbuffer + */ +static struct kbase_jd_atom *kbase_gpu_dequeue_atom(struct kbase_device *kbdev, + int js, + ktime_t *end_timestamp) +{ + struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; + struct kbase_jd_atom *katom; + + if (SLOT_RB_EMPTY(rb)) { + WARN(1, "GPU ringbuffer unexpectedly empty\n"); + return NULL; + } + + lockdep_assert_held(&kbdev->hwaccess_lock); + + katom = rb->entries[rb->read_idx & SLOT_RB_MASK].katom; + + kbase_gpu_release_atom(kbdev, katom, end_timestamp); + + rb->read_idx++; + + katom->gpu_rb_state = KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB; + + kbase_js_debug_log_current_affinities(kbdev); + + return katom; +} + +struct kbase_jd_atom *kbase_gpu_inspect(struct kbase_device *kbdev, int js, + int idx) +{ + struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if ((SLOT_RB_ENTRIES(rb) - 1) < idx) + return NULL; /* idx out of range */ + + return rb->entries[(rb->read_idx + idx) & SLOT_RB_MASK].katom; +} + +struct kbase_jd_atom *kbase_backend_inspect_head(struct kbase_device *kbdev, + int js) +{ + return kbase_gpu_inspect(kbdev, js, 0); +} + +struct kbase_jd_atom *kbase_backend_inspect_tail(struct kbase_device *kbdev, + int js) +{ + struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; + + if (SLOT_RB_EMPTY(rb)) + return NULL; + + return rb->entries[(rb->write_idx - 1) & SLOT_RB_MASK].katom; +} + +/** + * kbase_gpu_atoms_submitted - Inspect whether a slot has any atoms currently + * on the GPU + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return: true if there are atoms on the GPU for slot js, + * false otherwise + */ +static bool kbase_gpu_atoms_submitted(struct kbase_device *kbdev, int js) +{ + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (i = 0; i < SLOT_RB_SIZE; i++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); + + if (!katom) + return false; + if (katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED || + katom->gpu_rb_state == KBASE_ATOM_GPU_RB_READY) + return true; + } + + return false; +} + +/** + * kbase_gpu_atoms_submitted_any() - Inspect whether there are any atoms + * currently on the GPU + * @kbdev: Device pointer + * + * Return: true if there are any atoms on the GPU, false otherwise + */ +static bool kbase_gpu_atoms_submitted_any(struct kbase_device *kbdev) +{ + int js; + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + for (i = 0; i < SLOT_RB_SIZE; i++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); + + if (katom && katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) + return true; + } + } + return false; +} + +int kbase_backend_nr_atoms_submitted(struct kbase_device *kbdev, int js) +{ + int nr = 0; + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (i = 0; i < SLOT_RB_SIZE; i++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); + + if (katom && (katom->gpu_rb_state == + KBASE_ATOM_GPU_RB_SUBMITTED)) + nr++; + } + + return nr; +} + +int kbase_backend_nr_atoms_on_slot(struct kbase_device *kbdev, int js) +{ + int nr = 0; + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (i = 0; i < SLOT_RB_SIZE; i++) { + if (kbase_gpu_inspect(kbdev, js, i)) + nr++; + } + + return nr; +} + +static int kbase_gpu_nr_atoms_on_slot_min(struct kbase_device *kbdev, int js, + enum kbase_atom_gpu_rb_state min_rb_state) +{ + int nr = 0; + int i; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (i = 0; i < SLOT_RB_SIZE; i++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); + + if (katom && (katom->gpu_rb_state >= min_rb_state)) + nr++; + } + + return nr; +} + +/** + * check_secure_atom - Check if the given atom is in the given secure state and + * has a ringbuffer state of at least + * KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION + * @katom: Atom pointer + * @secure: Desired secure state + * + * Return: true if atom is in the given state, false otherwise + */ +static bool check_secure_atom(struct kbase_jd_atom *katom, bool secure) +{ + if (katom->gpu_rb_state >= + KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION && + ((kbase_jd_katom_is_protected(katom) && secure) || + (!kbase_jd_katom_is_protected(katom) && !secure))) + return true; + + return false; +} + +/** + * kbase_gpu_check_secure_atoms - Check if there are any atoms in the given + * secure state in the ringbuffers of at least + * state + * KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE + * @kbdev: Device pointer + * @secure: Desired secure state + * + * Return: true if any atoms are in the given state, false otherwise + */ +static bool kbase_gpu_check_secure_atoms(struct kbase_device *kbdev, + bool secure) +{ + int js, i; + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + for (i = 0; i < SLOT_RB_SIZE; i++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, + js, i); + + if (katom) { + if (check_secure_atom(katom, secure)) + return true; + } + } + } + + return false; +} + +int kbase_backend_slot_free(struct kbase_device *kbdev, int js) +{ + if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) != + KBASE_RESET_GPU_NOT_PENDING) { + /* The GPU is being reset - so prevent submission */ + return 0; + } + + return SLOT_RB_SIZE - kbase_backend_nr_atoms_on_slot(kbdev, js); +} + + +static void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +static bool kbasep_js_job_check_ref_cores(struct kbase_device *kbdev, + int js, + struct kbase_jd_atom *katom) +{ + /* The most recently checked affinity. Having this at this scope allows + * us to guarantee that we've checked the affinity in this function + * call. + */ + u64 recently_chosen_affinity = 0; + bool chosen_affinity = false; + bool retry; + + do { + retry = false; + + /* NOTE: The following uses a number of FALLTHROUGHs to optimize + * the calls to this function. Ending of the function is + * indicated by BREAK OUT */ + switch (katom->coreref_state) { + /* State when job is first attempted to be run */ + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + KBASE_DEBUG_ASSERT(katom->affinity == 0); + + /* Compute affinity */ + if (false == kbase_js_choose_affinity( + &recently_chosen_affinity, kbdev, katom, + js)) { + /* No cores are currently available */ + /* *** BREAK OUT: No state transition *** */ + break; + } + + chosen_affinity = true; + + /* Request the cores */ + kbase_pm_request_cores(kbdev, + katom->core_req & BASE_JD_REQ_T, + recently_chosen_affinity); + + katom->affinity = recently_chosen_affinity; + + /* Proceed to next state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + { + enum kbase_pm_cores_ready cores_ready; + + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + + cores_ready = kbase_pm_register_inuse_cores( + kbdev, + katom->core_req & BASE_JD_REQ_T, + katom->affinity); + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to + * previous state */ + kbasep_js_job_check_deref_cores(kbdev, + katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_REGISTER_INUSE_FAILED, + katom->kctx, katom, + katom->jc, js, + (u32) katom->affinity); + /* *** BREAK OUT: Return to previous + * state, retry *** */ + retry = true; + break; + } + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Stay in this state and return, to + * retry at this state later */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_REGISTER_INUSE_FAILED, + katom->kctx, katom, + katom->jc, js, + (u32) katom->affinity); + /* *** BREAK OUT: No state transition + * *** */ + break; + } + /* Proceed to next state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + } + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + + /* Optimize out choosing the affinity twice in the same + * function call */ + if (chosen_affinity == false) { + /* See if the affinity changed since a previous + * call. */ + if (false == kbase_js_choose_affinity( + &recently_chosen_affinity, + kbdev, katom, js)) { + /* No cores are currently available */ + kbasep_js_job_check_deref_cores(kbdev, + katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_REQUEST_ON_RECHECK_FAILED, + katom->kctx, katom, + katom->jc, js, + (u32) recently_chosen_affinity); + /* *** BREAK OUT: Transition to lower + * state *** */ + break; + } + chosen_affinity = true; + } + + /* Now see if this requires a different set of cores */ + if (recently_chosen_affinity != katom->affinity) { + enum kbase_pm_cores_ready cores_ready; + + kbase_pm_request_cores(kbdev, + katom->core_req & BASE_JD_REQ_T, + recently_chosen_affinity); + + /* Register new cores whilst we still hold the + * old ones, to minimize power transitions */ + cores_ready = + kbase_pm_register_inuse_cores(kbdev, + katom->core_req & BASE_JD_REQ_T, + recently_chosen_affinity); + kbasep_js_job_check_deref_cores(kbdev, katom); + + /* Fixup the state that was reduced by + * deref_cores: */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + katom->affinity = recently_chosen_affinity; + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to + * previous state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + + kbasep_js_job_check_deref_cores(kbdev, + katom); + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_REGISTER_INUSE_FAILED, + katom->kctx, katom, + katom->jc, js, + (u32) katom->affinity); + /* *** BREAK OUT: Return to previous + * state, retry *** */ + retry = true; + break; + } + /* Now might be waiting for powerup again, with + * a new affinity */ + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Return to previous state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_REGISTER_ON_RECHECK_FAILED, + katom->kctx, katom, + katom->jc, js, + (u32) katom->affinity); + /* *** BREAK OUT: Transition to lower + * state *** */ + break; + } + } + /* Proceed to next state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + case KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + KBASE_DEBUG_ASSERT(katom->affinity == + recently_chosen_affinity); + + /* Note: this is where the caller must've taken the + * hwaccess_lock */ + + /* Check for affinity violations - if there are any, + * then we just ask the caller to requeue and try again + * later */ + if (kbase_js_affinity_would_violate(kbdev, js, + katom->affinity) != false) { + /* Return to previous state */ + katom->coreref_state = + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + /* *** BREAK OUT: Transition to lower state *** + */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, + JS_CORE_REF_AFFINITY_WOULD_VIOLATE, + katom->kctx, katom, katom->jc, js, + (u32) katom->affinity); + break; + } + + /* No affinity violations would result, so the cores are + * ready */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_READY; + /* *** BREAK OUT: Cores Ready *** */ + break; + + default: + KBASE_DEBUG_ASSERT_MSG(false, + "Unhandled kbase_atom_coreref_state %d", + katom->coreref_state); + break; + } + } while (retry != false); + + return (katom->coreref_state == KBASE_ATOM_COREREF_STATE_READY); +} + +static void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + switch (katom->coreref_state) { + case KBASE_ATOM_COREREF_STATE_READY: + /* State where atom was submitted to the HW - just proceed to + * power-down */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + + /* *** FALLTHROUGH *** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + /* State where cores were registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_release_cores(kbdev, katom->core_req & BASE_JD_REQ_T, + katom->affinity); + + break; + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + /* State where cores were requested, but not registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || + (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_unrequest_cores(kbdev, katom->core_req & BASE_JD_REQ_T, + katom->affinity); + break; + + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + /* Initial state - nothing required */ + KBASE_DEBUG_ASSERT(katom->affinity == 0); + break; + + default: + KBASE_DEBUG_ASSERT_MSG(false, + "Unhandled coreref_state: %d", + katom->coreref_state); + break; + } + + katom->affinity = 0; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; +} + +static void kbasep_js_job_check_deref_cores_nokatom(struct kbase_device *kbdev, + base_jd_core_req core_req, u64 affinity, + enum kbase_atom_coreref_state coreref_state) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + switch (coreref_state) { + case KBASE_ATOM_COREREF_STATE_READY: + /* State where atom was submitted to the HW - just proceed to + * power-down */ + KBASE_DEBUG_ASSERT(affinity != 0 || + (core_req & BASE_JD_REQ_T)); + + /* *** FALLTHROUGH *** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + /* State where cores were registered */ + KBASE_DEBUG_ASSERT(affinity != 0 || + (core_req & BASE_JD_REQ_T)); + kbase_pm_release_cores(kbdev, core_req & BASE_JD_REQ_T, + affinity); + + break; + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + /* State where cores were requested, but not registered */ + KBASE_DEBUG_ASSERT(affinity != 0 || + (core_req & BASE_JD_REQ_T)); + kbase_pm_unrequest_cores(kbdev, core_req & BASE_JD_REQ_T, + affinity); + break; + + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + /* Initial state - nothing required */ + KBASE_DEBUG_ASSERT(affinity == 0); + break; + + default: + KBASE_DEBUG_ASSERT_MSG(false, + "Unhandled coreref_state: %d", + coreref_state); + break; + } +} + +static void kbase_gpu_release_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + ktime_t *end_timestamp) +{ + struct kbase_context *kctx = katom->kctx; + + switch (katom->gpu_rb_state) { + case KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB: + /* Should be impossible */ + WARN(1, "Attempting to release atom not in ringbuffer\n"); + break; + + case KBASE_ATOM_GPU_RB_SUBMITTED: + /* Inform power management at start/finish of atom so it can + * update its GPU utilisation metrics. Mark atom as not + * submitted beforehand. */ + katom->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; + kbase_pm_metrics_update(kbdev, end_timestamp); + + if (katom->core_req & BASE_JD_REQ_PERMON) + kbase_pm_release_gpu_cycle_counter_nolock(kbdev); + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + KBASE_TLSTREAM_TL_NRET_ATOM_LPU(katom, + &kbdev->gpu_props.props.raw_props.js_features + [katom->slot_nr]); + KBASE_TLSTREAM_TL_NRET_ATOM_AS(katom, &kbdev->as[kctx->as_nr]); + KBASE_TLSTREAM_TL_NRET_CTX_LPU(kctx, + &kbdev->gpu_props.props.raw_props.js_features + [katom->slot_nr]); + + case KBASE_ATOM_GPU_RB_READY: + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_AFFINITY: + kbase_js_affinity_release_slot_cores(kbdev, katom->slot_nr, + katom->affinity); + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE: + break; + + case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION: + if (katom->protected_state.enter != + KBASE_ATOM_ENTER_PROTECTED_CHECK || + katom->protected_state.exit != + KBASE_ATOM_EXIT_PROTECTED_CHECK) + kbdev->protected_mode_transition = false; + + if (kbase_jd_katom_is_protected(katom) && + (katom->protected_state.enter == + KBASE_ATOM_ENTER_PROTECTED_IDLE_L2)) { + kbase_vinstr_resume(kbdev->vinstr_ctx); + + /* Go back to configured model for IPA */ + kbase_ipa_model_use_configured_locked(kbdev); + } + + + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV: + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_BLOCKED: + /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ + + case KBASE_ATOM_GPU_RB_RETURN_TO_JS: + break; + } + + katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_BLOCKED; + katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; +} + +static void kbase_gpu_mark_atom_for_return(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + kbase_gpu_release_atom(kbdev, katom, NULL); + katom->gpu_rb_state = KBASE_ATOM_GPU_RB_RETURN_TO_JS; +} + +static inline bool kbase_gpu_rmu_workaround(struct kbase_device *kbdev, int js) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + bool slot_busy[3]; + + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + return true; + slot_busy[0] = kbase_gpu_nr_atoms_on_slot_min(kbdev, 0, + KBASE_ATOM_GPU_RB_WAITING_AFFINITY); + slot_busy[1] = kbase_gpu_nr_atoms_on_slot_min(kbdev, 1, + KBASE_ATOM_GPU_RB_WAITING_AFFINITY); + slot_busy[2] = kbase_gpu_nr_atoms_on_slot_min(kbdev, 2, + KBASE_ATOM_GPU_RB_WAITING_AFFINITY); + + if ((js == 2 && !(slot_busy[0] || slot_busy[1])) || + (js != 2 && !slot_busy[2])) + return true; + + /* Don't submit slot 2 atom while GPU has jobs on slots 0/1 */ + if (js == 2 && (kbase_gpu_atoms_submitted(kbdev, 0) || + kbase_gpu_atoms_submitted(kbdev, 1) || + backend->rmu_workaround_flag)) + return false; + + /* Don't submit slot 0/1 atom while GPU has jobs on slot 2 */ + if (js != 2 && (kbase_gpu_atoms_submitted(kbdev, 2) || + !backend->rmu_workaround_flag)) + return false; + + backend->rmu_workaround_flag = !backend->rmu_workaround_flag; + + return true; +} + +/** + * other_slots_busy - Determine if any job slots other than @js are currently + * running atoms + * @kbdev: Device pointer + * @js: Job slot + * + * Return: true if any slots other than @js are busy, false otherwise + */ +static inline bool other_slots_busy(struct kbase_device *kbdev, int js) +{ + int slot; + + for (slot = 0; slot < kbdev->gpu_props.num_job_slots; slot++) { + if (slot == js) + continue; + + if (kbase_gpu_nr_atoms_on_slot_min(kbdev, slot, + KBASE_ATOM_GPU_RB_SUBMITTED)) + return true; + } + + return false; +} + +static inline bool kbase_gpu_in_protected_mode(struct kbase_device *kbdev) +{ + return kbdev->protected_mode; +} + +static int kbase_gpu_protected_mode_enter(struct kbase_device *kbdev) +{ + int err = -EINVAL; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ONCE(!kbdev->protected_ops, + "Cannot enter protected mode: protected callbacks not specified.\n"); + + /* + * When entering into protected mode, we must ensure that the + * GPU is not operating in coherent mode as well. This is to + * ensure that no protected memory can be leaked. + */ + if (kbdev->system_coherency == COHERENCY_ACE) + kbase_cache_set_coherency_mode(kbdev, COHERENCY_ACE_LITE); + + if (kbdev->protected_ops) { + /* Switch GPU to protected mode */ + err = kbdev->protected_ops->protected_mode_enable( + kbdev->protected_dev); + + if (err) + dev_warn(kbdev->dev, "Failed to enable protected mode: %d\n", + err); + else + kbdev->protected_mode = true; + } + + return err; +} + +static int kbase_gpu_protected_mode_reset(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ONCE(!kbdev->protected_ops, + "Cannot exit protected mode: protected callbacks not specified.\n"); + + if (!kbdev->protected_ops) + return -EINVAL; + + /* The protected mode disable callback will be called as part of reset + */ + kbase_reset_gpu_silent(kbdev); + + return 0; +} + +static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev, + struct kbase_jd_atom **katom, int idx, int js) +{ + int err = 0; + + switch (katom[idx]->protected_state.enter) { + case KBASE_ATOM_ENTER_PROTECTED_CHECK: + KBASE_TLSTREAM_AUX_PROTECTED_ENTER_START(kbdev); + /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV + * should ensure that we are not already transitiong, and that + * there are no atoms currently on the GPU. */ + WARN_ON(kbdev->protected_mode_transition); + WARN_ON(kbase_gpu_atoms_submitted_any(kbdev)); + + kbdev->protected_mode_transition = true; + katom[idx]->protected_state.enter = + KBASE_ATOM_ENTER_PROTECTED_VINSTR; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_ENTER_PROTECTED_VINSTR: + if (kbase_vinstr_try_suspend(kbdev->vinstr_ctx) < 0) { + /* + * We can't switch now because + * the vinstr core state switch + * is not done yet. + */ + return -EAGAIN; + } + + /* Use generic model for IPA in protected mode */ + kbase_ipa_model_use_fallback_locked(kbdev); + + /* Once reaching this point GPU must be + * switched to protected mode or vinstr + * re-enabled. */ + + /* + * Not in correct mode, begin protected mode switch. + * Entering protected mode requires us to power down the L2, + * and drop out of fully coherent mode. + */ + katom[idx]->protected_state.enter = + KBASE_ATOM_ENTER_PROTECTED_IDLE_L2; + + kbase_pm_update_cores_state_nolock(kbdev); + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_ENTER_PROTECTED_IDLE_L2: + /* Avoid unnecessary waiting on non-ACE platforms. */ + if (kbdev->current_gpu_coherency_mode == COHERENCY_ACE) { + if (kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2) || + kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_L2)) { + /* + * The L2 is still powered, wait for all the users to + * finish with it before doing the actual reset. + */ + return -EAGAIN; + } + } + + katom[idx]->protected_state.enter = + KBASE_ATOM_ENTER_PROTECTED_FINISHED; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_ENTER_PROTECTED_FINISHED: + + /* No jobs running, so we can switch GPU mode right now. */ + err = kbase_gpu_protected_mode_enter(kbdev); + + /* + * Regardless of result, we are no longer transitioning + * the GPU. + */ + kbdev->protected_mode_transition = false; + KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END(kbdev); + if (err) { + /* + * Failed to switch into protected mode, resume + * vinstr core and fail atom. + */ + kbase_vinstr_resume(kbdev->vinstr_ctx); + katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID; + kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); + /* Only return if head atom or previous atom + * already removed - as atoms must be returned + * in order. */ + if (idx == 0 || katom[0]->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { + kbase_gpu_dequeue_atom(kbdev, js, NULL); + kbase_jm_return_atom_to_js(kbdev, katom[idx]); + } + + /* Go back to configured model for IPA */ + kbase_ipa_model_use_configured_locked(kbdev); + + return -EINVAL; + } + + /* Protected mode sanity checks. */ + KBASE_DEBUG_ASSERT_MSG( + kbase_jd_katom_is_protected(katom[idx]) == + kbase_gpu_in_protected_mode(kbdev), + "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", + kbase_jd_katom_is_protected(katom[idx]), + kbase_gpu_in_protected_mode(kbdev)); + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_READY; + } + + return 0; +} + +static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev, + struct kbase_jd_atom **katom, int idx, int js) +{ + int err = 0; + + + switch (katom[idx]->protected_state.exit) { + case KBASE_ATOM_EXIT_PROTECTED_CHECK: + KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_START(kbdev); + /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV + * should ensure that we are not already transitiong, and that + * there are no atoms currently on the GPU. */ + WARN_ON(kbdev->protected_mode_transition); + WARN_ON(kbase_gpu_atoms_submitted_any(kbdev)); + + /* + * Exiting protected mode requires a reset, but first the L2 + * needs to be powered down to ensure it's not active when the + * reset is issued. + */ + katom[idx]->protected_state.exit = + KBASE_ATOM_EXIT_PROTECTED_IDLE_L2; + + kbdev->protected_mode_transition = true; + kbase_pm_update_cores_state_nolock(kbdev); + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + case KBASE_ATOM_EXIT_PROTECTED_IDLE_L2: + if (kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2) || + kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_L2)) { + /* + * The L2 is still powered, wait for all the users to + * finish with it before doing the actual reset. + */ + return -EAGAIN; + } + katom[idx]->protected_state.exit = + KBASE_ATOM_EXIT_PROTECTED_RESET; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_EXIT_PROTECTED_RESET: + /* Issue the reset to the GPU */ + err = kbase_gpu_protected_mode_reset(kbdev); + + if (err) { + kbdev->protected_mode_transition = false; + + /* Failed to exit protected mode, fail atom */ + katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID; + kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); + /* Only return if head atom or previous atom + * already removed - as atoms must be returned + * in order */ + if (idx == 0 || katom[0]->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { + kbase_gpu_dequeue_atom(kbdev, js, NULL); + kbase_jm_return_atom_to_js(kbdev, katom[idx]); + } + + kbase_vinstr_resume(kbdev->vinstr_ctx); + + /* Use generic model for IPA in protected mode */ + kbase_ipa_model_use_fallback_locked(kbdev); + + return -EINVAL; + } + + katom[idx]->protected_state.exit = + KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT: + /* A GPU reset is issued when exiting protected mode. Once the + * reset is done all atoms' state will also be reset. For this + * reason, if the atom is still in this state we can safely + * say that the reset has not completed i.e., we have not + * finished exiting protected mode yet. + */ + return -EAGAIN; + } + + return 0; +} + +void kbase_backend_slot_update(struct kbase_device *kbdev) +{ + int js; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + struct kbase_jd_atom *katom[2]; + int idx; + + katom[0] = kbase_gpu_inspect(kbdev, js, 0); + katom[1] = kbase_gpu_inspect(kbdev, js, 1); + WARN_ON(katom[1] && !katom[0]); + + for (idx = 0; idx < SLOT_RB_SIZE; idx++) { + bool cores_ready; + int ret; + + if (!katom[idx]) + continue; + + switch (katom[idx]->gpu_rb_state) { + case KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB: + /* Should be impossible */ + WARN(1, "Attempting to update atom not in ringbuffer\n"); + break; + + case KBASE_ATOM_GPU_RB_WAITING_BLOCKED: + if (katom[idx]->atom_flags & + KBASE_KATOM_FLAG_X_DEP_BLOCKED) + break; + + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV: + if (kbase_gpu_check_secure_atoms(kbdev, + !kbase_jd_katom_is_protected( + katom[idx]))) + break; + + if ((idx == 1) && (kbase_jd_katom_is_protected( + katom[0]) != + kbase_jd_katom_is_protected( + katom[1]))) + break; + + if (kbdev->protected_mode_transition) + break; + + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION: + + /* + * Exiting protected mode must be done before + * the references on the cores are taken as + * a power down the L2 is required which + * can't happen after the references for this + * atom are taken. + */ + + if (!kbase_gpu_in_protected_mode(kbdev) && + kbase_jd_katom_is_protected(katom[idx])) { + /* Atom needs to transition into protected mode. */ + ret = kbase_jm_enter_protected_mode(kbdev, + katom, idx, js); + if (ret) + break; + } else if (kbase_gpu_in_protected_mode(kbdev) && + !kbase_jd_katom_is_protected(katom[idx])) { + /* Atom needs to transition out of protected mode. */ + ret = kbase_jm_exit_protected_mode(kbdev, + katom, idx, js); + if (ret) + break; + } + katom[idx]->protected_state.exit = + KBASE_ATOM_EXIT_PROTECTED_CHECK; + + /* Atom needs no protected mode transition. */ + + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE: + if (katom[idx]->will_fail_event_code) { + kbase_gpu_mark_atom_for_return(kbdev, + katom[idx]); + /* Set EVENT_DONE so this atom will be + completed, not unpulled. */ + katom[idx]->event_code = + BASE_JD_EVENT_DONE; + /* Only return if head atom or previous + * atom already removed - as atoms must + * be returned in order. */ + if (idx == 0 || katom[0]->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { + kbase_gpu_dequeue_atom(kbdev, js, NULL); + kbase_jm_return_atom_to_js(kbdev, katom[idx]); + } + break; + } + + cores_ready = + kbasep_js_job_check_ref_cores(kbdev, js, + katom[idx]); + + if (katom[idx]->event_code == + BASE_JD_EVENT_PM_EVENT) { + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_RETURN_TO_JS; + break; + } + + if (!cores_ready) + break; + + kbase_js_affinity_retain_slot_cores(kbdev, js, + katom[idx]->affinity); + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_WAITING_AFFINITY; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_WAITING_AFFINITY: + if (!kbase_gpu_rmu_workaround(kbdev, js)) + break; + + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_READY; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_READY: + + if (idx == 1) { + /* Only submit if head atom or previous + * atom already submitted */ + if ((katom[0]->gpu_rb_state != + KBASE_ATOM_GPU_RB_SUBMITTED && + katom[0]->gpu_rb_state != + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB)) + break; + + /* If intra-slot serialization in use + * then don't submit atom to NEXT slot + */ + if (kbdev->serialize_jobs & + KBASE_SERIALIZE_INTRA_SLOT) + break; + } + + /* If inter-slot serialization in use then don't + * submit atom if any other slots are in use */ + if ((kbdev->serialize_jobs & + KBASE_SERIALIZE_INTER_SLOT) && + other_slots_busy(kbdev, js)) + break; + + if ((kbdev->serialize_jobs & + KBASE_SERIALIZE_RESET) && + kbase_reset_gpu_active(kbdev)) + break; + + /* Check if this job needs the cycle counter + * enabled before submission */ + if (katom[idx]->core_req & BASE_JD_REQ_PERMON) + kbase_pm_request_gpu_cycle_counter_l2_is_on( + kbdev); + + kbase_job_hw_submit(kbdev, katom[idx], js); + katom[idx]->gpu_rb_state = + KBASE_ATOM_GPU_RB_SUBMITTED; + + /* Inform power management at start/finish of + * atom so it can update its GPU utilisation + * metrics. */ + kbase_pm_metrics_update(kbdev, + &katom[idx]->start_timestamp); + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_GPU_RB_SUBMITTED: + /* Atom submitted to HW, nothing else to do */ + break; + + case KBASE_ATOM_GPU_RB_RETURN_TO_JS: + /* Only return if head atom or previous atom + * already removed - as atoms must be returned + * in order */ + if (idx == 0 || katom[0]->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { + kbase_gpu_dequeue_atom(kbdev, js, NULL); + kbase_jm_return_atom_to_js(kbdev, + katom[idx]); + } + break; + } + } + } + + /* Warn if PRLAM-8987 affinity restrictions are violated */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + WARN_ON((kbase_gpu_atoms_submitted(kbdev, 0) || + kbase_gpu_atoms_submitted(kbdev, 1)) && + kbase_gpu_atoms_submitted(kbdev, 2)); +} + + +void kbase_backend_run_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + kbase_gpu_enqueue_atom(kbdev, katom); + kbase_backend_slot_update(kbdev); +} + +#define HAS_DEP(katom) (katom->pre_dep || katom->atom_flags & \ + (KBASE_KATOM_FLAG_X_DEP_BLOCKED | KBASE_KATOM_FLAG_FAIL_BLOCKER)) + +bool kbase_gpu_irq_evict(struct kbase_device *kbdev, int js) +{ + struct kbase_jd_atom *katom; + struct kbase_jd_atom *next_katom; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + katom = kbase_gpu_inspect(kbdev, js, 0); + next_katom = kbase_gpu_inspect(kbdev, js, 1); + + if (next_katom && katom->kctx == next_katom->kctx && + next_katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED && + HAS_DEP(next_katom) && + (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) + != 0 || + kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) + != 0)) { + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), + JS_COMMAND_NOP, NULL); + next_katom->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; + + KBASE_TLSTREAM_TL_NRET_ATOM_LPU(katom, + &kbdev->gpu_props.props.raw_props.js_features + [katom->slot_nr]); + KBASE_TLSTREAM_TL_NRET_ATOM_AS(katom, &kbdev->as + [katom->kctx->as_nr]); + KBASE_TLSTREAM_TL_NRET_CTX_LPU(katom->kctx, + &kbdev->gpu_props.props.raw_props.js_features + [katom->slot_nr]); + + return true; + } + + return false; +} + +void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js, + u32 completion_code, + u64 job_tail, + ktime_t *end_timestamp) +{ + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, 0); + struct kbase_context *kctx = katom->kctx; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* + * When a hard-stop is followed close after a soft-stop, the completion + * code may be set to STOPPED, even though the job is terminated + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8438)) { + if (completion_code == BASE_JD_EVENT_STOPPED && + (katom->atom_flags & + KBASE_KATOM_FLAG_BEEN_HARD_STOPPED)) { + completion_code = BASE_JD_EVENT_TERMINATED; + } + } + + if ((kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6787) || (katom->core_req & + BASE_JD_REQ_SKIP_CACHE_END)) && + completion_code != BASE_JD_EVENT_DONE && + !(completion_code & BASE_JD_SW_EVENT)) { + /* When a job chain fails, on a T60x or when + * BASE_JD_REQ_SKIP_CACHE_END is set, the GPU cache is not + * flushed. To prevent future evictions causing possible memory + * corruption we need to flush the cache manually before any + * affected memory gets reused. */ + katom->need_cache_flush_cores_retained = katom->affinity; + kbase_pm_request_cores(kbdev, false, katom->affinity); + } else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10676)) { + if (kbdev->gpu_props.num_core_groups > 1 && + !(katom->affinity & + kbdev->gpu_props.props.coherency_info.group[0].core_mask + ) && + (katom->affinity & + kbdev->gpu_props.props.coherency_info.group[1].core_mask + )) { + dev_info(kbdev->dev, "JD: Flushing cache due to PRLAM-10676\n"); + katom->need_cache_flush_cores_retained = + katom->affinity; + kbase_pm_request_cores(kbdev, false, + katom->affinity); + } + } + + katom = kbase_gpu_dequeue_atom(kbdev, js, end_timestamp); + kbase_timeline_job_slot_done(kbdev, katom->kctx, katom, js, 0); + + if (completion_code == BASE_JD_EVENT_STOPPED) { + struct kbase_jd_atom *next_katom = kbase_gpu_inspect(kbdev, js, + 0); + + /* + * Dequeue next atom from ringbuffers on same slot if required. + * This atom will already have been removed from the NEXT + * registers by kbase_gpu_soft_hard_stop_slot(), to ensure that + * the atoms on this slot are returned in the correct order. + */ + if (next_katom && katom->kctx == next_katom->kctx && + next_katom->sched_priority == + katom->sched_priority) { + kbase_gpu_dequeue_atom(kbdev, js, end_timestamp); + kbase_jm_return_atom_to_js(kbdev, next_katom); + } + } else if (completion_code != BASE_JD_EVENT_DONE) { + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + int i; + +#if KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR != 0 + KBASE_TRACE_DUMP(kbdev); +#endif + kbasep_js_clear_submit_allowed(js_devdata, katom->kctx); + + /* + * Remove all atoms on the same context from ringbuffers. This + * will not remove atoms that are already on the GPU, as these + * are guaranteed not to have fail dependencies on the failed + * atom. + */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { + struct kbase_jd_atom *katom_idx0 = + kbase_gpu_inspect(kbdev, i, 0); + struct kbase_jd_atom *katom_idx1 = + kbase_gpu_inspect(kbdev, i, 1); + + if (katom_idx0 && katom_idx0->kctx == katom->kctx && + HAS_DEP(katom_idx0) && + katom_idx0->gpu_rb_state != + KBASE_ATOM_GPU_RB_SUBMITTED) { + /* Dequeue katom_idx0 from ringbuffer */ + kbase_gpu_dequeue_atom(kbdev, i, end_timestamp); + + if (katom_idx1 && + katom_idx1->kctx == katom->kctx + && HAS_DEP(katom_idx1) && + katom_idx0->gpu_rb_state != + KBASE_ATOM_GPU_RB_SUBMITTED) { + /* Dequeue katom_idx1 from ringbuffer */ + kbase_gpu_dequeue_atom(kbdev, i, + end_timestamp); + + katom_idx1->event_code = + BASE_JD_EVENT_STOPPED; + kbase_jm_return_atom_to_js(kbdev, + katom_idx1); + } + katom_idx0->event_code = BASE_JD_EVENT_STOPPED; + kbase_jm_return_atom_to_js(kbdev, katom_idx0); + + } else if (katom_idx1 && + katom_idx1->kctx == katom->kctx && + HAS_DEP(katom_idx1) && + katom_idx1->gpu_rb_state != + KBASE_ATOM_GPU_RB_SUBMITTED) { + /* Can not dequeue this atom yet - will be + * dequeued when atom at idx0 completes */ + katom_idx1->event_code = BASE_JD_EVENT_STOPPED; + kbase_gpu_mark_atom_for_return(kbdev, + katom_idx1); + } + } + } + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, kctx, katom, katom->jc, + js, completion_code); + + if (job_tail != 0 && job_tail != katom->jc) { + bool was_updated = (job_tail != katom->jc); + + /* Some of the job has been executed, so we update the job chain + * address to where we should resume from */ + katom->jc = job_tail; + if (was_updated) + KBASE_TRACE_ADD_SLOT(kbdev, JM_UPDATE_HEAD, katom->kctx, + katom, job_tail, js); + } + + /* Only update the event code for jobs that weren't cancelled */ + if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED) + katom->event_code = (base_jd_event_code)completion_code; + + kbase_device_trace_register_access(kctx, REG_WRITE, + JOB_CONTROL_REG(JOB_IRQ_CLEAR), + 1 << js); + + /* Complete the job, and start new ones + * + * Also defer remaining work onto the workqueue: + * - Re-queue Soft-stopped jobs + * - For any other jobs, queue the job back into the dependency system + * - Schedule out the parent context if necessary, and schedule a new + * one in. + */ +#ifdef CONFIG_GPU_TRACEPOINTS + { + /* The atom in the HEAD */ + struct kbase_jd_atom *next_katom = kbase_gpu_inspect(kbdev, js, + 0); + + if (next_katom && next_katom->gpu_rb_state == + KBASE_ATOM_GPU_RB_SUBMITTED) { + char js_string[16]; + + trace_gpu_sched_switch(kbasep_make_job_slot_string(js, + js_string, + sizeof(js_string)), + ktime_to_ns(*end_timestamp), + (u32)next_katom->kctx->id, 0, + next_katom->work_id); + kbdev->hwaccess.backend.slot_rb[js].last_context = + next_katom->kctx; + } else { + char js_string[16]; + + trace_gpu_sched_switch(kbasep_make_job_slot_string(js, + js_string, + sizeof(js_string)), + ktime_to_ns(ktime_get()), 0, 0, + 0); + kbdev->hwaccess.backend.slot_rb[js].last_context = 0; + } + } +#endif + + if (kbdev->serialize_jobs & KBASE_SERIALIZE_RESET) + kbase_reset_gpu_silent(kbdev); + + if (completion_code == BASE_JD_EVENT_STOPPED) + katom = kbase_jm_return_atom_to_js(kbdev, katom); + else + katom = kbase_jm_complete(kbdev, katom, end_timestamp); + + if (katom) { + /* Cross-slot dependency has now become runnable. Try to submit + * it. */ + + /* Check if there are lower priority jobs to soft stop */ + kbase_job_slot_ctx_priority_check_locked(kctx, katom); + + kbase_jm_try_kick(kbdev, 1 << katom->slot_nr); + } + + /* Job completion may have unblocked other atoms. Try to update all job + * slots */ + kbase_backend_slot_update(kbdev); +} + +void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp) +{ + int js; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* Reset should always take the GPU out of protected mode */ + WARN_ON(kbase_gpu_in_protected_mode(kbdev)); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + int atom_idx = 0; + int idx; + + for (idx = 0; idx < SLOT_RB_SIZE; idx++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, + js, atom_idx); + bool keep_in_jm_rb = false; + + if (!katom) + break; + if (katom->protected_state.exit == + KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT) + { + KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END(kbdev); + + kbase_vinstr_resume(kbdev->vinstr_ctx); + + /* protected mode sanity checks */ + KBASE_DEBUG_ASSERT_MSG( + kbase_jd_katom_is_protected(katom) == kbase_gpu_in_protected_mode(kbdev), + "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", + kbase_jd_katom_is_protected(katom), kbase_gpu_in_protected_mode(kbdev)); + KBASE_DEBUG_ASSERT_MSG( + (kbase_jd_katom_is_protected(katom) && js == 0) || + !kbase_jd_katom_is_protected(katom), + "Protected atom on JS%d not supported", js); + } + if (katom->gpu_rb_state < KBASE_ATOM_GPU_RB_SUBMITTED) + keep_in_jm_rb = true; + + kbase_gpu_release_atom(kbdev, katom, NULL); + + /* + * If the atom wasn't on HW when the reset was issued + * then leave it in the RB and next time we're kicked + * it will be processed again from the starting state. + */ + if (keep_in_jm_rb) { + kbasep_js_job_check_deref_cores(kbdev, katom); + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; + katom->affinity = 0; + katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; + /* As the atom was not removed, increment the + * index so that we read the correct atom in the + * next iteration. */ + atom_idx++; + continue; + } + + /* + * The atom was on the HW when the reset was issued + * all we can do is fail the atom. + */ + kbase_gpu_dequeue_atom(kbdev, js, NULL); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + kbase_jm_complete(kbdev, katom, end_timestamp); + } + } + + kbdev->protected_mode_transition = false; +} + +static inline void kbase_gpu_stop_atom(struct kbase_device *kbdev, + int js, + struct kbase_jd_atom *katom, + u32 action) +{ + u32 hw_action = action & JS_COMMAND_MASK; + + kbase_job_check_enter_disjoint(kbdev, action, katom->core_req, katom); + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, js, hw_action, + katom->core_req, katom); + katom->kctx->blocked_js[js][katom->sched_priority] = true; +} + +static inline void kbase_gpu_remove_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + u32 action, + bool disjoint) +{ + katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; + kbase_gpu_mark_atom_for_return(kbdev, katom); + katom->kctx->blocked_js[katom->slot_nr][katom->sched_priority] = true; + + if (disjoint) + kbase_job_check_enter_disjoint(kbdev, action, katom->core_req, + katom); +} + +static int should_stop_x_dep_slot(struct kbase_jd_atom *katom) +{ + if (katom->x_post_dep) { + struct kbase_jd_atom *dep_atom = katom->x_post_dep; + + if (dep_atom->gpu_rb_state != + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB && + dep_atom->gpu_rb_state != + KBASE_ATOM_GPU_RB_RETURN_TO_JS) + return dep_atom->slot_nr; + } + return -1; +} + +static void kbase_job_evicted(struct kbase_jd_atom *katom) +{ + kbase_timeline_job_slot_done(katom->kctx->kbdev, katom->kctx, katom, + katom->slot_nr, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); +} + +bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js, + struct kbase_jd_atom *katom, + u32 action) +{ + struct kbase_jd_atom *katom_idx0; + struct kbase_jd_atom *katom_idx1; + + bool katom_idx0_valid, katom_idx1_valid; + + bool ret = false; + + int stop_x_dep_idx0 = -1, stop_x_dep_idx1 = -1; + int prio_idx0 = 0, prio_idx1 = 0; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + katom_idx0 = kbase_gpu_inspect(kbdev, js, 0); + katom_idx1 = kbase_gpu_inspect(kbdev, js, 1); + + if (katom_idx0) + prio_idx0 = katom_idx0->sched_priority; + if (katom_idx1) + prio_idx1 = katom_idx1->sched_priority; + + if (katom) { + katom_idx0_valid = (katom_idx0 == katom); + /* If idx0 is to be removed and idx1 is on the same context, + * then idx1 must also be removed otherwise the atoms might be + * returned out of order */ + if (katom_idx1) + katom_idx1_valid = (katom_idx1 == katom) || + (katom_idx0_valid && + (katom_idx0->kctx == + katom_idx1->kctx)); + else + katom_idx1_valid = false; + } else { + katom_idx0_valid = (katom_idx0 && + (!kctx || katom_idx0->kctx == kctx)); + katom_idx1_valid = (katom_idx1 && + (!kctx || katom_idx1->kctx == kctx) && + prio_idx0 == prio_idx1); + } + + if (katom_idx0_valid) + stop_x_dep_idx0 = should_stop_x_dep_slot(katom_idx0); + if (katom_idx1_valid) + stop_x_dep_idx1 = should_stop_x_dep_slot(katom_idx1); + + if (katom_idx0_valid) { + if (katom_idx0->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { + /* Simple case - just dequeue and return */ + kbase_gpu_dequeue_atom(kbdev, js, NULL); + if (katom_idx1_valid) { + kbase_gpu_dequeue_atom(kbdev, js, NULL); + katom_idx1->event_code = + BASE_JD_EVENT_REMOVED_FROM_NEXT; + kbase_jm_return_atom_to_js(kbdev, katom_idx1); + katom_idx1->kctx->blocked_js[js][prio_idx1] = + true; + } + + katom_idx0->event_code = + BASE_JD_EVENT_REMOVED_FROM_NEXT; + kbase_jm_return_atom_to_js(kbdev, katom_idx0); + katom_idx0->kctx->blocked_js[js][prio_idx0] = true; + } else { + /* katom_idx0 is on GPU */ + if (katom_idx1 && katom_idx1->gpu_rb_state == + KBASE_ATOM_GPU_RB_SUBMITTED) { + /* katom_idx0 and katom_idx1 are on GPU */ + + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, + JS_COMMAND_NEXT), NULL) == 0) { + /* idx0 has already completed - stop + * idx1 if needed*/ + if (katom_idx1_valid) { + kbase_gpu_stop_atom(kbdev, js, + katom_idx1, + action); + ret = true; + } + } else { + /* idx1 is in NEXT registers - attempt + * to remove */ + kbase_reg_write(kbdev, + JOB_SLOT_REG(js, + JS_COMMAND_NEXT), + JS_COMMAND_NOP, NULL); + + if (kbase_reg_read(kbdev, + JOB_SLOT_REG(js, + JS_HEAD_NEXT_LO), NULL) + != 0 || + kbase_reg_read(kbdev, + JOB_SLOT_REG(js, + JS_HEAD_NEXT_HI), NULL) + != 0) { + /* idx1 removed successfully, + * will be handled in IRQ */ + kbase_job_evicted(katom_idx1); + kbase_gpu_remove_atom(kbdev, + katom_idx1, + action, true); + stop_x_dep_idx1 = + should_stop_x_dep_slot(katom_idx1); + + /* stop idx0 if still on GPU */ + kbase_gpu_stop_atom(kbdev, js, + katom_idx0, + action); + ret = true; + } else if (katom_idx1_valid) { + /* idx0 has already completed, + * stop idx1 if needed */ + kbase_gpu_stop_atom(kbdev, js, + katom_idx1, + action); + ret = true; + } + } + } else if (katom_idx1_valid) { + /* idx1 not on GPU but must be dequeued*/ + + /* idx1 will be handled in IRQ */ + kbase_gpu_remove_atom(kbdev, katom_idx1, action, + false); + /* stop idx0 */ + /* This will be repeated for anything removed + * from the next registers, since their normal + * flow was also interrupted, and this function + * might not enter disjoint state e.g. if we + * don't actually do a hard stop on the head + * atom */ + kbase_gpu_stop_atom(kbdev, js, katom_idx0, + action); + ret = true; + } else { + /* no atom in idx1 */ + /* just stop idx0 */ + kbase_gpu_stop_atom(kbdev, js, katom_idx0, + action); + ret = true; + } + } + } else if (katom_idx1_valid) { + if (katom_idx1->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { + /* Mark for return */ + /* idx1 will be returned once idx0 completes */ + kbase_gpu_remove_atom(kbdev, katom_idx1, action, + false); + } else { + /* idx1 is on GPU */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, + JS_COMMAND_NEXT), NULL) == 0) { + /* idx0 has already completed - stop idx1 */ + kbase_gpu_stop_atom(kbdev, js, katom_idx1, + action); + ret = true; + } else { + /* idx1 is in NEXT registers - attempt to + * remove */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, + JS_COMMAND_NEXT), + JS_COMMAND_NOP, NULL); + + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, + JS_HEAD_NEXT_LO), NULL) != 0 || + kbase_reg_read(kbdev, JOB_SLOT_REG(js, + JS_HEAD_NEXT_HI), NULL) != 0) { + /* idx1 removed successfully, will be + * handled in IRQ once idx0 completes */ + kbase_job_evicted(katom_idx1); + kbase_gpu_remove_atom(kbdev, katom_idx1, + action, + false); + } else { + /* idx0 has already completed - stop + * idx1 */ + kbase_gpu_stop_atom(kbdev, js, + katom_idx1, + action); + ret = true; + } + } + } + } + + + if (stop_x_dep_idx0 != -1) + kbase_backend_soft_hard_stop_slot(kbdev, kctx, stop_x_dep_idx0, + NULL, action); + + if (stop_x_dep_idx1 != -1) + kbase_backend_soft_hard_stop_slot(kbdev, kctx, stop_x_dep_idx1, + NULL, action); + + return ret; +} + +void kbase_gpu_cacheclean(struct kbase_device *kbdev) +{ + /* Limit the number of loops to avoid a hang if the interrupt is missed + */ + u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; + + mutex_lock(&kbdev->cacheclean_lock); + + /* use GPU_COMMAND completion solution */ + /* clean & invalidate the caches */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CLEAN_INV_CACHES, NULL); + + /* wait for cache flush to complete before continuing */ + while (--max_loops && + (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & + CLEAN_CACHES_COMPLETED) == 0) + ; + + /* clear the CLEAN_CACHES_COMPLETED irq */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, + CLEAN_CACHES_COMPLETED); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), + CLEAN_CACHES_COMPLETED, NULL); + KBASE_DEBUG_ASSERT_MSG(kbdev->hwcnt.backend.state != + KBASE_INSTR_STATE_CLEANING, + "Instrumentation code was cleaning caches, but Job Management code cleared their IRQ - Instrumentation code will now hang."); + + mutex_unlock(&kbdev->cacheclean_lock); +} + +void kbase_backend_cacheclean(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + if (katom->need_cache_flush_cores_retained) { + unsigned long flags; + + kbase_gpu_cacheclean(kbdev); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_unrequest_cores(kbdev, false, + katom->need_cache_flush_cores_retained); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + katom->need_cache_flush_cores_retained = 0; + } +} + +void kbase_backend_complete_wq(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + /* + * If cache flush required due to HW workaround then perform the flush + * now + */ + kbase_backend_cacheclean(kbdev, katom); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10969) && + (katom->core_req & BASE_JD_REQ_FS) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT && + (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED) && + !(katom->atom_flags & KBASE_KATOM_FLAGS_RERUN)) { + dev_dbg(kbdev->dev, "Soft-stopped fragment shader job got a TILE_RANGE_FAULT. Possible HW issue, trying SW workaround\n"); + if (kbasep_10969_workaround_clamp_coordinates(katom)) { + /* The job had a TILE_RANGE_FAULT after was soft-stopped + * Due to an HW issue we try to execute the job again. + */ + dev_dbg(kbdev->dev, + "Clamping has been executed, try to rerun the job\n" + ); + katom->event_code = BASE_JD_EVENT_STOPPED; + katom->atom_flags |= KBASE_KATOM_FLAGS_RERUN; + } + } + + /* Clear the coreref_state now - while check_deref_cores() may not have + * been called yet, the caller will have taken a copy of this field. If + * this is not done, then if the atom is re-scheduled (following a soft + * stop) then the core reference would not be retaken. */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; + katom->affinity = 0; +} + +void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev, + base_jd_core_req core_req, u64 affinity, + enum kbase_atom_coreref_state coreref_state) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbasep_js_job_check_deref_cores_nokatom(kbdev, core_req, affinity, + coreref_state); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + if (!kbdev->pm.active_count) { + mutex_lock(&kbdev->js_data.runpool_mutex); + mutex_lock(&kbdev->pm.lock); + kbase_pm_update_active(kbdev); + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&kbdev->js_data.runpool_mutex); + } +} + +void kbase_gpu_dump_slots(struct kbase_device *kbdev) +{ + unsigned long flags; + int js; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + dev_info(kbdev->dev, "kbase_gpu_dump_slots:\n"); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + int idx; + + for (idx = 0; idx < SLOT_RB_SIZE; idx++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, + js, + idx); + + if (katom) + dev_info(kbdev->dev, + " js%d idx%d : katom=%p gpu_rb_state=%d\n", + js, idx, katom, katom->gpu_rb_state); + else + dev_info(kbdev->dev, " js%d idx%d : empty\n", + js, idx); + } + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + + + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.h new file mode 100644 index 000000000000..1e0e05ad3ea4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.h @@ -0,0 +1,76 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend specific APIs + */ + +#ifndef _KBASE_HWACCESS_GPU_H_ +#define _KBASE_HWACCESS_GPU_H_ + +#include + +/** + * kbase_gpu_irq_evict - Evict an atom from a NEXT slot + * + * @kbdev: Device pointer + * @js: Job slot to evict from + * + * Evict the atom in the NEXT slot for the specified job slot. This function is + * called from the job complete IRQ handler when the previous job has failed. + * + * Return: true if job evicted from NEXT registers, false otherwise + */ +bool kbase_gpu_irq_evict(struct kbase_device *kbdev, int js); + +/** + * kbase_gpu_complete_hw - Complete an atom on job slot js + * + * @kbdev: Device pointer + * @js: Job slot that has completed + * @completion_code: Event code from job that has completed + * @job_tail: The tail address from the hardware if the job has partially + * completed + * @end_timestamp: Time of completion + */ +void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js, + u32 completion_code, + u64 job_tail, + ktime_t *end_timestamp); + +/** + * kbase_gpu_inspect - Inspect the contents of the HW access ringbuffer + * + * @kbdev: Device pointer + * @js: Job slot to inspect + * @idx: Index into ringbuffer. 0 is the job currently running on + * the slot, 1 is the job waiting, all other values are invalid. + * Return: The atom at that position in the ringbuffer + * or NULL if no atom present + */ +struct kbase_jd_atom *kbase_gpu_inspect(struct kbase_device *kbdev, int js, + int idx); + +/** + * kbase_gpu_dump_slots - Print the contents of the slot ringbuffers + * + * @kbdev: Device pointer + */ +void kbase_gpu_dump_slots(struct kbase_device *kbdev); + +#endif /* _KBASE_HWACCESS_GPU_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.c new file mode 100644 index 000000000000..54d8ddd80097 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.c @@ -0,0 +1,303 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel affinity manager APIs + */ + +#include +#include "mali_kbase_js_affinity.h" +#include "mali_kbase_hw.h" + +#include + + +bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, + int js) +{ + /* + * Here are the reasons for using job slot 2: + * - BASE_HW_ISSUE_8987 (which is entirely used for that purpose) + * - In absence of the above, then: + * - Atoms with BASE_JD_REQ_COHERENT_GROUP + * - But, only when there aren't contexts with + * KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, because the atoms that run on + * all cores on slot 1 could be blocked by those using a coherent group + * on slot 2 + * - And, only when you actually have 2 or more coregroups - if you + * only have 1 coregroup, then having jobs for slot 2 implies they'd + * also be for slot 1, meaning you'll get interference from them. Jobs + * able to run on slot 2 could also block jobs that can only run on + * slot 1 (tiler jobs) + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + return true; + + if (js != 2) + return true; + + /* Only deal with js==2 now: */ + if (kbdev->gpu_props.num_core_groups > 1) { + /* Only use slot 2 in the 2+ coregroup case */ + if (kbasep_js_ctx_attr_is_attr_on_runpool(kbdev, + KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES) == + false) { + /* ...But only when we *don't* have atoms that run on + * all cores */ + + /* No specific check for BASE_JD_REQ_COHERENT_GROUP + * atoms - the policy will sort that out */ + return true; + } + } + + /* Above checks failed mean we shouldn't use slot 2 */ + return false; +} + +/* + * As long as it has been decided to have a deeper modification of + * what job scheduler, power manager and affinity manager will + * implement, this function is just an intermediate step that + * assumes: + * - all working cores will be powered on when this is called. + * - largest current configuration is 2 core groups. + * - It has been decided not to have hardcoded values so the low + * and high cores in a core split will be evently distributed. + * - Odd combinations of core requirements have been filtered out + * and do not get to this function (e.g. CS+T+NSS is not + * supported here). + * - This function is frequently called and can be optimized, + * (see notes in loops), but as the functionallity will likely + * be modified, optimization has not been addressed. +*/ +bool kbase_js_choose_affinity(u64 * const affinity, + struct kbase_device *kbdev, + struct kbase_jd_atom *katom, int js) +{ + base_jd_core_req core_req = katom->core_req; + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + u64 core_availability_mask; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + core_availability_mask = kbase_pm_ca_get_core_mask(kbdev); + + /* + * If no cores are currently available (core availability policy is + * transitioning) then fail. + */ + if (0 == core_availability_mask) { + *affinity = 0; + return false; + } + + KBASE_DEBUG_ASSERT(js >= 0); + + if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) == + BASE_JD_REQ_T) { + /* If the hardware supports XAFFINITY then we'll only enable + * the tiler (which is the default so this is a no-op), + * otherwise enable shader core 0. */ + if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY)) + *affinity = 1; + else + *affinity = 0; + + return true; + } + + if (1 == kbdev->gpu_props.num_cores) { + /* trivial case only one core, nothing to do */ + *affinity = core_availability_mask & + kbdev->pm.debug_core_mask[js]; + } else { + if ((core_req & (BASE_JD_REQ_COHERENT_GROUP | + BASE_JD_REQ_SPECIFIC_COHERENT_GROUP))) { + if (js == 0 || num_core_groups == 1) { + /* js[0] and single-core-group systems just get + * the first core group */ + *affinity = + kbdev->gpu_props.props.coherency_info.group[0].core_mask + & core_availability_mask & + kbdev->pm.debug_core_mask[js]; + } else { + /* js[1], js[2] use core groups 0, 1 for + * dual-core-group systems */ + u32 core_group_idx = ((u32) js) - 1; + + KBASE_DEBUG_ASSERT(core_group_idx < + num_core_groups); + *affinity = + kbdev->gpu_props.props.coherency_info.group[core_group_idx].core_mask + & core_availability_mask & + kbdev->pm.debug_core_mask[js]; + + /* If the job is specifically targeting core + * group 1 and the core availability policy is + * keeping that core group off, then fail */ + if (*affinity == 0 && core_group_idx == 1 && + kbdev->pm.backend.cg1_disabled + == true) + katom->event_code = + BASE_JD_EVENT_PM_EVENT; + } + } else { + /* All cores are available when no core split is + * required */ + *affinity = core_availability_mask & + kbdev->pm.debug_core_mask[js]; + } + } + + /* + * If no cores are currently available in the desired core group(s) + * (core availability policy is transitioning) then fail. + */ + if (*affinity == 0) + return false; + + /* Enable core 0 if tiler required for hardware without XAFFINITY + * support (notes above) */ + if (core_req & BASE_JD_REQ_T) { + if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY)) + *affinity = *affinity | 1; + } + + return true; +} + +static inline bool kbase_js_affinity_is_violating( + struct kbase_device *kbdev, + u64 *affinities) +{ + /* This implementation checks whether the two slots involved in Generic + * thread creation have intersecting affinity. This is due to micro- + * architectural issues where a job in slot A targetting cores used by + * slot B could prevent the job in slot B from making progress until the + * job in slot A has completed. + */ + u64 affinity_set_left; + u64 affinity_set_right; + u64 intersection; + + KBASE_DEBUG_ASSERT(affinities != NULL); + + affinity_set_left = affinities[1]; + + affinity_set_right = affinities[2]; + + /* A violation occurs when any bit in the left_set is also in the + * right_set */ + intersection = affinity_set_left & affinity_set_right; + + return (bool) (intersection != (u64) 0u); +} + +bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, + u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 new_affinities[BASE_JM_MAX_NR_SLOTS]; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + memcpy(new_affinities, js_devdata->runpool_irq.slot_affinities, + sizeof(js_devdata->runpool_irq.slot_affinities)); + + new_affinities[js] |= affinity; + + return kbase_js_affinity_is_violating(kbdev, new_affinities); +} + +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, + u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(kbase_js_affinity_would_violate(kbdev, js, affinity) + == false); + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + cnt = + ++(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (cnt == 1) + js_devdata->runpool_irq.slot_affinities[js] |= bit; + + cores &= ~bit; + } +} + +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, + u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + KBASE_DEBUG_ASSERT( + js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum] > 0); + + cnt = + --(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (0 == cnt) + js_devdata->runpool_irq.slot_affinities[js] &= ~bit; + + cores &= ~bit; + } +} + +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int slot_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + for (slot_nr = 0; slot_nr < 3; ++slot_nr) + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_AFFINITY_CURRENT, NULL, + NULL, 0u, slot_nr, + (u32) js_devdata->runpool_irq.slot_affinities[slot_nr]); +} +#endif /* KBASE_TRACE_ENABLE */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.h new file mode 100644 index 000000000000..35d9781ae092 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_affinity.h @@ -0,0 +1,129 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Affinity Manager internal APIs. + */ + +#ifndef _KBASE_JS_AFFINITY_H_ +#define _KBASE_JS_AFFINITY_H_ + +/** + * kbase_js_can_run_job_on_slot_no_lock - Decide whether it is possible to + * submit a job to a particular job slot in the current status + * + * @kbdev: The kbase device structure of the device + * @js: Job slot number to check for allowance + * + * Will check if submitting to the given job slot is allowed in the current + * status. For example using job slot 2 while in soft-stoppable state and only + * having 1 coregroup is not allowed by the policy. This function should be + * called prior to submitting a job to a slot to make sure policy rules are not + * violated. + * + * The following locking conditions are made on the caller + * - it must hold hwaccess_lock + */ +bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, int js); + +/** + * kbase_js_choose_affinity - Compute affinity for a given job. + * + * @affinity: Affinity bitmap computed + * @kbdev: The kbase device structure of the device + * @katom: Job chain of which affinity is going to be found + * @js: Slot the job chain is being submitted + * + * Currently assumes an all-on/all-off power management policy. + * Also assumes there is at least one core with tiler available. + * + * Returns true if a valid affinity was chosen, false if + * no cores were available. + */ +bool kbase_js_choose_affinity(u64 * const affinity, + struct kbase_device *kbdev, + struct kbase_jd_atom *katom, + int js); + +/** + * kbase_js_affinity_would_violate - Determine whether a proposed affinity on + * job slot @js would cause a violation of affinity restrictions. + * + * @kbdev: Kbase device structure + * @js: The job slot to test + * @affinity: The affinity mask to test + * + * The following locks must be held by the caller + * - hwaccess_lock + * + * Return: true if the affinity would violate the restrictions + */ +bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, + u64 affinity); + +/** + * kbase_js_affinity_retain_slot_cores - Affinity tracking: retain cores used by + * a slot + * + * @kbdev: Kbase device structure + * @js: The job slot retaining the cores + * @affinity: The cores to retain + * + * The following locks must be held by the caller + * - hwaccess_lock + */ +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, + u64 affinity); + +/** + * kbase_js_affinity_release_slot_cores - Affinity tracking: release cores used + * by a slot + * + * @kbdev: Kbase device structure + * @js: Job slot + * @affinity: Bit mask of core to be released + * + * Cores must be released as soon as a job is dequeued from a slot's 'submit + * slots', and before another job is submitted to those slots. Otherwise, the + * refcount could exceed the maximum number submittable to a slot, + * %BASE_JM_SUBMIT_SLOTS. + * + * The following locks must be held by the caller + * - hwaccess_lock + */ +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, + u64 affinity); + +/** + * kbase_js_debug_log_current_affinities - log the current affinities + * + * @kbdev: Kbase device structure + * + * Output to the Trace log the current tracked affinities on all slots + */ +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev); +#else /* KBASE_TRACE_ENABLE */ +static inline void +kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ +} +#endif /* KBASE_TRACE_ENABLE */ + +#endif /* _KBASE_JS_AFFINITY_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c new file mode 100644 index 000000000000..a8c1af23a369 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c @@ -0,0 +1,356 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend specific job scheduler APIs + */ + +#include +#include +#include +#include + +/* + * Define for when dumping is enabled. + * This should not be based on the instrumentation level as whether dumping is + * enabled for a particular level is down to the integrator. However this is + * being used for now as otherwise the cinstr headers would be needed. + */ +#define CINSTR_DUMPING_ENABLED (2 == MALI_INSTRUMENTATION_LEVEL) + +/* + * Hold the runpool_mutex for this + */ +static inline bool timer_callback_should_run(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + s8 nr_running_ctxs; + + lockdep_assert_held(&kbdev->js_data.runpool_mutex); + + /* Timer must stop if we are suspending */ + if (backend->suspend_timer) + return false; + + /* nr_contexts_pullable is updated with the runpool_mutex. However, the + * locking in the caller gives us a barrier that ensures + * nr_contexts_pullable is up-to-date for reading */ + nr_running_ctxs = atomic_read(&kbdev->js_data.nr_contexts_runnable); + +#ifdef CONFIG_MALI_DEBUG + if (kbdev->js_data.softstop_always) { + /* Debug support for allowing soft-stop on a single context */ + return true; + } +#endif /* CONFIG_MALI_DEBUG */ + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9435)) { + /* Timeouts would have to be 4x longer (due to micro- + * architectural design) to support OpenCL conformance tests, so + * only run the timer when there's: + * - 2 or more CL contexts + * - 1 or more GLES contexts + * + * NOTE: We will treat a context that has both Compute and Non- + * Compute jobs will be treated as an OpenCL context (hence, we + * don't check KBASEP_JS_CTX_ATTR_NON_COMPUTE). + */ + { + s8 nr_compute_ctxs = + kbasep_js_ctx_attr_count_on_runpool(kbdev, + KBASEP_JS_CTX_ATTR_COMPUTE); + s8 nr_noncompute_ctxs = nr_running_ctxs - + nr_compute_ctxs; + + return (bool) (nr_compute_ctxs >= 2 || + nr_noncompute_ctxs > 0); + } + } else { + /* Run the timer callback whenever you have at least 1 context + */ + return (bool) (nr_running_ctxs > 0); + } +} + +static enum hrtimer_restart timer_callback(struct hrtimer *timer) +{ + unsigned long flags; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + struct kbase_backend_data *backend; + int s; + bool reset_needed = false; + + KBASE_DEBUG_ASSERT(timer != NULL); + + backend = container_of(timer, struct kbase_backend_data, + scheduling_timer); + kbdev = container_of(backend, struct kbase_device, hwaccess.backend); + js_devdata = &kbdev->js_data; + + /* Loop through the slots */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + for (s = 0; s < kbdev->gpu_props.num_job_slots; s++) { + struct kbase_jd_atom *atom = NULL; + + if (kbase_backend_nr_atoms_on_slot(kbdev, s) > 0) { + atom = kbase_gpu_inspect(kbdev, s, 0); + KBASE_DEBUG_ASSERT(atom != NULL); + } + + if (atom != NULL) { + /* The current version of the model doesn't support + * Soft-Stop */ + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) { + u32 ticks = atom->ticks++; + +#if !CINSTR_DUMPING_ENABLED + u32 soft_stop_ticks, hard_stop_ticks, + gpu_reset_ticks; + if (atom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { + soft_stop_ticks = + js_devdata->soft_stop_ticks_cl; + hard_stop_ticks = + js_devdata->hard_stop_ticks_cl; + gpu_reset_ticks = + js_devdata->gpu_reset_ticks_cl; + } else { + soft_stop_ticks = + js_devdata->soft_stop_ticks; + hard_stop_ticks = + js_devdata->hard_stop_ticks_ss; + gpu_reset_ticks = + js_devdata->gpu_reset_ticks_ss; + } + + /* If timeouts have been changed then ensure + * that atom tick count is not greater than the + * new soft_stop timeout. This ensures that + * atoms do not miss any of the timeouts due to + * races between this worker and the thread + * changing the timeouts. */ + if (backend->timeouts_updated && + ticks > soft_stop_ticks) + ticks = atom->ticks = soft_stop_ticks; + + /* Job is Soft-Stoppable */ + if (ticks == soft_stop_ticks) { + int disjoint_threshold = + KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD; + u32 softstop_flags = 0u; + /* Job has been scheduled for at least + * js_devdata->soft_stop_ticks ticks. + * Soft stop the slot so we can run + * other jobs. + */ + dev_dbg(kbdev->dev, "Soft-stop"); +#if !KBASE_DISABLE_SCHEDULING_SOFT_STOPS + /* nr_user_contexts_running is updated + * with the runpool_mutex, but we can't + * take that here. + * + * However, if it's about to be + * increased then the new context can't + * run any jobs until they take the + * hwaccess_lock, so it's OK to observe + * the older value. + * + * Similarly, if it's about to be + * decreased, the last job from another + * context has already finished, so it's + * not too bad that we observe the older + * value and register a disjoint event + * when we try soft-stopping */ + if (js_devdata->nr_user_contexts_running + >= disjoint_threshold) + softstop_flags |= + JS_COMMAND_SW_CAUSES_DISJOINT; + + kbase_job_slot_softstop_swflags(kbdev, + s, atom, softstop_flags); +#endif + } else if (ticks == hard_stop_ticks) { + /* Job has been scheduled for at least + * js_devdata->hard_stop_ticks_ss ticks. + * It should have been soft-stopped by + * now. Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + int ms = + js_devdata->scheduling_period_ns + / 1000000u; + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", + (unsigned long)ticks, + (unsigned long)ms); + kbase_job_slot_hardstop(atom->kctx, s, + atom); +#endif + } else if (ticks == gpu_reset_ticks) { + /* Job has been scheduled for at least + * js_devdata->gpu_reset_ticks_ss ticks. + * It should have left the GPU by now. + * Signal that the GPU needs to be + * reset. + */ + reset_needed = true; + } +#else /* !CINSTR_DUMPING_ENABLED */ + /* NOTE: During CINSTR_DUMPING_ENABLED, we use + * the alternate timeouts, which makes the hard- + * stop and GPU reset timeout much longer. We + * also ensure that we don't soft-stop at all. + */ + if (ticks == js_devdata->soft_stop_ticks) { + /* Job has been scheduled for at least + * js_devdata->soft_stop_ticks. We do + * not soft-stop during + * CINSTR_DUMPING_ENABLED, however. + */ + dev_dbg(kbdev->dev, "Soft-stop"); + } else if (ticks == + js_devdata->hard_stop_ticks_dumping) { + /* Job has been scheduled for at least + * js_devdata->hard_stop_ticks_dumping + * ticks. Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + int ms = + js_devdata->scheduling_period_ns + / 1000000u; + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", + (unsigned long)ticks, + (unsigned long)ms); + kbase_job_slot_hardstop(atom->kctx, s, + atom); +#endif + } else if (ticks == + js_devdata->gpu_reset_ticks_dumping) { + /* Job has been scheduled for at least + * js_devdata->gpu_reset_ticks_dumping + * ticks. It should have left the GPU by + * now. Signal that the GPU needs to be + * reset. + */ + reset_needed = true; + } +#endif /* !CINSTR_DUMPING_ENABLED */ + } + } + } +#if KBASE_GPU_RESET_EN + if (reset_needed) { + dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issueing GPU soft-reset to resolve."); + + if (kbase_prepare_to_reset_gpu_locked(kbdev)) + kbase_reset_gpu_locked(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* the timer is re-issued if there is contexts in the run-pool */ + + if (backend->timer_running) + hrtimer_start(&backend->scheduling_timer, + HR_TIMER_DELAY_NSEC(js_devdata->scheduling_period_ns), + HRTIMER_MODE_REL); + + backend->timeouts_updated = false; + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return HRTIMER_NORESTART; +} + +void kbase_backend_ctx_count_changed(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + unsigned long flags; + + lockdep_assert_held(&js_devdata->runpool_mutex); + + if (!timer_callback_should_run(kbdev)) { + /* Take spinlock to force synchronisation with timer */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + backend->timer_running = false; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + /* From now on, return value of timer_callback_should_run() will + * also cause the timer to not requeue itself. Its return value + * cannot change, because it depends on variables updated with + * the runpool_mutex held, which the caller of this must also + * hold */ + hrtimer_cancel(&backend->scheduling_timer); + } + + if (timer_callback_should_run(kbdev) && !backend->timer_running) { + /* Take spinlock to force synchronisation with timer */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + backend->timer_running = true; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + hrtimer_start(&backend->scheduling_timer, + HR_TIMER_DELAY_NSEC(js_devdata->scheduling_period_ns), + HRTIMER_MODE_REL); + + KBASE_TRACE_ADD(kbdev, JS_POLICY_TIMER_START, NULL, NULL, 0u, + 0u); + } +} + +int kbase_backend_timer_init(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + + hrtimer_init(&backend->scheduling_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + backend->scheduling_timer.function = timer_callback; + + backend->timer_running = false; + + return 0; +} + +void kbase_backend_timer_term(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + + hrtimer_cancel(&backend->scheduling_timer); +} + +void kbase_backend_timer_suspend(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + + backend->suspend_timer = true; + + kbase_backend_ctx_count_changed(kbdev); +} + +void kbase_backend_timer_resume(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + + backend->suspend_timer = false; + + kbase_backend_ctx_count_changed(kbdev); +} + +void kbase_backend_timeouts_changed(struct kbase_device *kbdev) +{ + struct kbase_backend_data *backend = &kbdev->hwaccess.backend; + + backend->timeouts_updated = true; +} + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_internal.h new file mode 100644 index 000000000000..3f53779c6747 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_internal.h @@ -0,0 +1,69 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Register-based HW access backend specific job scheduler APIs + */ + +#ifndef _KBASE_JS_BACKEND_H_ +#define _KBASE_JS_BACKEND_H_ + +/** + * kbase_backend_timer_init() - Initialise the JS scheduling timer + * @kbdev: Device pointer + * + * This function should be called at driver initialisation + * + * Return: 0 on success + */ +int kbase_backend_timer_init(struct kbase_device *kbdev); + +/** + * kbase_backend_timer_term() - Terminate the JS scheduling timer + * @kbdev: Device pointer + * + * This function should be called at driver termination + */ +void kbase_backend_timer_term(struct kbase_device *kbdev); + +/** + * kbase_backend_timer_suspend - Suspend is happening, stop the JS scheduling + * timer + * @kbdev: Device pointer + * + * This function should be called on suspend, after the active count has reached + * zero. This is required as the timer may have been started on job submission + * to the job scheduler, but before jobs are submitted to the GPU. + * + * Caller must hold runpool_mutex. + */ +void kbase_backend_timer_suspend(struct kbase_device *kbdev); + +/** + * kbase_backend_timer_resume - Resume is happening, re-evaluate the JS + * scheduling timer + * @kbdev: Device pointer + * + * This function should be called on resume. Note that is is not guaranteed to + * re-start the timer, only evalute whether it should be re-started. + * + * Caller must hold runpool_mutex. + */ +void kbase_backend_timer_resume(struct kbase_device *kbdev); + +#endif /* _KBASE_JS_BACKEND_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.c new file mode 100644 index 000000000000..aa1817c8bca9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.c @@ -0,0 +1,401 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include +#include +#include +#include +#include +#include + +static inline u64 lock_region(struct kbase_device *kbdev, u64 pfn, + u32 num_pages) +{ + u64 region; + + /* can't lock a zero sized range */ + KBASE_DEBUG_ASSERT(num_pages); + + region = pfn << PAGE_SHIFT; + /* + * fls returns (given the ASSERT above): + * 1 .. 32 + * + * 10 + fls(num_pages) + * results in the range (11 .. 42) + */ + + /* gracefully handle num_pages being zero */ + if (0 == num_pages) { + region |= 11; + } else { + u8 region_width; + + region_width = 10 + fls(num_pages); + if (num_pages != (1ul << (region_width - 11))) { + /* not pow2, so must go up to the next pow2 */ + region_width += 1; + } + KBASE_DEBUG_ASSERT(region_width <= KBASE_LOCK_REGION_MAX_SIZE); + KBASE_DEBUG_ASSERT(region_width >= KBASE_LOCK_REGION_MIN_SIZE); + region |= region_width; + } + + return region; +} + +static int wait_ready(struct kbase_device *kbdev, + unsigned int as_nr, struct kbase_context *kctx) +{ + unsigned int max_loops = KBASE_AS_INACTIVE_MAX_LOOPS; + u32 val = kbase_reg_read(kbdev, MMU_AS_REG(as_nr, AS_STATUS), kctx); + + /* Wait for the MMU status to indicate there is no active command, in + * case one is pending. Do not log remaining register accesses. */ + while (--max_loops && (val & AS_STATUS_AS_ACTIVE)) + val = kbase_reg_read(kbdev, MMU_AS_REG(as_nr, AS_STATUS), NULL); + + if (max_loops == 0) { + dev_err(kbdev->dev, "AS_ACTIVE bit stuck\n"); + return -1; + } + + /* If waiting in loop was performed, log last read value. */ + if (KBASE_AS_INACTIVE_MAX_LOOPS - 1 > max_loops) + kbase_reg_read(kbdev, MMU_AS_REG(as_nr, AS_STATUS), kctx); + + return 0; +} + +static int write_cmd(struct kbase_device *kbdev, int as_nr, u32 cmd, + struct kbase_context *kctx) +{ + int status; + + /* write AS_COMMAND when MMU is ready to accept another command */ + status = wait_ready(kbdev, as_nr, kctx); + if (status == 0) + kbase_reg_write(kbdev, MMU_AS_REG(as_nr, AS_COMMAND), cmd, + kctx); + + return status; +} + +static void validate_protected_page_fault(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + /* GPUs which support (native) protected mode shall not report page + * fault addresses unless it has protected debug mode and protected + * debug mode is turned on */ + u32 protected_debug_mode = 0; + + if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE)) + return; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) { + protected_debug_mode = kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_STATUS), + kctx) & GPU_DBGEN; + } + + if (!protected_debug_mode) { + /* fault_addr should never be reported in protected mode. + * However, we just continue by printing an error message */ + dev_err(kbdev->dev, "Fault address reported in protected mode\n"); + } +} + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat) +{ + const int num_as = 16; + const int busfault_shift = MMU_PAGE_FAULT_FLAGS; + const int pf_shift = 0; + const unsigned long as_bit_mask = (1UL << num_as) - 1; + unsigned long flags; + u32 new_mask; + u32 tmp; + + /* bus faults */ + u32 bf_bits = (irq_stat >> busfault_shift) & as_bit_mask; + /* page faults (note: Ignore ASes with both pf and bf) */ + u32 pf_bits = ((irq_stat >> pf_shift) & as_bit_mask) & ~bf_bits; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + + /* remember current mask */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + new_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + /* mask interrupts for now */ + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); + + while (bf_bits | pf_bits) { + struct kbase_as *as; + int as_no; + struct kbase_context *kctx; + + /* + * the while logic ensures we have a bit set, no need to check + * for not-found here + */ + as_no = ffs(bf_bits | pf_bits) - 1; + as = &kbdev->as[as_no]; + + /* + * Refcount the kctx ASAP - it shouldn't disappear anyway, since + * Bus/Page faults _should_ only occur whilst jobs are running, + * and a job causing the Bus/Page fault shouldn't complete until + * the MMU is updated + */ + kctx = kbasep_js_runpool_lookup_ctx(kbdev, as_no); + + + /* find faulting address */ + as->fault_addr = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, + AS_FAULTADDRESS_HI), + kctx); + as->fault_addr <<= 32; + as->fault_addr |= kbase_reg_read(kbdev, + MMU_AS_REG(as_no, + AS_FAULTADDRESS_LO), + kctx); + + /* Mark the fault protected or not */ + as->protected_mode = kbdev->protected_mode; + + if (kbdev->protected_mode && as->fault_addr) + { + /* check if address reporting is allowed */ + validate_protected_page_fault(kbdev, kctx); + } + + /* report the fault to debugfs */ + kbase_as_fault_debugfs_new(kbdev, as_no); + + /* record the fault status */ + as->fault_status = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, + AS_FAULTSTATUS), + kctx); + + /* find the fault type */ + as->fault_type = (bf_bits & (1 << as_no)) ? + KBASE_MMU_FAULT_TYPE_BUS : + KBASE_MMU_FAULT_TYPE_PAGE; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) { + as->fault_extra_addr = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTEXTRA_HI), + kctx); + as->fault_extra_addr <<= 32; + as->fault_extra_addr |= kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTEXTRA_LO), + kctx); + } + + if (kbase_as_has_bus_fault(as)) { + /* Mark bus fault as handled. + * Note that a bus fault is processed first in case + * where both a bus fault and page fault occur. + */ + bf_bits &= ~(1UL << as_no); + + /* remove the queued BF (and PF) from the mask */ + new_mask &= ~(MMU_BUS_ERROR(as_no) | + MMU_PAGE_FAULT(as_no)); + } else { + /* Mark page fault as handled */ + pf_bits &= ~(1UL << as_no); + + /* remove the queued PF from the mask */ + new_mask &= ~MMU_PAGE_FAULT(as_no); + } + + /* Process the interrupt for this address space */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_mmu_interrupt_process(kbdev, kctx, as); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } + + /* reenable interrupts */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + tmp = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + new_mask |= tmp; + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), new_mask, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} + +void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx) +{ + struct kbase_mmu_setup *current_setup = &as->current_setup; + u32 transcfg = 0; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) { + transcfg = current_setup->transcfg & 0xFFFFFFFFUL; + + /* Set flag AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK */ + /* Clear PTW_MEMATTR bits */ + transcfg &= ~AS_TRANSCFG_PTW_MEMATTR_MASK; + /* Enable correct PTW_MEMATTR bits */ + transcfg |= AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK; + + if (kbdev->system_coherency == COHERENCY_ACE) { + /* Set flag AS_TRANSCFG_PTW_SH_OS (outer shareable) */ + /* Clear PTW_SH bits */ + transcfg = (transcfg & ~AS_TRANSCFG_PTW_SH_MASK); + /* Enable correct PTW_SH bits */ + transcfg = (transcfg | AS_TRANSCFG_PTW_SH_OS); + } + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_LO), + transcfg, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_HI), + (current_setup->transcfg >> 32) & 0xFFFFFFFFUL, + kctx); + } else { + if (kbdev->system_coherency == COHERENCY_ACE) + current_setup->transtab |= AS_TRANSTAB_LPAE_SHARE_OUTER; + } + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_LO), + current_setup->transtab & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_HI), + (current_setup->transtab >> 32) & 0xFFFFFFFFUL, kctx); + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_LO), + current_setup->memattr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_HI), + (current_setup->memattr >> 32) & 0xFFFFFFFFUL, kctx); + + KBASE_TLSTREAM_TL_ATTRIB_AS_CONFIG(as, + current_setup->transtab, + current_setup->memattr, + transcfg); + + write_cmd(kbdev, as->number, AS_COMMAND_UPDATE, kctx); +} + +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 op, + unsigned int handling_irq) +{ + int ret; + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + + if (op == AS_COMMAND_UNLOCK) { + /* Unlock doesn't require a lock first */ + ret = write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } else { + u64 lock_addr = lock_region(kbdev, vpfn, nr); + + /* Lock the region that needs to be updated */ + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_LO), + lock_addr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_HI), + (lock_addr >> 32) & 0xFFFFFFFFUL, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_LOCK, kctx); + + /* Run the MMU operation */ + write_cmd(kbdev, as->number, op, kctx); + + /* Wait for the flush to complete */ + ret = wait_ready(kbdev, as->number, kctx); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9630)) { + /* Issue an UNLOCK command to ensure that valid page + tables are re-read by the GPU after an update. + Note that, the FLUSH command should perform all the + actions necessary, however the bus logs show that if + multiple page faults occur within an 8 page region + the MMU does not always re-read the updated page + table entries for later faults or is only partially + read, it subsequently raises the page fault IRQ for + the same addresses, the unlock ensures that the MMU + cache is flushed, so updates can be re-read. As the + region is now unlocked we need to issue 2 UNLOCK + commands in order to flush the MMU/uTLB, + see PRLAM-8812. + */ + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } + } + + return ret; +} + +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + unsigned long flags; + u32 pf_bf_mask; + + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + + /* + * A reset is in-flight and we're flushing the IRQ + bottom half + * so don't update anything as it could race with the reset code. + */ + if (kbdev->irq_reset_flush) + goto unlock; + + /* Clear the page (and bus fault IRQ as well in case one occurred) */ + pf_bf_mask = MMU_PAGE_FAULT(as->number); + if (type == KBASE_MMU_FAULT_TYPE_BUS || + type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED) + pf_bf_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), pf_bf_mask, kctx); + +unlock: + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} + +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + unsigned long flags; + u32 irq_mask; + + /* Enable the page fault IRQ (and bus fault IRQ as well in case one + * occurred) */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + + /* + * A reset is in-flight and we're flushing the IRQ + bottom half + * so don't update anything as it could race with the reset code. + */ + if (kbdev->irq_reset_flush) + goto unlock; + + irq_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), kctx) | + MMU_PAGE_FAULT(as->number); + + if (type == KBASE_MMU_FAULT_TYPE_BUS || + type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED) + irq_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), irq_mask, kctx); + +unlock: + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.h new file mode 100644 index 000000000000..c02253c6acc3 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_mmu_hw_direct.h @@ -0,0 +1,42 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Interface file for the direct implementation for MMU hardware access + * + * Direct MMU hardware interface + * + * This module provides the interface(s) that are required by the direct + * register access implementation of the MMU hardware interface + */ + +#ifndef _MALI_KBASE_MMU_HW_DIRECT_H_ +#define _MALI_KBASE_MMU_HW_DIRECT_H_ + +#include + +/** + * kbase_mmu_interrupt - Process an MMU interrupt. + * + * Process the MMU interrupt that was reported by the &kbase_device. + * + * @kbdev: kbase context to clear the fault from. + * @irq_stat: Value of the MMU_IRQ_STATUS register + */ +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +#endif /* _MALI_KBASE_MMU_HW_DIRECT_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.c new file mode 100644 index 000000000000..0614348e935a --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.c @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT 2010-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * "Always on" power management policy + */ + +#include +#include + +static u64 always_on_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->gpu_props.props.raw_props.shader_present; +} + +static bool always_on_get_core_active(struct kbase_device *kbdev) +{ + return true; +} + +static void always_on_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void always_on_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/* + * The struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback + * and name. + */ +const struct kbase_pm_policy kbase_pm_always_on_policy_ops = { + "always_on", /* name */ + always_on_init, /* init */ + always_on_term, /* term */ + always_on_get_core_mask, /* get_core_mask */ + always_on_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_ALWAYS_ON, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_always_on_policy_ops); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.h new file mode 100644 index 000000000000..f9d244b01bc2 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_always_on.h @@ -0,0 +1,77 @@ + +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * "Always on" power management policy + */ + +#ifndef MALI_KBASE_PM_ALWAYS_ON_H +#define MALI_KBASE_PM_ALWAYS_ON_H + +/** + * DOC: + * The "Always on" power management policy has the following + * characteristics: + * + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * + * - When KBase indicates that the GPU need not be powered: + * The Shader Cores are kept powered, regardless of whether or not they will + * be needed. The GPU itself is also kept powered, even though it is not + * needed. + * + * This policy is automatically overridden during system suspend: the desired + * core state is ignored, and the cores are forced off regardless of what the + * policy requests. After resuming from suspend, new changes to the desired + * core state made by the policy are honored. + * + * Note: + * + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * struct kbasep_pm_policy_always_on - Private struct for policy instance data + * @dummy: unused dummy variable + * + * This contains data that is private to the particular power policy that is + * active. + */ +struct kbasep_pm_policy_always_on { + int dummy; +}; + +extern const struct kbase_pm_policy kbase_pm_always_on_policy_ops; + +#endif /* MALI_KBASE_PM_ALWAYS_ON_H */ + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c new file mode 100644 index 000000000000..c88b80a325dd --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c @@ -0,0 +1,478 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * GPU backend implementation of base kernel power management APIs + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data); + +void kbase_pm_register_access_enable(struct kbase_device *kbdev) +{ + struct kbase_pm_callback_conf *callbacks; + + callbacks = (struct kbase_pm_callback_conf *)POWER_MANAGEMENT_CALLBACKS; + + if (callbacks) + callbacks->power_on_callback(kbdev); + + kbdev->pm.backend.gpu_powered = true; +} + +void kbase_pm_register_access_disable(struct kbase_device *kbdev) +{ + struct kbase_pm_callback_conf *callbacks; + + callbacks = (struct kbase_pm_callback_conf *)POWER_MANAGEMENT_CALLBACKS; + + if (callbacks) + callbacks->power_off_callback(kbdev); + + kbdev->pm.backend.gpu_powered = false; +} + +int kbase_hwaccess_pm_init(struct kbase_device *kbdev) +{ + int ret = 0; + struct kbase_pm_callback_conf *callbacks; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_init(&kbdev->pm.lock); + + kbdev->pm.backend.gpu_poweroff_wait_wq = alloc_workqueue("kbase_pm_poweroff_wait", + WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!kbdev->pm.backend.gpu_poweroff_wait_wq) + return -ENOMEM; + + INIT_WORK(&kbdev->pm.backend.gpu_poweroff_wait_work, + kbase_pm_gpu_poweroff_wait_wq); + + kbdev->pm.backend.gpu_powered = false; + kbdev->pm.suspending = false; +#ifdef CONFIG_MALI_DEBUG + kbdev->pm.backend.driver_ready_for_irqs = false; +#endif /* CONFIG_MALI_DEBUG */ + kbdev->pm.backend.gpu_in_desired_state = true; + init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait); + + callbacks = (struct kbase_pm_callback_conf *)POWER_MANAGEMENT_CALLBACKS; + if (callbacks) { + kbdev->pm.backend.callback_power_on = + callbacks->power_on_callback; + kbdev->pm.backend.callback_power_off = + callbacks->power_off_callback; + kbdev->pm.backend.callback_power_suspend = + callbacks->power_suspend_callback; + kbdev->pm.backend.callback_power_resume = + callbacks->power_resume_callback; + kbdev->pm.callback_power_runtime_init = + callbacks->power_runtime_init_callback; + kbdev->pm.callback_power_runtime_term = + callbacks->power_runtime_term_callback; + kbdev->pm.backend.callback_power_runtime_on = + callbacks->power_runtime_on_callback; + kbdev->pm.backend.callback_power_runtime_off = + callbacks->power_runtime_off_callback; + kbdev->pm.backend.callback_power_runtime_idle = + callbacks->power_runtime_idle_callback; + } else { + kbdev->pm.backend.callback_power_on = NULL; + kbdev->pm.backend.callback_power_off = NULL; + kbdev->pm.backend.callback_power_suspend = NULL; + kbdev->pm.backend.callback_power_resume = NULL; + kbdev->pm.callback_power_runtime_init = NULL; + kbdev->pm.callback_power_runtime_term = NULL; + kbdev->pm.backend.callback_power_runtime_on = NULL; + kbdev->pm.backend.callback_power_runtime_off = NULL; + kbdev->pm.backend.callback_power_runtime_idle = NULL; + } + + /* Initialise the metrics subsystem */ + ret = kbasep_pm_metrics_init(kbdev); + if (ret) + return ret; + + init_waitqueue_head(&kbdev->pm.backend.l2_powered_wait); + kbdev->pm.backend.l2_powered = 0; + + init_waitqueue_head(&kbdev->pm.backend.reset_done_wait); + kbdev->pm.backend.reset_done = false; + + init_waitqueue_head(&kbdev->pm.zero_active_count_wait); + kbdev->pm.active_count = 0; + + spin_lock_init(&kbdev->pm.backend.gpu_cycle_counter_requests_lock); + spin_lock_init(&kbdev->pm.backend.gpu_powered_lock); + + init_waitqueue_head(&kbdev->pm.backend.poweroff_wait); + + if (kbase_pm_ca_init(kbdev) != 0) + goto workq_fail; + + if (kbase_pm_policy_init(kbdev) != 0) + goto pm_policy_fail; + + return 0; + +pm_policy_fail: + kbase_pm_ca_term(kbdev); +workq_fail: + kbasep_pm_metrics_term(kbdev); + return -EINVAL; +} + +void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume) +{ + lockdep_assert_held(&kbdev->pm.lock); + + /* Turn clocks and interrupts on - no-op if we haven't done a previous + * kbase_pm_clock_off() */ + kbase_pm_clock_on(kbdev, is_resume); + + /* Update core status as required by the policy */ + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START); + kbase_pm_update_cores_state(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END); + + /* NOTE: We don't wait to reach the desired state, since running atoms + * will wait for that state to be reached anyway */ +} + +static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data) +{ + struct kbase_device *kbdev = container_of(data, struct kbase_device, + pm.backend.gpu_poweroff_wait_work); + struct kbase_pm_device_data *pm = &kbdev->pm; + struct kbase_pm_backend_data *backend = &pm->backend; + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long flags; + +#if !PLATFORM_POWER_DOWN_ONLY + /* Wait for power transitions to complete. We do this with no locks held + * so that we don't deadlock with any pending workqueues */ + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START); + kbase_pm_check_transitions_sync(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END); +#endif /* !PLATFORM_POWER_DOWN_ONLY */ + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + +#if PLATFORM_POWER_DOWN_ONLY + if (kbdev->pm.backend.gpu_powered) { + if (kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2)) { + /* If L2 cache is powered then we must flush it before + * we power off the GPU. Normally this would have been + * handled when the L2 was powered off. */ + kbase_gpu_cacheclean(kbdev); + } + } +#endif /* PLATFORM_POWER_DOWN_ONLY */ + + if (!backend->poweron_required) { +#if !PLATFORM_POWER_DOWN_ONLY + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + WARN_ON(kbdev->l2_available_bitmap || + kbdev->shader_available_bitmap || + kbdev->tiler_available_bitmap); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +#endif /* !PLATFORM_POWER_DOWN_ONLY */ + + /* Consume any change-state events */ + kbase_timeline_pm_check_handle_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + + /* Disable interrupts and turn the clock off */ + if (!kbase_pm_clock_off(kbdev, backend->poweroff_is_suspend)) { + /* + * Page/bus faults are pending, must drop locks to + * process. Interrupts are disabled so no more faults + * should be generated at this point. + */ + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + kbase_flush_mmu_wqs(kbdev); + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + /* Turn off clock now that fault have been handled. We + * dropped locks so poweron_required may have changed - + * power back on if this is the case.*/ + if (backend->poweron_required) + kbase_pm_clock_on(kbdev, false); + else + WARN_ON(!kbase_pm_clock_off(kbdev, + backend->poweroff_is_suspend)); + } + } + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + backend->poweroff_wait_in_progress = false; + if (backend->poweron_required) { + backend->poweron_required = false; + kbase_pm_update_cores_state_nolock(kbdev); + kbase_backend_slot_update(kbdev); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + + wake_up(&kbdev->pm.backend.poweroff_wait); +} + +void kbase_pm_do_poweroff(struct kbase_device *kbdev, bool is_suspend) +{ + unsigned long flags; + + lockdep_assert_held(&kbdev->pm.lock); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (!kbdev->pm.backend.poweroff_wait_in_progress) { + /* Force all cores off */ + kbdev->pm.backend.desired_shader_state = 0; + kbdev->pm.backend.desired_tiler_state = 0; + + /* Force all cores to be unavailable, in the situation where + * transitions are in progress for some cores but not others, + * and kbase_pm_check_transitions_nolock can not immediately + * power off the cores */ + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_available_bitmap = 0; + + kbdev->pm.backend.poweroff_wait_in_progress = true; + kbdev->pm.backend.poweroff_is_suspend = is_suspend; + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + /*Kick off wq here. Callers will have to wait*/ + queue_work(kbdev->pm.backend.gpu_poweroff_wait_wq, + &kbdev->pm.backend.gpu_poweroff_wait_work); + } else { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } +} + +static bool is_poweroff_in_progress(struct kbase_device *kbdev) +{ + bool ret; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + ret = (kbdev->pm.backend.poweroff_wait_in_progress == false); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return ret; +} + +void kbase_pm_wait_for_poweroff_complete(struct kbase_device *kbdev) +{ + wait_event_killable(kbdev->pm.backend.poweroff_wait, + is_poweroff_in_progress(kbdev)); +} + +int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, + unsigned int flags) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long irq_flags; + int ret; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + /* A suspend won't happen during startup/insmod */ + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + /* Power up the GPU, don't enable IRQs as we are not ready to receive + * them. */ + ret = kbase_pm_init_hw(kbdev, flags); + if (ret) { + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + return ret; + } + + kbasep_pm_init_core_use_bitmaps(kbdev); + + kbdev->pm.debug_core_mask_all = kbdev->pm.debug_core_mask[0] = + kbdev->pm.debug_core_mask[1] = + kbdev->pm.debug_core_mask[2] = + kbdev->gpu_props.props.raw_props.shader_present; + + /* Pretend the GPU is active to prevent a power policy turning the GPU + * cores off */ + kbdev->pm.active_count = 1; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock, + irq_flags); + /* Ensure cycle counter is off */ + kbdev->pm.backend.gpu_cycle_counter_requests = 0; + spin_unlock_irqrestore( + &kbdev->pm.backend.gpu_cycle_counter_requests_lock, + irq_flags); + + /* We are ready to receive IRQ's now as power policy is set up, so + * enable them now. */ +#ifdef CONFIG_MALI_DEBUG + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, irq_flags); + kbdev->pm.backend.driver_ready_for_irqs = true; + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, irq_flags); +#endif + kbase_pm_enable_interrupts(kbdev); + + /* Turn on the GPU and any cores needed by the policy */ + kbase_pm_do_poweron(kbdev, false); + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + + /* Idle the GPU and/or cores, if the policy wants it to */ + kbase_pm_context_idle(kbdev); + + return 0; +} + +void kbase_hwaccess_pm_halt(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&kbdev->pm.lock); + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, false); + mutex_unlock(&kbdev->pm.lock); +} + +KBASE_EXPORT_TEST_API(kbase_hwaccess_pm_halt); + +void kbase_hwaccess_pm_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kbdev->pm.active_count == 0); + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_cycle_counter_requests == 0); + + /* Free any resources the policy allocated */ + kbase_pm_policy_term(kbdev); + kbase_pm_ca_term(kbdev); + + /* Shut down the metrics subsystem */ + kbasep_pm_metrics_term(kbdev); + + destroy_workqueue(kbdev->pm.backend.gpu_poweroff_wait_wq); +} + +void kbase_pm_power_changed(struct kbase_device *kbdev) +{ + bool cores_are_available; + unsigned long flags; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END); + + if (cores_are_available) { + /* Log timelining information that a change in state has + * completed */ + kbase_timeline_pm_handle_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + + kbase_backend_slot_update(kbdev); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, + u64 new_core_mask_js0, u64 new_core_mask_js1, + u64 new_core_mask_js2) +{ + kbdev->pm.debug_core_mask[0] = new_core_mask_js0; + kbdev->pm.debug_core_mask[1] = new_core_mask_js1; + kbdev->pm.debug_core_mask[2] = new_core_mask_js2; + kbdev->pm.debug_core_mask_all = new_core_mask_js0 | new_core_mask_js1 | + new_core_mask_js2; + + kbase_pm_update_cores_state_nolock(kbdev); +} + +void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev) +{ + kbase_pm_update_active(kbdev); +} + +void kbase_hwaccess_pm_gpu_idle(struct kbase_device *kbdev) +{ + kbase_pm_update_active(kbdev); +} + +void kbase_hwaccess_pm_suspend(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + /* Force power off the GPU and all cores (regardless of policy), only + * after the PM active count reaches zero (otherwise, we risk turning it + * off prematurely) */ + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, true); + + kbase_backend_timer_suspend(kbdev); + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + + kbase_pm_wait_for_poweroff_complete(kbdev); +} + +void kbase_hwaccess_pm_resume(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + kbdev->pm.suspending = false; + kbase_pm_do_poweron(kbdev, true); + + kbase_backend_timer_resume(kbdev); + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c new file mode 100644 index 000000000000..85890f1e85f5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c @@ -0,0 +1,182 @@ +/* + * + * (C) COPYRIGHT 2013-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Base kernel core availability APIs + */ + +#include +#include +#include + +static const struct kbase_pm_ca_policy *const policy_list[] = { + &kbase_pm_ca_fixed_policy_ops, +#ifdef CONFIG_MALI_DEVFREQ + &kbase_pm_ca_devfreq_policy_ops, +#endif +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_ca_random_policy_ops +#endif +}; + +/** + * POLICY_COUNT - The number of policies available in the system. + * + * This is derived from the number of functions listed in policy_list. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + +int kbase_pm_ca_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.backend.ca_current_policy = policy_list[0]; + + kbdev->pm.backend.ca_current_policy->init(kbdev); + + return 0; +} + +void kbase_pm_ca_term(struct kbase_device *kbdev) +{ + kbdev->pm.backend.ca_current_policy->term(kbdev); +} + +int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_list_policies); + +const struct kbase_pm_ca_policy +*kbase_pm_ca_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.backend.ca_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_policy); + +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, + const struct kbase_pm_ca_policy *new_policy) +{ + const struct kbase_pm_ca_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_CA_SET_POLICY, NULL, NULL, 0u, + new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a + * userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + old_policy = kbdev->pm.backend.ca_current_policy; + kbdev->pm.backend.ca_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + if (old_policy->term) + old_policy->term(kbdev); + + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->pm.backend.ca_current_policy = new_policy; + + /* If any core power state changes were previously attempted, but + * couldn't be made because the policy was changing (current_policy was + * NULL), then re-try them here. */ + kbase_pm_update_cores_state_nolock(kbdev); + + kbdev->pm.backend.ca_current_policy->update_core_status(kbdev, + kbdev->shader_ready_bitmap, + kbdev->shader_transitioning_bitmap); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + mutex_unlock(&kbdev->pm.lock); + + /* Now the policy change is finished, we release our fake context active + * reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_set_policy); + +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* All cores must be enabled when instrumentation is in use */ + if (kbdev->pm.backend.instr_enabled) + return kbdev->gpu_props.props.raw_props.shader_present & + kbdev->pm.debug_core_mask_all; + + if (kbdev->pm.backend.ca_current_policy == NULL) + return kbdev->gpu_props.props.raw_props.shader_present & + kbdev->pm.debug_core_mask_all; + + return kbdev->pm.backend.ca_current_policy->get_core_mask(kbdev) & + kbdev->pm.debug_core_mask_all; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_core_mask); + +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, + u64 cores_transitioning) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->pm.backend.ca_current_policy != NULL) + kbdev->pm.backend.ca_current_policy->update_core_status(kbdev, + cores_ready, + cores_transitioning); +} + +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->pm.backend.instr_enabled = true; + + kbase_pm_update_cores_state_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + kbdev->pm.backend.instr_enabled = false; + + kbase_pm_update_cores_state_nolock(kbdev); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.h new file mode 100644 index 000000000000..ee9e751f2d79 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.h @@ -0,0 +1,92 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Base kernel core availability APIs + */ + +#ifndef _KBASE_PM_CA_H_ +#define _KBASE_PM_CA_H_ + +/** + * kbase_pm_ca_init - Initialize core availability framework + * + * Must be called before calling any other core availability function + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Return: 0 if the core availability framework was successfully initialized, + * -errno otherwise + */ +int kbase_pm_ca_init(struct kbase_device *kbdev); + +/** + * kbase_pm_ca_term - Terminate core availability framework + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_term(struct kbase_device *kbdev); + +/** + * kbase_pm_ca_get_core_mask - Get currently available shaders core mask + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Returns a mask of the currently available shader cores. + * Calls into the core availability policy + * + * Return: The bit mask of available cores + */ +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev); + +/** + * kbase_pm_ca_update_core_status - Update core status + * + * @kbdev: The kbase device structure for the device (must be + * a valid pointer) + * @cores_ready: The bit mask of cores ready for job submission + * @cores_transitioning: The bit mask of cores that are transitioning power + * state + * + * Update core availability policy with current core power status + * + * Calls into the core availability policy + */ +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, + u64 cores_transitioning); + +/** + * kbase_pm_ca_instr_enable - Enable override for instrumentation + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This overrides the output of the core availability policy, ensuring that all + * cores are available + */ +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev); + +/** + * kbase_pm_ca_instr_disable - Disable override for instrumentation + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This disables any previously enabled override, and resumes normal policy + * functionality + */ +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev); + +#endif /* _KBASE_PM_CA_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.c new file mode 100644 index 000000000000..66bf660cffb6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.c @@ -0,0 +1,129 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * A core availability policy implementing core mask selection from devfreq OPPs + * + */ + +#include +#include +#include +#include + +void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask) +{ + struct kbasep_pm_ca_policy_devfreq *data = + &kbdev->pm.backend.ca_policy_data.devfreq; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + data->cores_desired = core_mask; + + /* Disable any cores that are now unwanted */ + data->cores_enabled &= data->cores_desired; + + kbdev->pm.backend.ca_in_transition = true; + + /* If there are no cores to be powered off then power on desired cores + */ + if (!(data->cores_used & ~data->cores_desired)) { + data->cores_enabled = data->cores_desired; + kbdev->pm.backend.ca_in_transition = false; + } + + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX %llX\n", + data->cores_desired, data->cores_enabled); +} + +static void devfreq_init(struct kbase_device *kbdev) +{ + struct kbasep_pm_ca_policy_devfreq *data = + &kbdev->pm.backend.ca_policy_data.devfreq; + + if (kbdev->current_core_mask) { + data->cores_enabled = kbdev->current_core_mask; + data->cores_desired = kbdev->current_core_mask; + } else { + data->cores_enabled = + kbdev->gpu_props.props.raw_props.shader_present; + data->cores_desired = + kbdev->gpu_props.props.raw_props.shader_present; + } + data->cores_used = 0; + kbdev->pm.backend.ca_in_transition = false; +} + +static void devfreq_term(struct kbase_device *kbdev) +{ +} + +static u64 devfreq_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->pm.backend.ca_policy_data.devfreq.cores_enabled; +} + +static void devfreq_update_core_status(struct kbase_device *kbdev, + u64 cores_ready, + u64 cores_transitioning) +{ + struct kbasep_pm_ca_policy_devfreq *data = + &kbdev->pm.backend.ca_policy_data.devfreq; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + data->cores_used = cores_ready | cores_transitioning; + + /* If in desired state then clear transition flag */ + if (data->cores_enabled == data->cores_desired) + kbdev->pm.backend.ca_in_transition = false; + + /* If all undesired cores are now off then power on desired cores. + * The direct comparison against cores_enabled limits potential + * recursion to one level */ + if (!(data->cores_used & ~data->cores_desired) && + data->cores_enabled != data->cores_desired) { + data->cores_enabled = data->cores_desired; + + kbase_pm_update_cores_state_nolock(kbdev); + + kbdev->pm.backend.ca_in_transition = false; + } +} + +/* + * The struct kbase_pm_ca_policy structure for the devfreq core availability + * policy. + * + * This is the static structure that defines the devfreq core availability power + * policy's callback and name. + */ +const struct kbase_pm_ca_policy kbase_pm_ca_devfreq_policy_ops = { + "devfreq", /* name */ + devfreq_init, /* init */ + devfreq_term, /* term */ + devfreq_get_core_mask, /* get_core_mask */ + devfreq_update_core_status, /* update_core_status */ + 0u, /* flags */ + KBASE_PM_CA_POLICY_ID_DEVFREQ, /* id */ +}; + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.h new file mode 100644 index 000000000000..7ab3cd4d8460 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_devfreq.h @@ -0,0 +1,55 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * A core availability policy for use with devfreq, where core masks are + * associated with OPPs. + */ + +#ifndef MALI_KBASE_PM_CA_DEVFREQ_H +#define MALI_KBASE_PM_CA_DEVFREQ_H + +/** + * struct kbasep_pm_ca_policy_devfreq - Private structure for devfreq ca policy + * + * This contains data that is private to the devfreq core availability + * policy. + * + * @cores_desired: Cores that the policy wants to be available + * @cores_enabled: Cores that the policy is currently returning as available + * @cores_used: Cores currently powered or transitioning + */ +struct kbasep_pm_ca_policy_devfreq { + u64 cores_desired; + u64 cores_enabled; + u64 cores_used; +}; + +extern const struct kbase_pm_ca_policy kbase_pm_ca_devfreq_policy_ops; + +/** + * kbase_devfreq_set_core_mask - Set core mask for policy to use + * @kbdev: Device pointer + * @core_mask: New core mask + * + * The new core mask will have immediate effect if the GPU is powered, or will + * take effect when it is next powered on. + */ +void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask); + +#endif /* MALI_KBASE_PM_CA_DEVFREQ_H */ + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.c new file mode 100644 index 000000000000..864612d31f9b --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.c @@ -0,0 +1,65 @@ +/* + * + * (C) COPYRIGHT 2013-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * A power policy implementing fixed core availability + */ + +#include +#include + +static void fixed_init(struct kbase_device *kbdev) +{ + kbdev->pm.backend.ca_in_transition = false; +} + +static void fixed_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static u64 fixed_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->gpu_props.props.raw_props.shader_present; +} + +static void fixed_update_core_status(struct kbase_device *kbdev, + u64 cores_ready, + u64 cores_transitioning) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(cores_ready); + CSTD_UNUSED(cores_transitioning); +} + +/* + * The struct kbase_pm_policy structure for the fixed power policy. + * + * This is the static structure that defines the fixed power policy's callback + * and name. + */ +const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops = { + "fixed", /* name */ + fixed_init, /* init */ + fixed_term, /* term */ + fixed_get_core_mask, /* get_core_mask */ + fixed_update_core_status, /* update_core_status */ + 0u, /* flags */ + KBASE_PM_CA_POLICY_ID_FIXED, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_ca_fixed_policy_ops); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.h new file mode 100644 index 000000000000..a763155cb703 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca_fixed.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2013-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * A power policy implementing fixed core availability + */ + +#ifndef MALI_KBASE_PM_CA_FIXED_H +#define MALI_KBASE_PM_CA_FIXED_H + +/** + * struct kbasep_pm_ca_policy_fixed - Private structure for policy instance data + * + * @dummy: Dummy member - no state is needed + * + * This contains data that is private to the particular power policy that is + * active. + */ +struct kbasep_pm_ca_policy_fixed { + int dummy; +}; + +extern const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops; + +#endif /* MALI_KBASE_PM_CA_FIXED_H */ + diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.c new file mode 100644 index 000000000000..f891fa225a89 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.c @@ -0,0 +1,70 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * "Coarse Demand" power management policy + */ + +#include +#include + +static u64 coarse_demand_get_core_mask(struct kbase_device *kbdev) +{ + if (kbdev->pm.active_count == 0) + return 0; + + return kbdev->gpu_props.props.raw_props.shader_present; +} + +static bool coarse_demand_get_core_active(struct kbase_device *kbdev) +{ + if (0 == kbdev->pm.active_count && !(kbdev->shader_needed_bitmap | + kbdev->shader_inuse_bitmap) && !kbdev->tiler_needed_cnt + && !kbdev->tiler_inuse_cnt) + return false; + + return true; +} + +static void coarse_demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void coarse_demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/* The struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback + * and name. + */ +const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = { + "coarse_demand", /* name */ + coarse_demand_init, /* init */ + coarse_demand_term, /* term */ + coarse_demand_get_core_mask, /* get_core_mask */ + coarse_demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_COARSE_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_coarse_demand_policy_ops); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.h new file mode 100644 index 000000000000..749d305eee9a --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_coarse_demand.h @@ -0,0 +1,64 @@ +/* + * + * (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * "Coarse Demand" power management policy + */ + +#ifndef MALI_KBASE_PM_COARSE_DEMAND_H +#define MALI_KBASE_PM_COARSE_DEMAND_H + +/** + * DOC: + * The "Coarse" demand power management policy has the following + * characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * struct kbasep_pm_policy_coarse_demand - Private structure for coarse demand + * policy + * + * This contains data that is private to the coarse demand power policy. + * + * @dummy: Dummy member - no state needed + */ +struct kbasep_pm_policy_coarse_demand { + int dummy; +}; + +extern const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops; + +#endif /* MALI_KBASE_PM_COARSE_DEMAND_H */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h new file mode 100644 index 000000000000..352744ee6d73 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h @@ -0,0 +1,519 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Backend-specific Power Manager definitions + */ + +#ifndef _KBASE_PM_HWACCESS_DEFS_H_ +#define _KBASE_PM_HWACCESS_DEFS_H_ + +#include "mali_kbase_pm_ca_fixed.h" +#include "mali_kbase_pm_ca_devfreq.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_ca_random.h" +#endif + +#include "mali_kbase_pm_always_on.h" +#include "mali_kbase_pm_coarse_demand.h" +#include "mali_kbase_pm_demand.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_demand_always_powered.h" +#include "mali_kbase_pm_fast_start.h" +#endif + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; +struct kbase_jd_atom; + +/** + * enum kbase_pm_core_type - The types of core in a GPU. + * + * These enumerated values are used in calls to + * - kbase_pm_get_present_cores() + * - kbase_pm_get_active_cores() + * - kbase_pm_get_trans_cores() + * - kbase_pm_get_ready_cores(). + * + * They specify which type of core should be acted on. These values are set in + * a manner that allows core_type_to_reg() function to be simpler and more + * efficient. + * + * @KBASE_PM_CORE_L2: The L2 cache + * @KBASE_PM_CORE_SHADER: Shader cores + * @KBASE_PM_CORE_TILER: Tiler cores + * @KBASE_PM_CORE_STACK: Core stacks + */ +enum kbase_pm_core_type { + KBASE_PM_CORE_L2 = L2_PRESENT_LO, + KBASE_PM_CORE_SHADER = SHADER_PRESENT_LO, + KBASE_PM_CORE_TILER = TILER_PRESENT_LO, + KBASE_PM_CORE_STACK = STACK_PRESENT_LO +}; + +/** + * struct kbasep_pm_metrics_data - Metrics data collected for use by the power + * management framework. + * + * @time_period_start: time at which busy/idle measurements started + * @time_busy: number of ns the GPU was busy executing jobs since the + * @time_period_start timestamp. + * @time_idle: number of ns since time_period_start the GPU was not executing + * jobs since the @time_period_start timestamp. + * @prev_busy: busy time in ns of previous time period. + * Updated when metrics are reset. + * @prev_idle: idle time in ns of previous time period + * Updated when metrics are reset. + * @gpu_active: true when the GPU is executing jobs. false when + * not. Updated when the job scheduler informs us a job in submitted + * or removed from a GPU slot. + * @busy_cl: number of ns the GPU was busy executing CL jobs. Note that + * if two CL jobs were active for 400ns, this value would be updated + * with 800. + * @busy_gl: number of ns the GPU was busy executing GL jobs. Note that + * if two GL jobs were active for 400ns, this value would be updated + * with 800. + * @active_cl_ctx: number of CL jobs active on the GPU. Array is per-device. + * @active_gl_ctx: number of GL jobs active on the GPU. Array is per-slot. As + * GL jobs never run on slot 2 this slot is not recorded. + * @lock: spinlock protecting the kbasep_pm_metrics_data structure + * @timer: timer to regularly make DVFS decisions based on the power + * management metrics. + * @timer_active: boolean indicating @timer is running + * @platform_data: pointer to data controlled by platform specific code + * @kbdev: pointer to kbase device for which metrics are collected + * + */ +struct kbasep_pm_metrics_data { + ktime_t time_period_start; + u32 time_busy; + u32 time_idle; + u32 prev_busy; + u32 prev_idle; + bool gpu_active; + u32 busy_cl[2]; + u32 busy_gl; + u32 active_cl_ctx[2]; + u32 active_gl_ctx[2]; /* GL jobs can only run on 2 of the 3 job slots */ + spinlock_t lock; + +#ifdef CONFIG_MALI_MIDGARD_DVFS + struct hrtimer timer; + bool timer_active; +#endif + + void *platform_data; + struct kbase_device *kbdev; +}; + +union kbase_pm_policy_data { + struct kbasep_pm_policy_always_on always_on; + struct kbasep_pm_policy_coarse_demand coarse_demand; + struct kbasep_pm_policy_demand demand; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_policy_demand_always_powered demand_always_powered; + struct kbasep_pm_policy_fast_start fast_start; +#endif +}; + +union kbase_pm_ca_policy_data { + struct kbasep_pm_ca_policy_fixed fixed; + struct kbasep_pm_ca_policy_devfreq devfreq; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_ca_policy_random random; +#endif +}; + +/** + * struct kbase_pm_backend_data - Data stored per device for power management. + * + * This structure contains data for the power management framework. There is one + * instance of this structure per device in the system. + * + * @ca_current_policy: The policy that is currently actively controlling core + * availability. + * @pm_current_policy: The policy that is currently actively controlling the + * power state. + * @ca_policy_data: Private data for current CA policy + * @pm_policy_data: Private data for current PM policy + * @ca_in_transition: Flag indicating when core availability policy is + * transitioning cores. The core availability policy must + * set this when a change in core availability is occurring. + * power_change_lock must be held when accessing this. + * @reset_done: Flag when a reset is complete + * @reset_done_wait: Wait queue to wait for changes to @reset_done + * @l2_powered_wait: Wait queue for whether the l2 cache has been powered as + * requested + * @l2_powered: State indicating whether all the l2 caches are powered. + * Non-zero indicates they're *all* powered + * Zero indicates that some (or all) are not powered + * @gpu_cycle_counter_requests: The reference count of active gpu cycle counter + * users + * @gpu_cycle_counter_requests_lock: Lock to protect @gpu_cycle_counter_requests + * @desired_shader_state: A bit mask identifying the shader cores that the + * power policy would like to be on. The current state + * of the cores may be different, but there should be + * transitions in progress that will eventually achieve + * this state (assuming that the policy doesn't change + * its mind in the mean time). + * @powering_on_shader_state: A bit mask indicating which shader cores are + * currently in a power-on transition + * @desired_tiler_state: A bit mask identifying the tiler cores that the power + * policy would like to be on. See @desired_shader_state + * @powering_on_tiler_state: A bit mask indicating which tiler core are + * currently in a power-on transition + * @powering_on_l2_state: A bit mask indicating which l2-caches are currently + * in a power-on transition + * @powering_on_stack_state: A bit mask indicating which core stacks are + * currently in a power-on transition + * @gpu_in_desired_state: This flag is set if the GPU is powered as requested + * by the desired_xxx_state variables + * @gpu_in_desired_state_wait: Wait queue set when @gpu_in_desired_state != 0 + * @gpu_powered: Set to true when the GPU is powered and register + * accesses are possible, false otherwise + * @instr_enabled: Set to true when instrumentation is enabled, + * false otherwise + * @cg1_disabled: Set if the policy wants to keep the second core group + * powered off + * @driver_ready_for_irqs: Debug state indicating whether sufficient + * initialization of the driver has occurred to handle + * IRQs + * @gpu_powered_lock: Spinlock that must be held when writing @gpu_powered or + * accessing @driver_ready_for_irqs + * @metrics: Structure to hold metrics for the GPU + * @gpu_poweroff_pending: number of poweroff timer ticks until the GPU is + * powered off + * @shader_poweroff_pending_time: number of poweroff timer ticks until shaders + * and/or timers are powered off + * @gpu_poweroff_timer: Timer for powering off GPU + * @gpu_poweroff_wq: Workqueue to power off GPU on when timer fires + * @gpu_poweroff_work: Workitem used on @gpu_poweroff_wq + * @shader_poweroff_pending: Bit mask of shaders to be powered off on next + * timer callback + * @tiler_poweroff_pending: Bit mask of tilers to be powered off on next timer + * callback + * @poweroff_timer_needed: true if the poweroff timer is currently required, + * false otherwise + * @poweroff_timer_running: true if the poweroff timer is currently running, + * false otherwise + * power_change_lock should be held when accessing, + * unless there is no way the timer can be running (eg + * hrtimer_cancel() was called immediately before) + * @poweroff_wait_in_progress: true if a wait for GPU power off is in progress. + * hwaccess_lock must be held when accessing + * @poweron_required: true if a GPU power on is required. Should only be set + * when poweroff_wait_in_progress is true, and therefore the + * GPU can not immediately be powered on. pm.lock must be + * held when accessing + * @poweroff_is_suspend: true if the GPU is being powered off due to a suspend + * request. pm.lock must be held when accessing + * @gpu_poweroff_wait_wq: workqueue for waiting for GPU to power off + * @gpu_poweroff_wait_work: work item for use with @gpu_poweroff_wait_wq + * @poweroff_wait: waitqueue for waiting for @gpu_poweroff_wait_work to complete + * @callback_power_on: Callback when the GPU needs to be turned on. See + * &struct kbase_pm_callback_conf + * @callback_power_off: Callback when the GPU may be turned off. See + * &struct kbase_pm_callback_conf + * @callback_power_suspend: Callback when a suspend occurs and the GPU needs to + * be turned off. See &struct kbase_pm_callback_conf + * @callback_power_resume: Callback when a resume occurs and the GPU needs to + * be turned on. See &struct kbase_pm_callback_conf + * @callback_power_runtime_on: Callback when the GPU needs to be turned on. See + * &struct kbase_pm_callback_conf + * @callback_power_runtime_off: Callback when the GPU may be turned off. See + * &struct kbase_pm_callback_conf + * @callback_power_runtime_idle: Optional callback when the GPU may be idle. See + * &struct kbase_pm_callback_conf + * + * Note: + * During an IRQ, @ca_current_policy or @pm_current_policy can be NULL when the + * policy is being changed with kbase_pm_ca_set_policy() or + * kbase_pm_set_policy(). The change is protected under + * kbase_device.pm.power_change_lock. Direct access to this + * from IRQ context must therefore check for NULL. If NULL, then + * kbase_pm_ca_set_policy() or kbase_pm_set_policy() will re-issue the policy + * functions that would have been done under IRQ. + */ +struct kbase_pm_backend_data { + const struct kbase_pm_ca_policy *ca_current_policy; + const struct kbase_pm_policy *pm_current_policy; + union kbase_pm_ca_policy_data ca_policy_data; + union kbase_pm_policy_data pm_policy_data; + bool ca_in_transition; + bool reset_done; + wait_queue_head_t reset_done_wait; + wait_queue_head_t l2_powered_wait; + int l2_powered; + int gpu_cycle_counter_requests; + spinlock_t gpu_cycle_counter_requests_lock; + + u64 desired_shader_state; + u64 powering_on_shader_state; + u64 desired_tiler_state; + u64 powering_on_tiler_state; + u64 powering_on_l2_state; +#ifdef CONFIG_MALI_CORESTACK + u64 powering_on_stack_state; +#endif /* CONFIG_MALI_CORESTACK */ + + bool gpu_in_desired_state; + wait_queue_head_t gpu_in_desired_state_wait; + + bool gpu_powered; + + bool instr_enabled; + + bool cg1_disabled; + +#ifdef CONFIG_MALI_DEBUG + bool driver_ready_for_irqs; +#endif /* CONFIG_MALI_DEBUG */ + + spinlock_t gpu_powered_lock; + + + struct kbasep_pm_metrics_data metrics; + + int gpu_poweroff_pending; + int shader_poweroff_pending_time; + + struct hrtimer gpu_poweroff_timer; + struct workqueue_struct *gpu_poweroff_wq; + struct work_struct gpu_poweroff_work; + + u64 shader_poweroff_pending; + u64 tiler_poweroff_pending; + + bool poweroff_timer_needed; + bool poweroff_timer_running; + + bool poweroff_wait_in_progress; + bool poweron_required; + bool poweroff_is_suspend; + + struct workqueue_struct *gpu_poweroff_wait_wq; + struct work_struct gpu_poweroff_wait_work; + + wait_queue_head_t poweroff_wait; + + int (*callback_power_on)(struct kbase_device *kbdev); + void (*callback_power_off)(struct kbase_device *kbdev); + void (*callback_power_suspend)(struct kbase_device *kbdev); + void (*callback_power_resume)(struct kbase_device *kbdev); + int (*callback_power_runtime_on)(struct kbase_device *kbdev); + void (*callback_power_runtime_off)(struct kbase_device *kbdev); + int (*callback_power_runtime_idle)(struct kbase_device *kbdev); +}; + + +/* List of policy IDs */ +enum kbase_pm_policy_id { + KBASE_PM_POLICY_ID_DEMAND = 1, + KBASE_PM_POLICY_ID_ALWAYS_ON, + KBASE_PM_POLICY_ID_COARSE_DEMAND, +#if !MALI_CUSTOMER_RELEASE + KBASE_PM_POLICY_ID_DEMAND_ALWAYS_POWERED, + KBASE_PM_POLICY_ID_FAST_START +#endif +}; + +typedef u32 kbase_pm_policy_flags; + +/** + * struct kbase_pm_policy - Power policy structure. + * + * Each power policy exposes a (static) instance of this structure which + * contains function pointers to the policy's methods. + * + * @name: The name of this policy + * @init: Function called when the policy is selected + * @term: Function called when the policy is unselected + * @get_core_mask: Function called to get the current shader core mask + * @get_core_active: Function called to get the current overall GPU power + * state + * @flags: Field indicating flags for this policy + * @id: Field indicating an ID for this policy. This is not + * necessarily the same as its index in the list returned + * by kbase_pm_list_policies(). + * It is used purely for debugging. + */ +struct kbase_pm_policy { + char *name; + + /** + * Function called when the policy is selected + * + * This should initialize the kbdev->pm.pm_policy_data structure. It + * should not attempt to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is + * called. + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** + * Function called when the policy is unselected. + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** + * Function called to get the current shader core mask + * + * The returned mask should meet or exceed (kbdev->shader_needed_bitmap + * | kbdev->shader_inuse_bitmap). + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + * + * Return: The mask of shader cores to be powered + */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** + * Function called to get the current overall GPU power state + * + * This function should consider the state of kbdev->pm.active_count. If + * this count is greater than 0 then there is at least one active + * context on the device and the GPU should be powered. If it is equal + * to 0 then there are no active contexts and the GPU could be powered + * off if desired. + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + * + * Return: true if the GPU should be powered, false otherwise + */ + bool (*get_core_active)(struct kbase_device *kbdev); + + kbase_pm_policy_flags flags; + enum kbase_pm_policy_id id; +}; + + +enum kbase_pm_ca_policy_id { + KBASE_PM_CA_POLICY_ID_FIXED = 1, + KBASE_PM_CA_POLICY_ID_DEVFREQ, + KBASE_PM_CA_POLICY_ID_RANDOM +}; + +typedef u32 kbase_pm_ca_policy_flags; + +/** + * Maximum length of a CA policy names + */ +#define KBASE_PM_CA_MAX_POLICY_NAME_LEN 15 + +/** + * struct kbase_pm_ca_policy - Core availability policy structure. + * + * Each core availability policy exposes a (static) instance of this structure + * which contains function pointers to the policy's methods. + * + * @name: The name of this policy + * @init: Function called when the policy is selected + * @term: Function called when the policy is unselected + * @get_core_mask: Function called to get the current shader core + * availability mask + * @update_core_status: Function called to update the current core status + * @flags: Field indicating flags for this policy + * @id: Field indicating an ID for this policy. This is not + * necessarily the same as its index in the list returned + * by kbase_pm_list_policies(). + * It is used purely for debugging. + */ +struct kbase_pm_ca_policy { + char name[KBASE_PM_CA_MAX_POLICY_NAME_LEN + 1]; + + /** + * Function called when the policy is selected + * + * This should initialize the kbdev->pm.ca_policy_data structure. It + * should not attempt to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is + * called. + * + * @kbdev The kbase device structure for the device (must be a + * valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** + * Function called when the policy is unselected. + * + * @kbdev The kbase device structure for the device (must be a + * valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** + * Function called to get the current shader core availability mask + * + * When a change in core availability is occurring, the policy must set + * kbdev->pm.ca_in_transition to true. This is to indicate that + * reporting changes in power state cannot be optimized out, even if + * kbdev->pm.desired_shader_state remains unchanged. This must be done + * by any functions internal to the Core Availability Policy that change + * the return value of kbase_pm_ca_policy::get_core_mask. + * + * @kbdev The kbase device structure for the device (must be a + * valid pointer) + * + * Return: The current core availability mask + */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** + * Function called to update the current core status + * + * If none of the cores in core group 0 are ready or transitioning, then + * the policy must ensure that the next call to get_core_mask does not + * return 0 for all cores in core group 0. It is an error to disable + * core group 0 through the core availability policy. + * + * When a change in core availability has finished, the policy must set + * kbdev->pm.ca_in_transition to false. This is to indicate that + * changes in power state can once again be optimized out when + * kbdev->pm.desired_shader_state is unchanged. + * + * @kbdev: The kbase device structure for the device + * (must be a valid pointer) + * @cores_ready: The mask of cores currently powered and + * ready to run jobs + * @cores_transitioning: The mask of cores currently transitioning + * power state + */ + void (*update_core_status)(struct kbase_device *kbdev, u64 cores_ready, + u64 cores_transitioning); + + kbase_pm_ca_policy_flags flags; + + /** + * Field indicating an ID for this policy. This is not necessarily the + * same as its index in the list returned by kbase_pm_list_policies(). + * It is used purely for debugging. + */ + enum kbase_pm_ca_policy_id id; +}; + +#endif /* _KBASE_PM_HWACCESS_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.c new file mode 100644 index 000000000000..81322fd0dd17 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * A simple demand based power management policy + */ + +#include +#include + +static u64 demand_get_core_mask(struct kbase_device *kbdev) +{ + u64 desired = kbdev->shader_needed_bitmap | kbdev->shader_inuse_bitmap; + + if (0 == kbdev->pm.active_count) + return 0; + + return desired; +} + +static bool demand_get_core_active(struct kbase_device *kbdev) +{ + if (0 == kbdev->pm.active_count && !(kbdev->shader_needed_bitmap | + kbdev->shader_inuse_bitmap) && !kbdev->tiler_needed_cnt + && !kbdev->tiler_inuse_cnt) + return false; + + return true; +} + +static void demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/* + * The struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback + * and name. + */ +const struct kbase_pm_policy kbase_pm_demand_policy_ops = { + "demand", /* name */ + demand_init, /* init */ + demand_term, /* term */ + demand_get_core_mask, /* get_core_mask */ + demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_demand_policy_ops); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.h new file mode 100644 index 000000000000..c0c84b6e9189 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_demand.h @@ -0,0 +1,64 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * A simple demand based power management policy + */ + +#ifndef MALI_KBASE_PM_DEMAND_H +#define MALI_KBASE_PM_DEMAND_H + +/** + * DOC: Demand power management policy + * + * The demand power management policy has the following characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - The Shader Cores are not powered up + * + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - Only those Shader Cores are powered up + * + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * Note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * struct kbasep_pm_policy_demand - Private structure for policy instance data + * + * @dummy: No state is needed, a dummy variable + * + * This contains data that is private to the demand power policy. + */ +struct kbasep_pm_policy_demand { + int dummy; +}; + +extern const struct kbase_pm_policy kbase_pm_demand_policy_ops; + +#endif /* MALI_KBASE_PM_DEMAND_H */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c new file mode 100644 index 000000000000..cbc258cb361b --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c @@ -0,0 +1,1672 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel Power Management hardware control + */ + +#include +#include +#include +#if defined(CONFIG_MALI_GATOR_SUPPORT) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if MALI_MOCK_TEST +#define MOCKABLE(function) function##_original +#else +#define MOCKABLE(function) function +#endif /* MALI_MOCK_TEST */ + +/** + * enum kbasep_pm_action - Actions that can be performed on a core. + * + * This enumeration is private to the file. Its values are set to allow + * core_type_to_reg() function, which decodes this enumeration, to be simpler + * and more efficient. + * + * @ACTION_PRESENT: The cores that are present + * @ACTION_READY: The cores that are ready + * @ACTION_PWRON: Power on the cores specified + * @ACTION_PWROFF: Power off the cores specified + * @ACTION_PWRTRANS: The cores that are transitioning + * @ACTION_PWRACTIVE: The cores that are active + */ +enum kbasep_pm_action { + ACTION_PRESENT = 0, + ACTION_READY = (SHADER_READY_LO - SHADER_PRESENT_LO), + ACTION_PWRON = (SHADER_PWRON_LO - SHADER_PRESENT_LO), + ACTION_PWROFF = (SHADER_PWROFF_LO - SHADER_PRESENT_LO), + ACTION_PWRTRANS = (SHADER_PWRTRANS_LO - SHADER_PRESENT_LO), + ACTION_PWRACTIVE = (SHADER_PWRACTIVE_LO - SHADER_PRESENT_LO) +}; + +static u64 kbase_pm_get_state( + struct kbase_device *kbdev, + enum kbase_pm_core_type core_type, + enum kbasep_pm_action action); + +/** + * core_type_to_reg - Decode a core type and action to a register. + * + * Given a core type (defined by kbase_pm_core_type) and an action (defined + * by kbasep_pm_action) this function will return the register offset that + * will perform the action on the core type. The register returned is the _LO + * register and an offset must be applied to use the _HI register. + * + * @core_type: The type of core + * @action: The type of action + * + * Return: The register offset of the _LO register that performs an action of + * type @action on a core of type @core_type. + */ +static u32 core_type_to_reg(enum kbase_pm_core_type core_type, + enum kbasep_pm_action action) +{ +#ifdef CONFIG_MALI_CORESTACK + if (core_type == KBASE_PM_CORE_STACK) { + switch (action) { + case ACTION_PRESENT: + return STACK_PRESENT_LO; + case ACTION_READY: + return STACK_READY_LO; + case ACTION_PWRON: + return STACK_PWRON_LO; + case ACTION_PWROFF: + return STACK_PWROFF_LO; + case ACTION_PWRTRANS: + return STACK_PWRTRANS_LO; + default: + BUG(); + } + } +#endif /* CONFIG_MALI_CORESTACK */ + + return (u32)core_type + (u32)action; +} + +#ifdef CONFIG_ARM64 +static void mali_cci_flush_l2(struct kbase_device *kbdev) +{ + const u32 mask = CLEAN_CACHES_COMPLETED | RESET_COMPLETED; + u32 loops = KBASE_CLEAN_CACHE_MAX_LOOPS; + u32 raw; + + /* + * Note that we don't take the cache flush mutex here since + * we expect to be the last user of the L2, all other L2 users + * would have dropped their references, to initiate L2 power + * down, L2 power down being the only valid place for this + * to be called from. + */ + + kbase_reg_write(kbdev, + GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CLEAN_INV_CACHES, + NULL); + + raw = kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), + NULL); + + /* Wait for cache flush to complete before continuing, exit on + * gpu resets or loop expiry. */ + while (((raw & mask) == 0) && --loops) { + raw = kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), + NULL); + } +} +#endif + +/** + * kbase_pm_invoke - Invokes an action on a core set + * + * This function performs the action given by @action on a set of cores of a + * type given by @core_type. It is a static function used by + * kbase_pm_transition_core_type() + * + * @kbdev: The kbase device structure of the device + * @core_type: The type of core that the action should be performed on + * @cores: A bit mask of cores to perform the action on (low 32 bits) + * @action: The action to perform on the cores + */ +static void kbase_pm_invoke(struct kbase_device *kbdev, + enum kbase_pm_core_type core_type, + u64 cores, + enum kbasep_pm_action action) +{ + u32 reg; + u32 lo = cores & 0xFFFFFFFF; + u32 hi = (cores >> 32) & 0xFFFFFFFF; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); +#if defined(CONFIG_MALI_GATOR_SUPPORT) + if (cores) { + if (action == ACTION_PWRON) + kbase_trace_mali_pm_power_on(core_type, cores); + else if (action == ACTION_PWROFF) + kbase_trace_mali_pm_power_off(core_type, cores); + } +#endif + + if (cores) { + u64 state = kbase_pm_get_state(kbdev, core_type, ACTION_READY); + + if (action == ACTION_PWRON) + state |= cores; + else if (action == ACTION_PWROFF) + state &= ~cores; + KBASE_TLSTREAM_AUX_PM_STATE(core_type, state); + } + + /* Tracing */ + if (cores) { + if (action == ACTION_PWRON) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWRON, NULL, NULL, 0u, + lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWRON_TILER, NULL, + NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWRON_L2, NULL, NULL, + 0u, lo); + break; + default: + break; + } + else if (action == ACTION_PWROFF) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF, NULL, NULL, + 0u, lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_TILER, NULL, + NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_L2, NULL, NULL, + 0u, lo); + /* disable snoops before L2 is turned off */ + kbase_pm_cache_snoop_disable(kbdev); + break; + default: + break; + } + } + + if (lo != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg), lo, NULL); + + if (hi != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg + 4), hi, NULL); +} + +/** + * kbase_pm_get_state - Get information about a core set + * + * This function gets information (chosen by @action) about a set of cores of + * a type given by @core_type. It is a static function used by + * kbase_pm_get_active_cores(), kbase_pm_get_trans_cores() and + * kbase_pm_get_ready_cores(). + * + * @kbdev: The kbase device structure of the device + * @core_type: The type of core that the should be queried + * @action: The property of the cores to query + * + * Return: A bit mask specifying the state of the cores + */ +static u64 kbase_pm_get_state(struct kbase_device *kbdev, + enum kbase_pm_core_type core_type, + enum kbasep_pm_action action) +{ + u32 reg; + u32 lo, hi; + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); + + lo = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg), NULL); + hi = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg + 4), NULL); + + return (((u64) hi) << 32) | ((u64) lo); +} + +void kbasep_pm_init_core_use_bitmaps(struct kbase_device *kbdev) +{ + kbdev->shader_inuse_bitmap = 0; + kbdev->shader_needed_bitmap = 0; + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_users_count = 0; + kbdev->l2_available_bitmap = 0; + kbdev->tiler_needed_cnt = 0; + kbdev->tiler_inuse_cnt = 0; + + memset(kbdev->shader_needed_cnt, 0, sizeof(kbdev->shader_needed_cnt)); +} + +/** + * kbase_pm_get_present_cores - Get the cores that are present + * + * @kbdev: Kbase device + * @type: The type of cores to query + * + * Return: Bitmask of the cores that are present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + switch (type) { + case KBASE_PM_CORE_L2: + return kbdev->gpu_props.props.raw_props.l2_present; + case KBASE_PM_CORE_SHADER: + return kbdev->gpu_props.props.raw_props.shader_present; + case KBASE_PM_CORE_TILER: + return kbdev->gpu_props.props.raw_props.tiler_present; +#ifdef CONFIG_MALI_CORESTACK + case KBASE_PM_CORE_STACK: + return kbdev->gpu_props.props.raw_props.stack_present; +#endif /* CONFIG_MALI_CORESTACK */ + default: + break; + } + KBASE_DEBUG_ASSERT(0); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_present_cores); + +/** + * kbase_pm_get_active_cores - Get the cores that are "active" + * (busy processing work) + * + * @kbdev: Kbase device + * @type: The type of cores to query + * + * Return: Bitmask of cores that are active + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRACTIVE); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_active_cores); + +/** + * kbase_pm_get_trans_cores - Get the cores that are transitioning between + * power states + * + * @kbdev: Kbase device + * @type: The type of cores to query + * + * Return: Bitmask of cores that are transitioning + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRTRANS); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_trans_cores); + +/** + * kbase_pm_get_ready_cores - Get the cores that are powered on + * + * @kbdev: Kbase device + * @type: The type of cores to query + * + * Return: Bitmask of cores that are ready (powered on) + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type) +{ + u64 result; + + result = kbase_pm_get_state(kbdev, type, ACTION_READY); + + switch (type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED, NULL, NULL, 0u, + (u32) result); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_TILER, NULL, NULL, 0u, + (u32) result); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_L2, NULL, NULL, 0u, + (u32) result); + break; + default: + break; + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_ready_cores); + +/** + * kbase_pm_transition_core_type - Perform power transitions for a particular + * core type. + * + * This function will perform any available power transitions to make the actual + * hardware state closer to the desired state. If a core is currently + * transitioning then changes to the power state of that call cannot be made + * until the transition has finished. Cores which are not present in the + * hardware are ignored if they are specified in the desired_state bitmask, + * however the return value will always be 0 in this case. + * + * @kbdev: The kbase device + * @type: The core type to perform transitions for + * @desired_state: A bit mask of the desired state of the cores + * @in_use: A bit mask of the cores that are currently running + * jobs. These cores have to be kept powered up because + * there are jobs running (or about to run) on them. + * @available: Receives a bit mask of the cores that the job + * scheduler can use to submit jobs to. May be NULL if + * this is not needed. + * @powering_on: Bit mask to update with cores that are + * transitioning to a power-on state. + * + * Return: true if the desired state has been reached, false otherwise + */ +static bool kbase_pm_transition_core_type(struct kbase_device *kbdev, + enum kbase_pm_core_type type, + u64 desired_state, + u64 in_use, + u64 * const available, + u64 *powering_on) +{ + u64 present; + u64 ready; + u64 trans; + u64 powerup; + u64 powerdown; + u64 powering_on_trans; + u64 desired_state_in_use; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* Get current state */ + present = kbase_pm_get_present_cores(kbdev, type); + trans = kbase_pm_get_trans_cores(kbdev, type); + ready = kbase_pm_get_ready_cores(kbdev, type); + /* mask off ready from trans in case transitions finished between the + * register reads */ + trans &= ~ready; + + if (trans) /* Do not progress if any cores are transitioning */ + return false; + + powering_on_trans = trans & *powering_on; + *powering_on = powering_on_trans; + + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + /* Update desired state to include the in-use cores. These have to be + * kept powered up because there are jobs running or about to run on + * these cores + */ + desired_state_in_use = desired_state | in_use; + + /* Update state of whether l2 caches are powered */ + if (type == KBASE_PM_CORE_L2) { + if ((ready == present) && (desired_state_in_use == ready) && + (trans == 0)) { + /* All are ready, none will be turned off, and none are + * transitioning */ + kbdev->pm.backend.l2_powered = 1; + /* + * Ensure snoops are enabled after L2 is powered up, + * note that kbase keeps track of the snoop state, so + * safe to repeatedly call. + */ + kbase_pm_cache_snoop_enable(kbdev); + if (kbdev->l2_users_count > 0) { + /* Notify any registered l2 cache users + * (optimized out when no users waiting) */ + wake_up(&kbdev->pm.backend.l2_powered_wait); + } + } else + kbdev->pm.backend.l2_powered = 0; + } + + if (desired_state == ready && (trans == 0)) + return true; + + /* Restrict the cores to those that are actually present */ + powerup = desired_state_in_use & present; + powerdown = (~desired_state_in_use) & present; + + /* Restrict to cores that are not already in the desired state */ + powerup &= ~ready; + powerdown &= ready; + + /* Don't transition any cores that are already transitioning, except for + * Mali cores that support the following case: + * + * If the SHADER_PWRON or TILER_PWRON registers are written to turn on + * a core that is currently transitioning to power off, then this is + * remembered and the shader core is automatically powered up again once + * the original transition completes. Once the automatic power on is + * complete any job scheduled on the shader core should start. + */ + powerdown &= ~trans; + + if (kbase_hw_has_feature(kbdev, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS)) + if (KBASE_PM_CORE_SHADER == type || KBASE_PM_CORE_TILER == type) + trans = powering_on_trans; /* for exception cases, only + * mask off cores in power on + * transitions */ + + powerup &= ~trans; + + /* Perform transitions if any */ + kbase_pm_invoke(kbdev, type, powerup, ACTION_PWRON); +#if !PLATFORM_POWER_DOWN_ONLY + kbase_pm_invoke(kbdev, type, powerdown, ACTION_PWROFF); +#endif + + /* Recalculate cores transitioning on, and re-evaluate our state */ + powering_on_trans |= powerup; + *powering_on = powering_on_trans; + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + return false; +} + +KBASE_EXPORT_TEST_API(kbase_pm_transition_core_type); + +/** + * get_desired_cache_status - Determine which caches should be on for a + * particular core state + * + * This function takes a bit mask of the present caches and the cores (or + * caches) that are attached to the caches that will be powered. It then + * computes which caches should be turned on to allow the cores requested to be + * powered up. + * + * @present: The bit mask of present caches + * @cores_powered: A bit mask of cores (or L2 caches) that are desired to + * be powered + * @tilers_powered: The bit mask of tilers that are desired to be powered + * + * Return: A bit mask of the caches that should be turned on + */ +static u64 get_desired_cache_status(u64 present, u64 cores_powered, + u64 tilers_powered) +{ + u64 desired = 0; + + while (present) { + /* Find out which is the highest set bit */ + u64 bit = fls64(present) - 1; + u64 bit_mask = 1ull << bit; + /* Create a mask which has all bits from 'bit' upwards set */ + + u64 mask = ~(bit_mask - 1); + + /* If there are any cores powered at this bit or above (that + * haven't previously been processed) then we need this core on + */ + if (cores_powered & mask) + desired |= bit_mask; + + /* Remove bits from cores_powered and present */ + cores_powered &= ~mask; + present &= ~bit_mask; + } + + /* Power up the required L2(s) for the tiler */ + if (tilers_powered) + desired |= 1; + + return desired; +} + +KBASE_EXPORT_TEST_API(get_desired_cache_status); + +#ifdef CONFIG_MALI_CORESTACK +u64 kbase_pm_core_stack_mask(u64 cores) +{ + u64 stack_mask = 0; + size_t const MAX_CORE_ID = 31; + size_t const NUM_CORES_PER_STACK = 4; + size_t i; + + for (i = 0; i <= MAX_CORE_ID; ++i) { + if (test_bit(i, (unsigned long *)&cores)) { + /* Every core which ID >= 16 is filled to stacks 4-7 + * instead of 0-3 */ + size_t const stack_num = (i > 16) ? + (i % NUM_CORES_PER_STACK) + 4 : + (i % NUM_CORES_PER_STACK); + set_bit(stack_num, (unsigned long *)&stack_mask); + } + } + + return stack_mask; +} +#endif /* CONFIG_MALI_CORESTACK */ + +bool +MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev) +{ + bool cores_are_available = false; + bool in_desired_state = true; + u64 desired_l2_state; +#ifdef CONFIG_MALI_CORESTACK + u64 desired_stack_state; + u64 stacks_powered; +#endif /* CONFIG_MALI_CORESTACK */ + u64 cores_powered; + u64 tilers_powered; + u64 tiler_available_bitmap; + u64 tiler_transitioning_bitmap; + u64 shader_available_bitmap; + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + u64 l2_available_bitmap; + u64 prev_l2_available_bitmap; + u64 l2_inuse_bitmap; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->hwaccess_lock); + + spin_lock(&kbdev->pm.backend.gpu_powered_lock); + if (kbdev->pm.backend.gpu_powered == false) { + spin_unlock(&kbdev->pm.backend.gpu_powered_lock); + if (kbdev->pm.backend.desired_shader_state == 0 && + kbdev->pm.backend.desired_tiler_state == 0) + return true; + return false; + } + + /* Trace that a change-state is being requested, and that it took + * (effectively) no time to start it. This is useful for counting how + * many state changes occurred, in a way that's backwards-compatible + * with processing the trace data */ + kbase_timeline_pm_send_event(kbdev, + KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + kbase_timeline_pm_handle_event(kbdev, + KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + + /* If any cores are already powered then, we must keep the caches on */ + shader_transitioning_bitmap = kbase_pm_get_trans_cores(kbdev, + KBASE_PM_CORE_SHADER); + cores_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + cores_powered |= kbdev->pm.backend.desired_shader_state; + +#ifdef CONFIG_MALI_CORESTACK + /* Work out which core stacks want to be powered */ + desired_stack_state = kbase_pm_core_stack_mask(cores_powered); + stacks_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_STACK) | + desired_stack_state; +#endif /* CONFIG_MALI_CORESTACK */ + + /* Work out which tilers want to be powered */ + tiler_transitioning_bitmap = kbase_pm_get_trans_cores(kbdev, + KBASE_PM_CORE_TILER); + tilers_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER); + tilers_powered |= kbdev->pm.backend.desired_tiler_state; + + /* If there are l2 cache users registered, keep all l2s powered even if + * all other cores are off. */ + if (kbdev->l2_users_count > 0) + cores_powered |= kbdev->gpu_props.props.raw_props.l2_present; + + desired_l2_state = get_desired_cache_status( + kbdev->gpu_props.props.raw_props.l2_present, + cores_powered, tilers_powered); + + l2_inuse_bitmap = get_desired_cache_status( + kbdev->gpu_props.props.raw_props.l2_present, + cores_powered | shader_transitioning_bitmap, + tilers_powered | tiler_transitioning_bitmap); + +#ifdef CONFIG_MALI_CORESTACK + if (stacks_powered) + desired_l2_state |= 1; +#endif /* CONFIG_MALI_CORESTACK */ + + /* If any l2 cache is on, then enable l2 #0, for use by job manager */ + if (0 != desired_l2_state) + desired_l2_state |= 1; + + prev_l2_available_bitmap = kbdev->l2_available_bitmap; + in_desired_state &= kbase_pm_transition_core_type(kbdev, + KBASE_PM_CORE_L2, desired_l2_state, l2_inuse_bitmap, + &l2_available_bitmap, + &kbdev->pm.backend.powering_on_l2_state); + + if (kbdev->l2_available_bitmap != l2_available_bitmap) + KBASE_TIMELINE_POWER_L2(kbdev, l2_available_bitmap); + + kbdev->l2_available_bitmap = l2_available_bitmap; + + +#ifdef CONFIG_MALI_CORESTACK + if (in_desired_state) { + in_desired_state &= kbase_pm_transition_core_type(kbdev, + KBASE_PM_CORE_STACK, desired_stack_state, 0, + &kbdev->stack_available_bitmap, + &kbdev->pm.backend.powering_on_stack_state); + } +#endif /* CONFIG_MALI_CORESTACK */ + + if (in_desired_state) { + in_desired_state &= kbase_pm_transition_core_type(kbdev, + KBASE_PM_CORE_TILER, + kbdev->pm.backend.desired_tiler_state, + 0, &tiler_available_bitmap, + &kbdev->pm.backend.powering_on_tiler_state); + in_desired_state &= kbase_pm_transition_core_type(kbdev, + KBASE_PM_CORE_SHADER, + kbdev->pm.backend.desired_shader_state, + kbdev->shader_inuse_bitmap, + &shader_available_bitmap, + &kbdev->pm.backend.powering_on_shader_state); + + if (kbdev->shader_available_bitmap != shader_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, + NULL, 0u, + (u32) shader_available_bitmap); + KBASE_TIMELINE_POWER_SHADER(kbdev, + shader_available_bitmap); + } + + kbdev->shader_available_bitmap = shader_available_bitmap; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, + NULL, NULL, 0u, + (u32) tiler_available_bitmap); + KBASE_TIMELINE_POWER_TILER(kbdev, + tiler_available_bitmap); + } + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + + } else if ((l2_available_bitmap & + kbdev->gpu_props.props.raw_props.tiler_present) != + kbdev->gpu_props.props.raw_props.tiler_present) { + tiler_available_bitmap = 0; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) + KBASE_TIMELINE_POWER_TILER(kbdev, + tiler_available_bitmap); + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + } + + /* State updated for slow-path waiters */ + kbdev->pm.backend.gpu_in_desired_state = in_desired_state; + + shader_ready_bitmap = kbase_pm_get_ready_cores(kbdev, + KBASE_PM_CORE_SHADER); + shader_transitioning_bitmap = kbase_pm_get_trans_cores(kbdev, + KBASE_PM_CORE_SHADER); + + /* Determine whether the cores are now available (even if the set of + * available cores is empty). Note that they can be available even if + * we've not finished transitioning to the desired state */ + if ((kbdev->shader_available_bitmap & + kbdev->pm.backend.desired_shader_state) + == kbdev->pm.backend.desired_shader_state && + (kbdev->tiler_available_bitmap & + kbdev->pm.backend.desired_tiler_state) + == kbdev->pm.backend.desired_tiler_state) { + cores_are_available = true; + + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE, NULL, NULL, 0u, + (u32)(kbdev->shader_available_bitmap & + kbdev->pm.backend.desired_shader_state)); + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE_TILER, NULL, NULL, 0u, + (u32)(kbdev->tiler_available_bitmap & + kbdev->pm.backend.desired_tiler_state)); + + /* Log timelining information about handling events that power + * up cores, to match up either with immediate submission either + * because cores already available, or from PM IRQ */ + if (!in_desired_state) + kbase_timeline_pm_send_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + } + + if (in_desired_state) { + KBASE_DEBUG_ASSERT(cores_are_available); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_pm_status(KBASE_PM_CORE_L2, + kbase_pm_get_ready_cores(kbdev, + KBASE_PM_CORE_L2)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_SHADER, + kbase_pm_get_ready_cores(kbdev, + KBASE_PM_CORE_SHADER)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_TILER, + kbase_pm_get_ready_cores(kbdev, + KBASE_PM_CORE_TILER)); +#ifdef CONFIG_MALI_CORESTACK + kbase_trace_mali_pm_status(KBASE_PM_CORE_STACK, + kbase_pm_get_ready_cores(kbdev, + KBASE_PM_CORE_STACK)); +#endif /* CONFIG_MALI_CORESTACK */ +#endif + + KBASE_TLSTREAM_AUX_PM_STATE( + KBASE_PM_CORE_L2, + kbase_pm_get_ready_cores( + kbdev, KBASE_PM_CORE_L2)); + KBASE_TLSTREAM_AUX_PM_STATE( + KBASE_PM_CORE_SHADER, + kbase_pm_get_ready_cores( + kbdev, KBASE_PM_CORE_SHADER)); + KBASE_TLSTREAM_AUX_PM_STATE( + KBASE_PM_CORE_TILER, + kbase_pm_get_ready_cores( + kbdev, + KBASE_PM_CORE_TILER)); +#ifdef CONFIG_MALI_CORESTACK + KBASE_TLSTREAM_AUX_PM_STATE( + KBASE_PM_CORE_STACK, + kbase_pm_get_ready_cores( + kbdev, + KBASE_PM_CORE_STACK)); +#endif /* CONFIG_MALI_CORESTACK */ + + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL, NULL, + kbdev->pm.backend.gpu_in_desired_state, + (u32)kbdev->pm.backend.desired_shader_state); + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED_TILER, NULL, NULL, 0u, + (u32)kbdev->pm.backend.desired_tiler_state); + + /* Log timelining information for synchronous waiters */ + kbase_timeline_pm_send_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + /* Wake slow-path waiters. Job scheduler does not use this. */ + KBASE_TRACE_ADD(kbdev, PM_WAKE_WAITERS, NULL, NULL, 0u, 0); + + wake_up(&kbdev->pm.backend.gpu_in_desired_state_wait); + } + + spin_unlock(&kbdev->pm.backend.gpu_powered_lock); + + /* kbase_pm_ca_update_core_status can cause one-level recursion into + * this function, so it must only be called once all changes to kbdev + * have been committed, and after the gpu_powered_lock has been + * dropped. */ + if (kbdev->shader_ready_bitmap != shader_ready_bitmap || + kbdev->shader_transitioning_bitmap != shader_transitioning_bitmap) { + kbdev->shader_ready_bitmap = shader_ready_bitmap; + kbdev->shader_transitioning_bitmap = + shader_transitioning_bitmap; + + kbase_pm_ca_update_core_status(kbdev, shader_ready_bitmap, + shader_transitioning_bitmap); + } + + /* The core availability policy is not allowed to keep core group 0 + * turned off (unless it was changing the l2 power state) */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & + kbdev->gpu_props.props.coherency_info.group[0].core_mask) && + (prev_l2_available_bitmap == desired_l2_state) && + !(kbase_pm_ca_get_core_mask(kbdev) & + kbdev->gpu_props.props.coherency_info.group[0].core_mask)) + BUG(); + + /* The core availability policy is allowed to keep core group 1 off, + * but all jobs specifically targeting CG1 must fail */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & + kbdev->gpu_props.props.coherency_info.group[1].core_mask) && + !(kbase_pm_ca_get_core_mask(kbdev) & + kbdev->gpu_props.props.coherency_info.group[1].core_mask)) + kbdev->pm.backend.cg1_disabled = true; + else + kbdev->pm.backend.cg1_disabled = false; + + return cores_are_available; +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_nolock); + +/* Timeout for kbase_pm_check_transitions_sync when wait_event_killable has + * aborted due to a fatal signal. If the time spent waiting has exceeded this + * threshold then there is most likely a hardware issue. */ +#define PM_TIMEOUT (5*HZ) /* 5s */ + +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev) +{ + unsigned long flags; + unsigned long timeout; + bool cores_are_available; + int ret; + + /* Force the transition to be checked and reported - the cores may be + * 'available' (for job submission) but not fully powered up. */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + timeout = jiffies + PM_TIMEOUT; + + /* Wait for cores */ + ret = wait_event_killable(kbdev->pm.backend.gpu_in_desired_state_wait, + kbdev->pm.backend.gpu_in_desired_state); + + if (ret < 0 && time_after(jiffies, timeout)) { + dev_err(kbdev->dev, "Power transition timed out unexpectedly\n"); + dev_err(kbdev->dev, "Desired state :\n"); + dev_err(kbdev->dev, "\tShader=%016llx\n", + kbdev->pm.backend.desired_shader_state); + dev_err(kbdev->dev, "\tTiler =%016llx\n", + kbdev->pm.backend.desired_tiler_state); + dev_err(kbdev->dev, "Current state :\n"); + dev_err(kbdev->dev, "\tShader=%08x%08x\n", + kbase_reg_read(kbdev, + GPU_CONTROL_REG(SHADER_READY_HI), NULL), + kbase_reg_read(kbdev, + GPU_CONTROL_REG(SHADER_READY_LO), + NULL)); + dev_err(kbdev->dev, "\tTiler =%08x%08x\n", + kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_READY_HI), NULL), + kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_READY_LO), NULL)); + dev_err(kbdev->dev, "\tL2 =%08x%08x\n", + kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_READY_HI), NULL), + kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_READY_LO), NULL)); + dev_err(kbdev->dev, "Cores transitioning :\n"); + dev_err(kbdev->dev, "\tShader=%08x%08x\n", + kbase_reg_read(kbdev, GPU_CONTROL_REG( + SHADER_PWRTRANS_HI), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG( + SHADER_PWRTRANS_LO), NULL)); + dev_err(kbdev->dev, "\tTiler =%08x%08x\n", + kbase_reg_read(kbdev, GPU_CONTROL_REG( + TILER_PWRTRANS_HI), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG( + TILER_PWRTRANS_LO), NULL)); + dev_err(kbdev->dev, "\tL2 =%08x%08x\n", + kbase_reg_read(kbdev, GPU_CONTROL_REG( + L2_PWRTRANS_HI), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG( + L2_PWRTRANS_LO), NULL)); +#if KBASE_GPU_RESET_EN + dev_err(kbdev->dev, "Sending reset to GPU - all running jobs will be lost\n"); + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ + } else { + /* Log timelining information that a change in state has + * completed */ + kbase_timeline_pm_handle_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + } +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_sync); + +void kbase_pm_enable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Clear all interrupts, + * and unmask them all. + */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, + NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), GPU_IRQ_REG_ALL, + NULL); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, + NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0xFFFFFFFF, NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0xFFFFFFFF, NULL); +} + +KBASE_EXPORT_TEST_API(kbase_pm_enable_interrupts); + +void kbase_pm_disable_interrupts_nolock(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Mask all interrupts, + * and clear them all. + */ + lockdep_assert_held(&kbdev->hwaccess_lock); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, + NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, + NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); +} + +void kbase_pm_disable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_disable_interrupts_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts); + + +/* + * pmu layout: + * 0x0000: PMU TAG (RO) (0xCAFECAFE) + * 0x0004: PMU VERSION ID (RO) (0x00000000) + * 0x0008: CLOCK ENABLE (RW) (31:1 SBZ, 0 CLOCK STATE) + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) +{ + bool reset_required = is_resume; + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&kbdev->pm.lock); + + if (kbdev->pm.backend.gpu_powered) { + /* Already turned on */ + if (kbdev->poweroff_pending) + kbase_pm_enable_interrupts(kbdev); + kbdev->poweroff_pending = false; + KBASE_DEBUG_ASSERT(!is_resume); + return; + } + + kbdev->poweroff_pending = false; + + KBASE_TRACE_ADD(kbdev, PM_GPU_ON, NULL, NULL, 0u, 0u); + + if (is_resume && kbdev->pm.backend.callback_power_resume) { + kbdev->pm.backend.callback_power_resume(kbdev); + return; + } else if (kbdev->pm.backend.callback_power_on) { + kbdev->pm.backend.callback_power_on(kbdev); + /* If your platform properly keeps the GPU state you may use the + * return value of the callback_power_on function to + * conditionally reset the GPU on power up. Currently we are + * conservative and always reset the GPU. */ + reset_required = true; + } + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + kbdev->pm.backend.gpu_powered = true; + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (reset_required) { + /* GPU state was lost, reset GPU to ensure it is in a + * consistent state */ + kbase_pm_init_hw(kbdev, PM_ENABLE_IRQS); + } + + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_ctx_sched_restore_all_as(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + /* Lastly, enable the interrupts */ + kbase_pm_enable_interrupts(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_on); + +bool kbase_pm_clock_off(struct kbase_device *kbdev, bool is_suspend) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* ASSERT that the cores should now be unavailable. No lock needed. */ + KBASE_DEBUG_ASSERT(kbdev->shader_available_bitmap == 0u); + + kbdev->poweroff_pending = true; + + if (!kbdev->pm.backend.gpu_powered) { + /* Already turned off */ + if (is_suspend && kbdev->pm.backend.callback_power_suspend) + kbdev->pm.backend.callback_power_suspend(kbdev); + return true; + } + + KBASE_TRACE_ADD(kbdev, PM_GPU_OFF, NULL, NULL, 0u, 0u); + + /* Disable interrupts. This also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + /* Ensure that any IRQ handlers have finished */ + kbase_synchronize_irqs(kbdev); + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (atomic_read(&kbdev->faults_pending)) { + /* Page/bus faults are still being processed. The GPU can not + * be powered off until they have completed */ + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + flags); + return false; + } + + kbase_pm_cache_snoop_disable(kbdev); + + /* The GPU power may be turned off from this point */ + kbdev->pm.backend.gpu_powered = false; + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); + + if (is_suspend && kbdev->pm.backend.callback_power_suspend) + kbdev->pm.backend.callback_power_suspend(kbdev); + else if (kbdev->pm.backend.callback_power_off) + kbdev->pm.backend.callback_power_off(kbdev); + return true; +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_off); + +struct kbasep_reset_timeout_data { + struct hrtimer timer; + bool timed_out; + struct kbase_device *kbdev; +}; + +void kbase_pm_reset_done(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + kbdev->pm.backend.reset_done = true; + wake_up(&kbdev->pm.backend.reset_done_wait); +} + +/** + * kbase_pm_wait_for_reset - Wait for a reset to happen + * + * Wait for the %RESET_COMPLETED IRQ to occur, then reset the waiting state. + * + * @kbdev: Kbase device + */ +static void kbase_pm_wait_for_reset(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.lock); + + wait_event(kbdev->pm.backend.reset_done_wait, + (kbdev->pm.backend.reset_done)); + kbdev->pm.backend.reset_done = false; +} + +KBASE_EXPORT_TEST_API(kbase_pm_reset_done); + +static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer) +{ + struct kbasep_reset_timeout_data *rtdata = + container_of(timer, struct kbasep_reset_timeout_data, timer); + + rtdata->timed_out = 1; + + /* Set the wait queue to wake up kbase_pm_init_hw even though the reset + * hasn't completed */ + kbase_pm_reset_done(rtdata->kbdev); + + return HRTIMER_NORESTART; +} + +static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev) +{ + struct device_node *np = kbdev->dev->of_node; + u32 jm_values[4]; + const u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> + GPU_ID_VERSION_PRODUCT_ID_SHIFT; + const u32 major = (gpu_id & GPU_ID_VERSION_MAJOR) >> + GPU_ID_VERSION_MAJOR_SHIFT; + + kbdev->hw_quirks_sc = 0; + + /* Needed due to MIDBASE-1494: LS_PAUSEBUFFER_DISABLE. See PRLAM-8443. + * and needed due to MIDGLES-3539. See PRLAM-11035 */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8443) || + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_11035)) + kbdev->hw_quirks_sc |= SC_LS_PAUSEBUFFER_DISABLE; + + /* Needed due to MIDBASE-2054: SDC_DISABLE_OQ_DISCARD. See PRLAM-10327. + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10327)) + kbdev->hw_quirks_sc |= SC_SDC_DISABLE_OQ_DISCARD; + +#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY + /* Enable alternative hardware counter selection if configured. */ + if (!GPU_ID_IS_NEW_FORMAT(prod_id)) + kbdev->hw_quirks_sc |= SC_ALT_COUNTERS; +#endif + + /* Needed due to MIDBASE-2795. ENABLE_TEXGRD_FLAGS. See PRLAM-10797. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10797)) + kbdev->hw_quirks_sc |= SC_ENABLE_TEXGRD_FLAGS; + + if (!kbase_hw_has_issue(kbdev, GPUCORE_1619)) { + if (prod_id < 0x750 || prod_id == 0x6956) /* T60x, T62x, T72x */ + kbdev->hw_quirks_sc |= SC_LS_ATTR_CHECK_DISABLE; + else if (prod_id >= 0x750 && prod_id <= 0x880) /* T76x, T8xx */ + kbdev->hw_quirks_sc |= SC_LS_ALLOW_ATTR_TYPES; + } + + if (!kbdev->hw_quirks_sc) + kbdev->hw_quirks_sc = kbase_reg_read(kbdev, + GPU_CONTROL_REG(SHADER_CONFIG), NULL); + + kbdev->hw_quirks_tiler = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TILER_CONFIG), NULL); + + /* Set tiler clock gate override if required */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3953)) + kbdev->hw_quirks_tiler |= TC_CLOCK_GATE_OVERRIDE; + + /* Limit the GPU bus bandwidth if the platform needs this. */ + kbdev->hw_quirks_mmu = kbase_reg_read(kbdev, + GPU_CONTROL_REG(L2_MMU_CONFIG), NULL); + + /* Limit read ID width for AXI */ + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS); + kbdev->hw_quirks_mmu |= (DEFAULT_ARID_LIMIT & 0x3) << + L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT; + + /* Limit write ID width for AXI */ + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); + kbdev->hw_quirks_mmu |= (DEFAULT_AWID_LIMIT & 0x3) << + L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT; + + if (kbdev->system_coherency == COHERENCY_ACE) { + /* Allow memory configuration disparity to be ignored, we + * optimize the use of shared memory and thus we expect + * some disparity in the memory configuration */ + kbdev->hw_quirks_mmu |= L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY; + } + + kbdev->hw_quirks_jm = 0; + /* Only for T86x/T88x-based products after r2p0 */ + if (prod_id >= 0x860 && prod_id <= 0x880 && major >= 2) { + + if (of_property_read_u32_array(np, + "jm_config", + &jm_values[0], + ARRAY_SIZE(jm_values))) { + /* Entry not in device tree, use defaults */ + jm_values[0] = 0; + jm_values[1] = 0; + jm_values[2] = 0; + jm_values[3] = JM_MAX_JOB_THROTTLE_LIMIT; + } + + /* Limit throttle limit to 6 bits*/ + if (jm_values[3] > JM_MAX_JOB_THROTTLE_LIMIT) { + dev_dbg(kbdev->dev, "JOB_THROTTLE_LIMIT supplied in device tree is too large. Limiting to MAX (63)."); + jm_values[3] = JM_MAX_JOB_THROTTLE_LIMIT; + } + + /* Aggregate to one integer. */ + kbdev->hw_quirks_jm |= (jm_values[0] ? + JM_TIMESTAMP_OVERRIDE : 0); + kbdev->hw_quirks_jm |= (jm_values[1] ? + JM_CLOCK_GATE_OVERRIDE : 0); + kbdev->hw_quirks_jm |= (jm_values[2] ? + JM_JOB_THROTTLE_ENABLE : 0); + kbdev->hw_quirks_jm |= (jm_values[3] << + JM_JOB_THROTTLE_LIMIT_SHIFT); + + } else if (GPU_ID_IS_NEW_FORMAT(prod_id) && + (GPU_ID2_MODEL_MATCH_VALUE(prod_id) == + GPU_ID2_PRODUCT_TMIX)) { + /* Only for tMIx */ + u32 coherency_features; + + coherency_features = kbase_reg_read(kbdev, + GPU_CONTROL_REG(COHERENCY_FEATURES), NULL); + + /* (COHERENCY_ACE_LITE | COHERENCY_ACE) was incorrectly + * documented for tMIx so force correct value here. + */ + if (coherency_features == + COHERENCY_FEATURE_BIT(COHERENCY_ACE)) { + kbdev->hw_quirks_jm |= + (COHERENCY_ACE_LITE | COHERENCY_ACE) << + JM_FORCE_COHERENCY_FEATURES_SHIFT; + } + } + + + if (!kbdev->hw_quirks_jm) + kbdev->hw_quirks_jm = kbase_reg_read(kbdev, + GPU_CONTROL_REG(JM_CONFIG), NULL); + +#ifdef CONFIG_MALI_CORESTACK +#define MANUAL_POWER_CONTROL ((u32)(1 << 8)) + kbdev->hw_quirks_jm |= MANUAL_POWER_CONTROL; +#endif /* CONFIG_MALI_CORESTACK */ +} + +static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev) +{ + kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), + kbdev->hw_quirks_sc, NULL); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(TILER_CONFIG), + kbdev->hw_quirks_tiler, NULL); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), + kbdev->hw_quirks_mmu, NULL); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(JM_CONFIG), + kbdev->hw_quirks_jm, NULL); + +} + +void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev) +{ + if ((kbdev->current_gpu_coherency_mode == COHERENCY_ACE) && + !kbdev->cci_snoop_enabled) { +#ifdef CONFIG_ARM64 + if (kbdev->snoop_enable_smc != 0) + kbase_invoke_smc_fid(kbdev->snoop_enable_smc, 0, 0, 0); +#endif /* CONFIG_ARM64 */ + dev_dbg(kbdev->dev, "MALI - CCI Snoops - Enabled\n"); + kbdev->cci_snoop_enabled = true; + } +} + +void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev) +{ + if (kbdev->cci_snoop_enabled) { +#ifdef CONFIG_ARM64 + if (kbdev->snoop_disable_smc != 0) { + mali_cci_flush_l2(kbdev); + kbase_invoke_smc_fid(kbdev->snoop_disable_smc, 0, 0, 0); + } +#endif /* CONFIG_ARM64 */ + dev_dbg(kbdev->dev, "MALI - CCI Snoops Disabled\n"); + kbdev->cci_snoop_enabled = false; + } +} + +static int kbase_pm_do_reset(struct kbase_device *kbdev) +{ + struct kbasep_reset_timeout_data rtdata; + + KBASE_TRACE_ADD(kbdev, CORE_GPU_SOFT_RESET, NULL, NULL, 0u, 0); + + KBASE_TLSTREAM_JD_GPU_SOFT_RESET(kbdev); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_SOFT_RESET, NULL); + + /* Unmask the reset complete interrupt only */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), RESET_COMPLETED, + NULL); + + /* Initialize a structure for tracking the status of the reset */ + rtdata.kbdev = kbdev; + rtdata.timed_out = 0; + + /* Create a timer to use as a timeout on the reset */ + hrtimer_init_on_stack(&rtdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rtdata.timer.function = kbasep_reset_timeout; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), + HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + return 0; + } + + /* No interrupt has been received - check if the RAWSTAT register says + * the reset has completed */ + if (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & + RESET_COMPLETED) { + /* The interrupt is set in the RAWSTAT; this suggests that the + * interrupts are not getting to the CPU */ + dev_err(kbdev->dev, "Reset interrupt didn't reach CPU. Check interrupt assignments.\n"); + /* If interrupts aren't working we can't continue. */ + destroy_hrtimer_on_stack(&rtdata.timer); + return -EINVAL; + } + + /* The GPU doesn't seem to be responding to the reset so try a hard + * reset */ + dev_err(kbdev->dev, "Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n", + RESET_TIMEOUT); + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_HARD_RESET, NULL); + + /* Restart the timer to wait for the hard reset to complete */ + rtdata.timed_out = 0; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), + HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + return 0; + } + + destroy_hrtimer_on_stack(&rtdata.timer); + + dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n", + RESET_TIMEOUT); + + return -EINVAL; +} + +static int kbasep_protected_mode_enable(struct protected_mode_device *pdev) +{ + struct kbase_device *kbdev = pdev->data; + + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_SET_PROTECTED_MODE, NULL); + return 0; +} + +static int kbasep_protected_mode_disable(struct protected_mode_device *pdev) +{ + struct kbase_device *kbdev = pdev->data; + + lockdep_assert_held(&kbdev->pm.lock); + + return kbase_pm_do_reset(kbdev); +} + +struct protected_mode_ops kbase_native_protected_ops = { + .protected_mode_enable = kbasep_protected_mode_enable, + .protected_mode_disable = kbasep_protected_mode_disable +}; + +int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) +{ + unsigned long irq_flags; + int err; + bool resume_vinstr = false; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* Ensure the clock is on before attempting to access the hardware */ + if (!kbdev->pm.backend.gpu_powered) { + if (kbdev->pm.backend.callback_power_on) + kbdev->pm.backend.callback_power_on(kbdev); + + spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, + irq_flags); + kbdev->pm.backend.gpu_powered = true; + spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, + irq_flags); + } + + /* Ensure interrupts are off to begin with, this also clears any + * outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + /* Ensure cache snoops are disabled before reset. */ + kbase_pm_cache_snoop_disable(kbdev); + /* Prepare for the soft-reset */ + kbdev->pm.backend.reset_done = false; + + /* The cores should be made unavailable due to the reset */ + spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); + if (kbdev->shader_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, + NULL, 0u, (u32)0u); + if (kbdev->tiler_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, + NULL, NULL, 0u, (u32)0u); + kbdev->shader_available_bitmap = 0u; + kbdev->tiler_available_bitmap = 0u; + kbdev->l2_available_bitmap = 0u; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); + + /* Soft reset the GPU */ + if (kbdev->protected_mode_support) + err = kbdev->protected_ops->protected_mode_disable( + kbdev->protected_dev); + else + err = kbase_pm_do_reset(kbdev); + + spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); + if (kbdev->protected_mode) + resume_vinstr = true; + kbdev->protected_mode = false; + kbase_ipa_model_use_configured_locked(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); + + if (err) + goto exit; + + if (flags & PM_HW_ISSUES_DETECT) + kbase_pm_hw_issues_detect(kbdev); + + kbase_pm_hw_issues_apply(kbdev); + kbase_cache_set_coherency_mode(kbdev, kbdev->system_coherency); + + /* Sanity check protected mode was left after reset */ + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE)) { + u32 gpu_status = kbase_reg_read(kbdev, + GPU_CONTROL_REG(GPU_STATUS), NULL); + + WARN_ON(gpu_status & GPU_STATUS_PROTECTED_MODE_ACTIVE); + } + + /* If cycle counter was in use re-enable it, enable_irqs will only be + * false when called from kbase_pm_powerup */ + if (kbdev->pm.backend.gpu_cycle_counter_requests && + (flags & PM_ENABLE_IRQS)) { + /* enable interrupts as the L2 may have to be powered on */ + kbase_pm_enable_interrupts(kbdev); + kbase_pm_request_l2_caches(kbdev); + + /* Re-enable the counters if we need to */ + spin_lock_irqsave( + &kbdev->pm.backend.gpu_cycle_counter_requests_lock, + irq_flags); + if (kbdev->pm.backend.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CYCLE_COUNT_START, NULL); + spin_unlock_irqrestore( + &kbdev->pm.backend.gpu_cycle_counter_requests_lock, + irq_flags); + + spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); + kbase_pm_release_l2_caches(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); + + kbase_pm_disable_interrupts(kbdev); + } + + if (flags & PM_ENABLE_IRQS) + kbase_pm_enable_interrupts(kbdev); + +exit: + /* If GPU is leaving protected mode resume vinstr operation. */ + if (kbdev->vinstr_ctx && resume_vinstr) + kbase_vinstr_resume(kbdev->vinstr_ctx); + + return err; +} + +/** + * kbase_pm_request_gpu_cycle_counter_do_request - Request cycle counters + * + * Increase the count of cycle counter users and turn the cycle counters on if + * they were previously off + * + * This function is designed to be called by + * kbase_pm_request_gpu_cycle_counter() or + * kbase_pm_request_gpu_cycle_counter_l2_is_on() only + * + * When this function is called the l2 cache must be on and the l2 cache users + * count must have been incremented by a call to ( + * kbase_pm_request_l2_caches() or kbase_pm_request_l2_caches_l2_on() ) + * + * @kbdev: The kbase device structure of the device + */ +static void +kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock, + flags); + + ++kbdev->pm.backend.gpu_cycle_counter_requests; + + if (1 == kbdev->pm.backend.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CYCLE_COUNT_START, NULL); + + spin_unlock_irqrestore( + &kbdev->pm.backend.gpu_cycle_counter_requests_lock, + flags); +} + +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_cycle_counter_requests < + INT_MAX); + + kbase_pm_request_l2_caches(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter); + +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_cycle_counter_requests < + INT_MAX); + + kbase_pm_request_l2_caches_l2_is_on(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter_l2_is_on); + +void kbase_pm_release_gpu_cycle_counter_nolock(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock, + flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_cycle_counter_requests > 0); + + --kbdev->pm.backend.gpu_cycle_counter_requests; + + if (0 == kbdev->pm.backend.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), + GPU_COMMAND_CYCLE_COUNT_STOP, NULL); + + spin_unlock_irqrestore( + &kbdev->pm.backend.gpu_cycle_counter_requests_lock, + flags); + + kbase_pm_release_l2_caches(kbdev); +} + +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbase_pm_release_gpu_cycle_counter_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_gpu_cycle_counter); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h new file mode 100644 index 000000000000..6804f45ac27b --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h @@ -0,0 +1,548 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Power management API definitions used internally by GPU backend + */ + +#ifndef _KBASE_BACKEND_PM_INTERNAL_H_ +#define _KBASE_BACKEND_PM_INTERNAL_H_ + +#include + +#include "mali_kbase_pm_ca.h" +#include "mali_kbase_pm_policy.h" + + +/** + * kbase_pm_dev_idle - The GPU is idle. + * + * The OS may choose to turn off idle devices + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_idle(struct kbase_device *kbdev); + +/** + * kbase_pm_dev_activate - The GPU is active. + * + * The OS should avoid opportunistically turning off the GPU while it is active + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_activate(struct kbase_device *kbdev); + +/** + * kbase_pm_get_present_cores - Get details of the cores that are present in + * the device. + * + * This function can be called by the active power policy to return a bitmask of + * the cores (of a specified type) present in the GPU device and also a count of + * the number of cores. + * + * @kbdev: The kbase device structure for the device (must be a valid + * pointer) + * @type: The type of core (see the enum kbase_pm_core_type enumeration) + * + * Return: The bit mask of cores present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type); + +/** + * kbase_pm_get_active_cores - Get details of the cores that are currently + * active in the device. + * + * This function can be called by the active power policy to return a bitmask of + * the cores (of a specified type) that are actively processing work (i.e. + * turned on *and* busy). + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @type: The type of core (see the enum kbase_pm_core_type enumeration) + * + * Return: The bit mask of active cores + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type); + +/** + * kbase_pm_get_trans_cores - Get details of the cores that are currently + * transitioning between power states. + * + * This function can be called by the active power policy to return a bitmask of + * the cores (of a specified type) that are currently transitioning between + * power states. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @type: The type of core (see the enum kbase_pm_core_type enumeration) + * + * Return: The bit mask of transitioning cores + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type); + +/** + * kbase_pm_get_ready_cores - Get details of the cores that are currently + * powered and ready for jobs. + * + * This function can be called by the active power policy to return a bitmask of + * the cores (of a specified type) that are powered and ready for jobs (they may + * or may not be currently executing jobs). + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @type: The type of core (see the enum kbase_pm_core_type enumeration) + * + * Return: The bit mask of ready cores + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, + enum kbase_pm_core_type type); + +/** + * kbase_pm_clock_on - Turn the clock for the device on, and enable device + * interrupts. + * + * This function can be used by a power policy to turn the clock for the GPU on. + * It should be modified during integration to perform the necessary actions to + * ensure that the GPU is fully powered and clocked. + * + * @kbdev: The kbase device structure for the device (must be a valid + * pointer) + * @is_resume: true if clock on due to resume after suspend, false otherwise + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume); + +/** + * kbase_pm_clock_off - Disable device interrupts, and turn the clock for the + * device off. + * + * This function can be used by a power policy to turn the clock for the GPU + * off. It should be modified during integration to perform the necessary + * actions to turn the clock off (if this is possible in the integration). + * + * @kbdev: The kbase device structure for the device (must be a valid + * pointer) + * @is_suspend: true if clock off due to suspend, false otherwise + * + * Return: true if clock was turned off, or + * false if clock can not be turned off due to pending page/bus fault + * workers. Caller must flush MMU workqueues and retry + */ +bool kbase_pm_clock_off(struct kbase_device *kbdev, bool is_suspend); + +/** + * kbase_pm_enable_interrupts - Enable interrupts on the device. + * + * Interrupts are also enabled after a call to kbase_pm_clock_on(). + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_enable_interrupts(struct kbase_device *kbdev); + +/** + * kbase_pm_disable_interrupts - Disable interrupts on the device. + * + * This prevents delivery of Power Management interrupts to the CPU so that + * kbase_pm_check_transitions_nolock() will not be called from the IRQ handler + * until kbase_pm_enable_interrupts() or kbase_pm_clock_on() is called. + * + * Interrupts are also disabled after a call to kbase_pm_clock_off(). + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_disable_interrupts(struct kbase_device *kbdev); + +/** + * kbase_pm_disable_interrupts_nolock - Version of kbase_pm_disable_interrupts() + * that does not take the hwaccess_lock + * + * Caller must hold the hwaccess_lock. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_disable_interrupts_nolock(struct kbase_device *kbdev); + +/** + * kbase_pm_init_hw - Initialize the hardware. + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @flags: Flags specifying the type of PM init + * + * This function checks the GPU ID register to ensure that the GPU is supported + * by the driver and performs a reset on the device so that it is in a known + * state before the device is used. + * + * Return: 0 if the device is supported and successfully reset. + */ +int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags); + +/** + * kbase_pm_reset_done - The GPU has been reset successfully. + * + * This function must be called by the GPU interrupt handler when the + * RESET_COMPLETED bit is set. It signals to the power management initialization + * code that the GPU has been successfully reset. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_reset_done(struct kbase_device *kbdev); + + +/** + * kbase_pm_check_transitions_nolock - Check if there are any power transitions + * to make, and if so start them. + * + * This function will check the desired_xx_state members of + * struct kbase_pm_device_data and the actual status of the hardware to see if + * any power transitions can be made at this time to make the hardware state + * closer to the state desired by the power policy. + * + * The return value can be used to check whether all the desired cores are + * available, and so whether it's worth submitting a job (e.g. from a Power + * Management IRQ). + * + * Note that this still returns true when desired_xx_state has no + * cores. That is: of the no cores desired, none were *un*available. In + * this case, the caller may still need to try submitting jobs. This is because + * the Core Availability Policy might have taken us to an intermediate state + * where no cores are powered, before powering on more cores (e.g. for core + * rotation) + * + * The caller must hold kbase_device.pm.power_change_lock + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Return: non-zero when all desired cores are available. That is, + * it's worthwhile for the caller to submit a job. + * false otherwise + */ +bool kbase_pm_check_transitions_nolock(struct kbase_device *kbdev); + +/** + * kbase_pm_check_transitions_sync - Synchronous and locking variant of + * kbase_pm_check_transitions_nolock() + * + * On returning, the desired state at the time of the call will have been met. + * + * There is nothing to stop the core being switched off by calls to + * kbase_pm_release_cores() or kbase_pm_unrequest_cores(). Therefore, the + * caller must have already made a call to + * kbase_pm_request_cores()/kbase_pm_request_cores_sync() previously. + * + * The usual use-case for this is to ensure cores are 'READY' after performing + * a GPU Reset. + * + * Unlike kbase_pm_check_transitions_nolock(), the caller must not hold + * kbase_device.pm.power_change_lock, because this function will take that + * lock itself. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev); + +/** + * kbase_pm_update_cores_state_nolock - Variant of kbase_pm_update_cores_state() + * where the caller must hold + * kbase_device.pm.power_change_lock + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev); + +/** + * kbase_pm_update_cores_state - Update the desired state of shader cores from + * the Power Policy, and begin any power + * transitions. + * + * This function will update the desired_xx_state members of + * struct kbase_pm_device_data by calling into the current Power Policy. It will + * then begin power transitions to make the hardware acheive the desired shader + * core state. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_cores_state(struct kbase_device *kbdev); + +/** + * kbase_pm_cancel_deferred_poweroff - Cancel any pending requests to power off + * the GPU and/or shader cores. + * + * This should be called by any functions which directly power off the GPU. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev); + +/** + * kbasep_pm_init_core_use_bitmaps - Initialise data tracking the required + * and used cores. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_init_core_use_bitmaps(struct kbase_device *kbdev); + +/** + * kbasep_pm_metrics_init - Initialize the metrics gathering framework. + * + * This must be called before other metric gathering APIs are called. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Return: 0 on success, error code on error + */ +int kbasep_pm_metrics_init(struct kbase_device *kbdev); + +/** + * kbasep_pm_metrics_term - Terminate the metrics gathering framework. + * + * This must be called when metric gathering is no longer required. It is an + * error to call any metrics gathering function (other than + * kbasep_pm_metrics_init()) after calling this function. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_metrics_term(struct kbase_device *kbdev); + +/** + * kbase_pm_report_vsync - Function to be called by the frame buffer driver to + * update the vsync metric. + * + * This function should be called by the frame buffer driver to update whether + * the system is hitting the vsync target or not. buffer_updated should be true + * if the vsync corresponded with a new frame being displayed, otherwise it + * should be false. This function does not need to be called every vsync, but + * only when the value of @buffer_updated differs from a previous call. + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + * @buffer_updated: True if the buffer has been updated on this VSync, + * false otherwise + */ +void kbase_pm_report_vsync(struct kbase_device *kbdev, int buffer_updated); + +/** + * kbase_pm_get_dvfs_action - Determine whether the DVFS system should change + * the clock speed of the GPU. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This function should be called regularly by the DVFS system to check whether + * the clock speed of the GPU needs updating. + */ +void kbase_pm_get_dvfs_action(struct kbase_device *kbdev); + +/** + * kbase_pm_request_gpu_cycle_counter - Mark that the GPU cycle counter is + * needed + * + * If the caller is the first caller then the GPU cycle counters will be enabled + * along with the l2 cache + * + * The GPU must be powered when calling this function (i.e. + * kbase_pm_context_active() must have been called). + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev); + +/** + * kbase_pm_request_gpu_cycle_counter_l2_is_on - Mark GPU cycle counter is + * needed (l2 cache already on) + * + * This is a version of the above function + * (kbase_pm_request_gpu_cycle_counter()) suitable for being called when the + * l2 cache is known to be on and assured to be on until the subsequent call of + * kbase_pm_release_gpu_cycle_counter() such as when a job is submitted. It does + * not sleep and can be called from atomic functions. + * + * The GPU must be powered when calling this function (i.e. + * kbase_pm_context_active() must have been called) and the l2 cache must be + * powered on. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev); + +/** + * kbase_pm_release_gpu_cycle_counter - Mark that the GPU cycle counter is no + * longer in use + * + * If the caller is the last caller then the GPU cycle counters will be + * disabled. A request must have been made before a call to this. + * + * Caller must not hold the hwaccess_lock, as it will be taken in this function. + * If the caller is already holding this lock then + * kbase_pm_release_gpu_cycle_counter_nolock() must be used instead. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev); + +/** + * kbase_pm_release_gpu_cycle_counter_nolock - Version of kbase_pm_release_gpu_cycle_counter() + * that does not take hwaccess_lock + * + * Caller must hold the hwaccess_lock. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_release_gpu_cycle_counter_nolock(struct kbase_device *kbdev); + +/** + * kbase_pm_wait_for_poweroff_complete - Wait for the poweroff workqueue to + * complete + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_wait_for_poweroff_complete(struct kbase_device *kbdev); + +/** + * kbase_pm_register_access_enable - Enable access to GPU registers + * + * Enables access to the GPU registers before power management has powered up + * the GPU with kbase_pm_powerup(). + * + * Access to registers should be done using kbase_os_reg_read()/write() at this + * stage, not kbase_reg_read()/write(). + * + * This results in the power management callbacks provided in the driver + * configuration to get called to turn on power and/or clocks to the GPU. See + * kbase_pm_callback_conf. + * + * This should only be used before power management is powered up with + * kbase_pm_powerup() + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_enable(struct kbase_device *kbdev); + +/** + * kbase_pm_register_access_disable - Disable early register access + * + * Disables access to the GPU registers enabled earlier by a call to + * kbase_pm_register_access_enable(). + * + * This results in the power management callbacks provided in the driver + * configuration to get called to turn off power and/or clocks to the GPU. See + * kbase_pm_callback_conf + * + * This should only be used before power management is powered up with + * kbase_pm_powerup() + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_disable(struct kbase_device *kbdev); + +/* NOTE: kbase_pm_is_suspending is in mali_kbase.h, because it is an inline + * function */ + +/** + * kbase_pm_metrics_is_active - Check if the power management metrics + * collection is active. + * + * Note that this returns if the power management metrics collection was + * active at the time of calling, it is possible that after the call the metrics + * collection enable may have changed state. + * + * The caller must handle the consequence that the state may have changed. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * Return: true if metrics collection was active else false. + */ +bool kbase_pm_metrics_is_active(struct kbase_device *kbdev); + +/** + * kbase_pm_do_poweron - Power on the GPU, and any cores that are requested. + * + * @kbdev: The kbase device structure for the device (must be a valid + * pointer) + * @is_resume: true if power on due to resume after suspend, + * false otherwise + */ +void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume); + +/** + * kbase_pm_do_poweroff - Power off the GPU, and any cores that have been + * requested. + * + * @kbdev: The kbase device structure for the device (must be a valid + * pointer) + * @is_suspend: true if power off due to suspend, + * false otherwise + */ +void kbase_pm_do_poweroff(struct kbase_device *kbdev, bool is_suspend); + +#if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, + unsigned long *total, unsigned long *busy); +void kbase_pm_reset_dvfs_utilisation(struct kbase_device *kbdev); +#endif /* defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) */ + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/** + * kbase_platform_dvfs_event - Report utilisation to DVFS code + * + * Function provided by platform specific code when DVFS is enabled to allow + * the power management metrics system to report utilisation. + * + * @kbdev: The kbase device structure for the device (must be a + * valid pointer) + * @utilisation: The current calculated utilisation by the metrics system. + * @util_gl_share: The current calculated gl share of utilisation. + * @util_cl_share: The current calculated cl share of utilisation per core + * group. + * Return: Returns 0 on failure and non zero on success. + */ + +int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, + u32 util_gl_share, u32 util_cl_share[2]); +#endif + +void kbase_pm_power_changed(struct kbase_device *kbdev); + +/** + * kbase_pm_metrics_update - Inform the metrics system that an atom is either + * about to be run or has just completed. + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @now: Pointer to the timestamp of the change, or NULL to use current time + * + * Caller must hold hwaccess_lock + */ +void kbase_pm_metrics_update(struct kbase_device *kbdev, + ktime_t *now); + +/** + * kbase_pm_cache_snoop_enable - Allow CPU snoops on the GPU + * If the GPU does not have coherency this is a no-op + * @kbdev: Device pointer + * + * This function should be called after L2 power up. + */ + +void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev); + +/** + * kbase_pm_cache_snoop_disable - Prevent CPU snoops on the GPU + * If the GPU does not have coherency this is a no-op + * @kbdev: Device pointer + * + * This function should be called before L2 power off. + */ +void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev); + +#endif /* _KBASE_BACKEND_PM_INTERNAL_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c new file mode 100644 index 000000000000..024248ca7123 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c @@ -0,0 +1,401 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Metrics for power management + */ + +#include +#include +#include +#include + +/* When VSync is being hit aim for utilisation between 70-90% */ +#define KBASE_PM_VSYNC_MIN_UTILISATION 70 +#define KBASE_PM_VSYNC_MAX_UTILISATION 90 +/* Otherwise aim for 10-40% */ +#define KBASE_PM_NO_VSYNC_MIN_UTILISATION 10 +#define KBASE_PM_NO_VSYNC_MAX_UTILISATION 40 + +/* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns + * This gives a maximum period between samples of 2^(32+8)/100 ns = slightly + * under 11s. Exceeding this will cause overflow */ +#define KBASE_PM_TIME_SHIFT 8 + +/* Maximum time between sampling of utilization data, without resetting the + * counters. */ +#define MALI_UTILIZATION_MAX_PERIOD 100000 /* ns = 100ms */ + +#ifdef CONFIG_MALI_MIDGARD_DVFS +static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) +{ + unsigned long flags; + struct kbasep_pm_metrics_data *metrics; + + KBASE_DEBUG_ASSERT(timer != NULL); + + metrics = container_of(timer, struct kbasep_pm_metrics_data, timer); + kbase_pm_get_dvfs_action(metrics->kbdev); + + spin_lock_irqsave(&metrics->lock, flags); + + if (metrics->timer_active) + hrtimer_start(timer, + HR_TIMER_DELAY_MSEC(metrics->kbdev->pm.dvfs_period), + HRTIMER_MODE_REL); + + spin_unlock_irqrestore(&metrics->lock, flags); + + return HRTIMER_NORESTART; +} +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +int kbasep_pm_metrics_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.backend.metrics.kbdev = kbdev; + + kbdev->pm.backend.metrics.time_period_start = ktime_get(); + kbdev->pm.backend.metrics.time_busy = 0; + kbdev->pm.backend.metrics.time_idle = 0; + kbdev->pm.backend.metrics.prev_busy = 0; + kbdev->pm.backend.metrics.prev_idle = 0; + kbdev->pm.backend.metrics.gpu_active = false; + kbdev->pm.backend.metrics.active_cl_ctx[0] = 0; + kbdev->pm.backend.metrics.active_cl_ctx[1] = 0; + kbdev->pm.backend.metrics.active_gl_ctx[0] = 0; + kbdev->pm.backend.metrics.active_gl_ctx[1] = 0; + kbdev->pm.backend.metrics.busy_cl[0] = 0; + kbdev->pm.backend.metrics.busy_cl[1] = 0; + kbdev->pm.backend.metrics.busy_gl = 0; + + spin_lock_init(&kbdev->pm.backend.metrics.lock); + +#ifdef CONFIG_MALI_MIDGARD_DVFS + kbdev->pm.backend.metrics.timer_active = true; + hrtimer_init(&kbdev->pm.backend.metrics.timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + kbdev->pm.backend.metrics.timer.function = dvfs_callback; + + hrtimer_start(&kbdev->pm.backend.metrics.timer, + HR_TIMER_DELAY_MSEC(kbdev->pm.dvfs_period), + HRTIMER_MODE_REL); +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + + return 0; +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init); + +void kbasep_pm_metrics_term(struct kbase_device *kbdev) +{ +#ifdef CONFIG_MALI_MIDGARD_DVFS + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + kbdev->pm.backend.metrics.timer_active = false; + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); + + hrtimer_cancel(&kbdev->pm.backend.metrics.timer); +#endif /* CONFIG_MALI_MIDGARD_DVFS */ +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term); + +/* caller needs to hold kbdev->pm.backend.metrics.lock before calling this + * function + */ +static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev, + ktime_t now) +{ + ktime_t diff; + + lockdep_assert_held(&kbdev->pm.backend.metrics.lock); + + diff = ktime_sub(now, kbdev->pm.backend.metrics.time_period_start); + if (ktime_to_ns(diff) < 0) + return; + + if (kbdev->pm.backend.metrics.gpu_active) { + u32 ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + + kbdev->pm.backend.metrics.time_busy += ns_time; + if (kbdev->pm.backend.metrics.active_cl_ctx[0]) + kbdev->pm.backend.metrics.busy_cl[0] += ns_time; + if (kbdev->pm.backend.metrics.active_cl_ctx[1]) + kbdev->pm.backend.metrics.busy_cl[1] += ns_time; + if (kbdev->pm.backend.metrics.active_gl_ctx[0]) + kbdev->pm.backend.metrics.busy_gl += ns_time; + if (kbdev->pm.backend.metrics.active_gl_ctx[1]) + kbdev->pm.backend.metrics.busy_gl += ns_time; + } else { + kbdev->pm.backend.metrics.time_idle += (u32) (ktime_to_ns(diff) + >> KBASE_PM_TIME_SHIFT); + } + + kbdev->pm.backend.metrics.time_period_start = now; +} + +#if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) +/* Caller needs to hold kbdev->pm.backend.metrics.lock before calling this + * function. + */ +static void kbase_pm_reset_dvfs_utilisation_unlocked(struct kbase_device *kbdev, + ktime_t now) +{ + /* Store previous value */ + kbdev->pm.backend.metrics.prev_idle = + kbdev->pm.backend.metrics.time_idle; + kbdev->pm.backend.metrics.prev_busy = + kbdev->pm.backend.metrics.time_busy; + + /* Reset current values */ + kbdev->pm.backend.metrics.time_period_start = now; + kbdev->pm.backend.metrics.time_idle = 0; + kbdev->pm.backend.metrics.time_busy = 0; + kbdev->pm.backend.metrics.busy_cl[0] = 0; + kbdev->pm.backend.metrics.busy_cl[1] = 0; + kbdev->pm.backend.metrics.busy_gl = 0; +} + +void kbase_pm_reset_dvfs_utilisation(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, ktime_get()); + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); +} + +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, + unsigned long *total_out, unsigned long *busy_out) +{ + ktime_t now = ktime_get(); + unsigned long flags, busy, total; + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + busy = kbdev->pm.backend.metrics.time_busy; + total = busy + kbdev->pm.backend.metrics.time_idle; + + /* Reset stats if older than MALI_UTILIZATION_MAX_PERIOD (default + * 100ms) */ + if (total >= MALI_UTILIZATION_MAX_PERIOD) { + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, now); + } else if (total < (MALI_UTILIZATION_MAX_PERIOD / 2)) { + total += kbdev->pm.backend.metrics.prev_idle + + kbdev->pm.backend.metrics.prev_busy; + busy += kbdev->pm.backend.metrics.prev_busy; + } + + *total_out = total; + *busy_out = busy; + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); +} +#endif + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/* caller needs to hold kbdev->pm.backend.metrics.lock before calling this + * function + */ +int kbase_pm_get_dvfs_utilisation_old(struct kbase_device *kbdev, + int *util_gl_share, + int util_cl_share[2], + ktime_t now) +{ + int utilisation; + int busy; + + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + if (kbdev->pm.backend.metrics.time_idle + + kbdev->pm.backend.metrics.time_busy == 0) { + /* No data - so we return NOP */ + utilisation = -1; + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + goto out; + } + + utilisation = (100 * kbdev->pm.backend.metrics.time_busy) / + (kbdev->pm.backend.metrics.time_idle + + kbdev->pm.backend.metrics.time_busy); + + busy = kbdev->pm.backend.metrics.busy_gl + + kbdev->pm.backend.metrics.busy_cl[0] + + kbdev->pm.backend.metrics.busy_cl[1]; + + if (busy != 0) { + if (util_gl_share) + *util_gl_share = + (100 * kbdev->pm.backend.metrics.busy_gl) / + busy; + if (util_cl_share) { + util_cl_share[0] = + (100 * kbdev->pm.backend.metrics.busy_cl[0]) / + busy; + util_cl_share[1] = + (100 * kbdev->pm.backend.metrics.busy_cl[1]) / + busy; + } + } else { + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + } + +out: + return utilisation; +} + +void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) +{ + unsigned long flags; + int utilisation, util_gl_share; + int util_cl_share[2]; + ktime_t now; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + + now = ktime_get(); + + utilisation = kbase_pm_get_dvfs_utilisation_old(kbdev, &util_gl_share, + util_cl_share, now); + + if (utilisation < 0 || util_gl_share < 0 || util_cl_share[0] < 0 || + util_cl_share[1] < 0) { + utilisation = 0; + util_gl_share = 0; + util_cl_share[0] = 0; + util_cl_share[1] = 0; + goto out; + } + +out: +#ifdef CONFIG_MALI_MIDGARD_DVFS + kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, + util_cl_share); +#endif /*CONFIG_MALI_MIDGARD_DVFS */ + + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, now); + + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); +} + +bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) +{ + bool isactive; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + isactive = kbdev->pm.backend.metrics.timer_active; + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); + + return isactive; +} +KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active); + +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +/** + * kbase_pm_metrics_active_calc - Update PM active counts based on currently + * running atoms + * @kbdev: Device pointer + * + * The caller must hold kbdev->pm.backend.metrics.lock + */ +static void kbase_pm_metrics_active_calc(struct kbase_device *kbdev) +{ + int js; + + lockdep_assert_held(&kbdev->pm.backend.metrics.lock); + + kbdev->pm.backend.metrics.active_gl_ctx[0] = 0; + kbdev->pm.backend.metrics.active_gl_ctx[1] = 0; + kbdev->pm.backend.metrics.active_cl_ctx[0] = 0; + kbdev->pm.backend.metrics.active_cl_ctx[1] = 0; + kbdev->pm.backend.metrics.gpu_active = false; + + for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { + struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, 0); + + /* Head atom may have just completed, so if it isn't running + * then try the next atom */ + if (katom && katom->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) + katom = kbase_gpu_inspect(kbdev, js, 1); + + if (katom && katom->gpu_rb_state == + KBASE_ATOM_GPU_RB_SUBMITTED) { + if (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { + int device_nr = (katom->core_req & + BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) + ? katom->device_nr : 0; + if (!WARN_ON(device_nr >= 2)) + kbdev->pm.backend.metrics. + active_cl_ctx[device_nr] = 1; + } else { + /* Slot 2 should not be running non-compute + * atoms */ + if (!WARN_ON(js >= 2)) + kbdev->pm.backend.metrics. + active_gl_ctx[js] = 1; + } + kbdev->pm.backend.metrics.gpu_active = true; + } + } +} + +/* called when job is submitted to or removed from a GPU slot */ +void kbase_pm_metrics_update(struct kbase_device *kbdev, ktime_t *timestamp) +{ + unsigned long flags; + ktime_t now; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); + + if (!timestamp) { + now = ktime_get(); + timestamp = &now; + } + + /* Track how long CL and/or GL jobs have been busy for */ + kbase_pm_get_dvfs_utilisation_calc(kbdev, *timestamp); + + kbase_pm_metrics_active_calc(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c new file mode 100644 index 000000000000..075f020c66e6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c @@ -0,0 +1,973 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Power policy API implementations + */ + +#include +#include +#include +#include +#include + +static const struct kbase_pm_policy *const policy_list[] = { +#ifdef CONFIG_MALI_NO_MALI + &kbase_pm_always_on_policy_ops, + &kbase_pm_demand_policy_ops, + &kbase_pm_coarse_demand_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif +#else /* CONFIG_MALI_NO_MALI */ +#if !PLATFORM_POWER_DOWN_ONLY + &kbase_pm_demand_policy_ops, +#endif /* !PLATFORM_POWER_DOWN_ONLY */ + &kbase_pm_coarse_demand_policy_ops, + &kbase_pm_always_on_policy_ops, +#if !MALI_CUSTOMER_RELEASE +#if !PLATFORM_POWER_DOWN_ONLY + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif /* !PLATFORM_POWER_DOWN_ONLY */ +#endif +#endif /* CONFIG_MALI_NO_MALI */ +}; + +/* The number of policies available in the system. + * This is derived from the number of functions listed in policy_get_functions. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + + +/* Function IDs for looking up Timeline Trace codes in + * kbase_pm_change_state_trace_code */ +enum kbase_pm_func_id { + KBASE_PM_FUNC_ID_REQUEST_CORES_START, + KBASE_PM_FUNC_ID_REQUEST_CORES_END, + KBASE_PM_FUNC_ID_RELEASE_CORES_START, + KBASE_PM_FUNC_ID_RELEASE_CORES_END, + /* Note: kbase_pm_unrequest_cores() is on the slow path, and we neither + * expect to hit it nor tend to hit it very much anyway. We can detect + * whether we need more instrumentation by a difference between + * PM_CHECKTRANS events and PM_SEND/HANDLE_EVENT. */ + + /* Must be the last */ + KBASE_PM_FUNC_ID_COUNT +}; + + +/* State changes during request/unrequest/release-ing cores */ +enum { + KBASE_PM_CHANGE_STATE_SHADER = (1u << 0), + KBASE_PM_CHANGE_STATE_TILER = (1u << 1), + + /* These two must be last */ + KBASE_PM_CHANGE_STATE_MASK = (KBASE_PM_CHANGE_STATE_TILER | + KBASE_PM_CHANGE_STATE_SHADER), + KBASE_PM_CHANGE_STATE_COUNT = KBASE_PM_CHANGE_STATE_MASK + 1 +}; +typedef u32 kbase_pm_change_state; + + +#ifdef CONFIG_MALI_TRACE_TIMELINE +/* Timeline Trace code lookups for each function */ +static u32 kbase_pm_change_state_trace_code[KBASE_PM_FUNC_ID_COUNT] + [KBASE_PM_CHANGE_STATE_COUNT] = { + /* kbase_pm_request_cores */ + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER | + KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER | + KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, + + /* kbase_pm_release_cores */ + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER | + KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER | + KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END +}; + +static inline void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, + kbase_pm_change_state state) +{ + int trace_code; + + KBASE_DEBUG_ASSERT(func_id >= 0 && func_id < KBASE_PM_FUNC_ID_COUNT); + KBASE_DEBUG_ASSERT(state != 0 && (state & KBASE_PM_CHANGE_STATE_MASK) == + state); + + trace_code = kbase_pm_change_state_trace_code[func_id][state]; + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code); +} + +#else /* CONFIG_MALI_TRACE_TIMELINE */ +static inline void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, kbase_pm_change_state state) +{ +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +/** + * kbasep_pm_do_poweroff_cores - Process a poweroff request and power down any + * requested shader cores + * @kbdev: Device pointer + */ +static void kbasep_pm_do_poweroff_cores(struct kbase_device *kbdev) +{ + u64 prev_shader_state = kbdev->pm.backend.desired_shader_state; + u64 prev_tiler_state = kbdev->pm.backend.desired_tiler_state; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + kbdev->pm.backend.desired_shader_state &= + ~kbdev->pm.backend.shader_poweroff_pending; + kbdev->pm.backend.desired_tiler_state &= + ~kbdev->pm.backend.tiler_poweroff_pending; + + kbdev->pm.backend.shader_poweroff_pending = 0; + kbdev->pm.backend.tiler_poweroff_pending = 0; + + if (prev_shader_state != kbdev->pm.backend.desired_shader_state || + prev_tiler_state != + kbdev->pm.backend.desired_tiler_state || + kbdev->pm.backend.ca_in_transition) { + bool cores_are_available; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END); + + /* Don't need 'cores_are_available', + * because we don't return anything */ + CSTD_UNUSED(cores_are_available); + } +} + +static enum hrtimer_restart +kbasep_pm_do_gpu_poweroff_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev; + unsigned long flags; + + kbdev = container_of(timer, struct kbase_device, + pm.backend.gpu_poweroff_timer); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* It is safe for this call to do nothing if the work item is already + * queued. The worker function will read the must up-to-date state of + * kbdev->pm.backend.gpu_poweroff_pending under lock. + * + * If a state change occurs while the worker function is processing, + * this call will succeed as a work item can be requeued once it has + * started processing. + */ + if (kbdev->pm.backend.gpu_poweroff_pending) + queue_work(kbdev->pm.backend.gpu_poweroff_wq, + &kbdev->pm.backend.gpu_poweroff_work); + + if (kbdev->pm.backend.shader_poweroff_pending || + kbdev->pm.backend.tiler_poweroff_pending) { + kbdev->pm.backend.shader_poweroff_pending_time--; + + KBASE_DEBUG_ASSERT( + kbdev->pm.backend.shader_poweroff_pending_time + >= 0); + + if (!kbdev->pm.backend.shader_poweroff_pending_time) + kbasep_pm_do_poweroff_cores(kbdev); + } + + if (kbdev->pm.backend.poweroff_timer_needed) { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + hrtimer_add_expires(timer, kbdev->pm.gpu_poweroff_time); + + return HRTIMER_RESTART; + } + + kbdev->pm.backend.poweroff_timer_running = false; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return HRTIMER_NORESTART; +} + +static void kbasep_pm_do_gpu_poweroff_wq(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + bool do_poweroff = false; + + kbdev = container_of(data, struct kbase_device, + pm.backend.gpu_poweroff_work); + + mutex_lock(&kbdev->pm.lock); + + if (kbdev->pm.backend.gpu_poweroff_pending == 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + kbdev->pm.backend.gpu_poweroff_pending--; + + if (kbdev->pm.backend.gpu_poweroff_pending > 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_poweroff_pending == 0); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Only power off the GPU if a request is still pending */ + if (!kbdev->pm.backend.pm_current_policy->get_core_active(kbdev)) + do_poweroff = true; + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + if (do_poweroff) { + kbdev->pm.backend.poweroff_timer_needed = false; + hrtimer_cancel(&kbdev->pm.backend.gpu_poweroff_timer); + kbdev->pm.backend.poweroff_timer_running = false; + + /* Power off the GPU */ + kbase_pm_do_poweroff(kbdev, false); + } + + mutex_unlock(&kbdev->pm.lock); +} + +int kbase_pm_policy_init(struct kbase_device *kbdev) +{ + struct workqueue_struct *wq; + + wq = alloc_workqueue("kbase_pm_do_poweroff", + WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!wq) + return -ENOMEM; + + kbdev->pm.backend.gpu_poweroff_wq = wq; + INIT_WORK(&kbdev->pm.backend.gpu_poweroff_work, + kbasep_pm_do_gpu_poweroff_wq); + hrtimer_init(&kbdev->pm.backend.gpu_poweroff_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.backend.gpu_poweroff_timer.function = + kbasep_pm_do_gpu_poweroff_callback; + kbdev->pm.backend.pm_current_policy = policy_list[0]; + kbdev->pm.backend.pm_current_policy->init(kbdev); + kbdev->pm.gpu_poweroff_time = + HR_TIMER_DELAY_NSEC(DEFAULT_PM_GPU_POWEROFF_TICK_NS); + kbdev->pm.poweroff_shader_ticks = DEFAULT_PM_POWEROFF_TICK_SHADER; + kbdev->pm.poweroff_gpu_ticks = DEFAULT_PM_POWEROFF_TICK_GPU; + + return 0; +} + +void kbase_pm_policy_term(struct kbase_device *kbdev) +{ + kbdev->pm.backend.pm_current_policy->term(kbdev); + destroy_workqueue(kbdev->pm.backend.gpu_poweroff_wq); +} + +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev) +{ + unsigned long flags; + + lockdep_assert_held(&kbdev->pm.lock); + + kbdev->pm.backend.poweroff_timer_needed = false; + hrtimer_cancel(&kbdev->pm.backend.gpu_poweroff_timer); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->pm.backend.poweroff_timer_running = false; + + /* If wq is already running but is held off by pm.lock, make sure it has + * no effect */ + kbdev->pm.backend.gpu_poweroff_pending = 0; + + kbdev->pm.backend.shader_poweroff_pending = 0; + kbdev->pm.backend.tiler_poweroff_pending = 0; + kbdev->pm.backend.shader_poweroff_pending_time = 0; + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +void kbase_pm_update_active(struct kbase_device *kbdev) +{ + struct kbase_pm_device_data *pm = &kbdev->pm; + struct kbase_pm_backend_data *backend = &pm->backend; + unsigned long flags; + bool active; + + lockdep_assert_held(&pm->lock); + + /* pm_current_policy will never be NULL while pm.lock is held */ + KBASE_DEBUG_ASSERT(backend->pm_current_policy); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + active = backend->pm_current_policy->get_core_active(kbdev); + + if (active) { + if (backend->gpu_poweroff_pending) { + /* Cancel any pending power off request */ + backend->gpu_poweroff_pending = 0; + + /* If a request was pending then the GPU was still + * powered, so no need to continue */ + if (!kbdev->poweroff_pending) { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, + flags); + return; + } + } + + if (!backend->poweroff_timer_running && !backend->gpu_powered && + (pm->poweroff_gpu_ticks || + pm->poweroff_shader_ticks)) { + backend->poweroff_timer_needed = true; + backend->poweroff_timer_running = true; + hrtimer_start(&backend->gpu_poweroff_timer, + pm->gpu_poweroff_time, + HRTIMER_MODE_REL); + } + + /* Power on the GPU and any cores requested by the policy */ + if (pm->backend.poweroff_wait_in_progress) { + pm->backend.poweron_required = true; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } else { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + kbase_pm_do_poweron(kbdev, false); + } + } else { + /* It is an error for the power policy to power off the GPU + * when there are contexts active */ + KBASE_DEBUG_ASSERT(pm->active_count == 0); + + if (backend->shader_poweroff_pending || + backend->tiler_poweroff_pending) { + backend->shader_poweroff_pending = 0; + backend->tiler_poweroff_pending = 0; + backend->shader_poweroff_pending_time = 0; + } + + /* Request power off */ + if (pm->backend.gpu_powered) { + if (pm->poweroff_gpu_ticks) { + backend->gpu_poweroff_pending = + pm->poweroff_gpu_ticks; + backend->poweroff_timer_needed = true; + if (!backend->poweroff_timer_running) { + /* Start timer if not running (eg if + * power policy has been changed from + * always_on to something else). This + * will ensure the GPU is actually + * powered off */ + backend->poweroff_timer_running + = true; + hrtimer_start( + &backend->gpu_poweroff_timer, + pm->gpu_poweroff_time, + HRTIMER_MODE_REL); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, + flags); + } else { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, + flags); + + /* Power off the GPU immediately */ + kbase_pm_do_poweroff(kbdev, false); + } + } else { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } + } +} + +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev) +{ + u64 desired_bitmap; + u64 desired_tiler_bitmap; + bool cores_are_available; + bool do_poweroff = false; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->pm.backend.pm_current_policy == NULL) + return; + if (kbdev->pm.backend.poweroff_wait_in_progress) + return; + + if (kbdev->protected_mode_transition && !kbdev->shader_needed_bitmap && + !kbdev->shader_inuse_bitmap && !kbdev->tiler_needed_cnt + && !kbdev->tiler_inuse_cnt) { + /* We are trying to change in/out of protected mode - force all + * cores off so that the L2 powers down */ + desired_bitmap = 0; + desired_tiler_bitmap = 0; + } else { + desired_bitmap = + kbdev->pm.backend.pm_current_policy->get_core_mask(kbdev); + desired_bitmap &= kbase_pm_ca_get_core_mask(kbdev); + + if (kbdev->tiler_needed_cnt > 0 || kbdev->tiler_inuse_cnt > 0) + desired_tiler_bitmap = 1; + else + desired_tiler_bitmap = 0; + + if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY)) { + /* Unless XAFFINITY is supported, enable core 0 if tiler + * required, regardless of core availability */ + if (kbdev->tiler_needed_cnt > 0 || + kbdev->tiler_inuse_cnt > 0) + desired_bitmap |= 1; + } + } + + if (kbdev->pm.backend.desired_shader_state != desired_bitmap) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, NULL, 0u, + (u32)desired_bitmap); + /* Are any cores being powered on? */ + if (~kbdev->pm.backend.desired_shader_state & desired_bitmap || + ~kbdev->pm.backend.desired_tiler_state & desired_tiler_bitmap || + kbdev->pm.backend.ca_in_transition) { + /* Check if we are powering off any cores before updating shader + * state */ + if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap || + kbdev->pm.backend.desired_tiler_state & + ~desired_tiler_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.backend.shader_poweroff_pending |= + (kbdev->pm.backend.desired_shader_state & + ~desired_bitmap); + kbdev->pm.backend.tiler_poweroff_pending |= + (kbdev->pm.backend.desired_tiler_state & + ~desired_tiler_bitmap); + + if (kbdev->pm.poweroff_shader_ticks && + !kbdev->protected_mode_transition) + kbdev->pm.backend.shader_poweroff_pending_time = + kbdev->pm.poweroff_shader_ticks; + else + do_poweroff = true; + } + + kbdev->pm.backend.desired_shader_state = desired_bitmap; + kbdev->pm.backend.desired_tiler_state = desired_tiler_bitmap; + + /* If any cores are being powered on, transition immediately */ + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + } else if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap || + kbdev->pm.backend.desired_tiler_state & + ~desired_tiler_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.backend.shader_poweroff_pending |= + (kbdev->pm.backend.desired_shader_state & + ~desired_bitmap); + kbdev->pm.backend.tiler_poweroff_pending |= + (kbdev->pm.backend.desired_tiler_state & + ~desired_tiler_bitmap); + if (kbdev->pm.poweroff_shader_ticks && + !kbdev->protected_mode_transition) + kbdev->pm.backend.shader_poweroff_pending_time = + kbdev->pm.poweroff_shader_ticks; + else + kbasep_pm_do_poweroff_cores(kbdev); + } else if (kbdev->pm.active_count == 0 && desired_bitmap != 0 && + desired_tiler_bitmap != 0 && + kbdev->pm.backend.poweroff_timer_needed) { + /* If power policy is keeping cores on despite there being no + * active contexts then disable poweroff timer as it isn't + * required. + * Only reset poweroff_timer_needed if we're not in the middle + * of the power off callback */ + kbdev->pm.backend.poweroff_timer_needed = false; + } + + /* Ensure timer does not power off wanted cores and make sure to power + * off unwanted cores */ + if (kbdev->pm.backend.shader_poweroff_pending || + kbdev->pm.backend.tiler_poweroff_pending) { + kbdev->pm.backend.shader_poweroff_pending &= + ~(kbdev->pm.backend.desired_shader_state & + desired_bitmap); + kbdev->pm.backend.tiler_poweroff_pending &= + ~(kbdev->pm.backend.desired_tiler_state & + desired_tiler_bitmap); + + if (!kbdev->pm.backend.shader_poweroff_pending && + !kbdev->pm.backend.tiler_poweroff_pending) + kbdev->pm.backend.shader_poweroff_pending_time = 0; + } + + /* Shader poweroff is deferred to the end of the function, to eliminate + * issues caused by the core availability policy recursing into this + * function */ + if (do_poweroff) + kbasep_pm_do_poweroff_cores(kbdev); + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); +} + +void kbase_pm_update_cores_state(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +int kbase_pm_list_policies(const struct kbase_pm_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_list_policies); + +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.backend.pm_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_policy); + +void kbase_pm_set_policy(struct kbase_device *kbdev, + const struct kbase_pm_policy *new_policy) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + const struct kbase_pm_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_SET_POLICY, NULL, NULL, 0u, new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a + * userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + old_policy = kbdev->pm.backend.pm_current_policy; + kbdev->pm.backend.pm_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_TERM, NULL, NULL, 0u, + old_policy->id); + if (old_policy->term) + old_policy->term(kbdev); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_INIT, NULL, NULL, 0u, + new_policy->id); + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->pm.backend.pm_current_policy = new_policy; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + /* If any core power state changes were previously attempted, but + * couldn't be made because the policy was changing (current_policy was + * NULL), then re-try them here. */ + kbase_pm_update_active(kbdev); + kbase_pm_update_cores_state(kbdev); + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + + /* Now the policy change is finished, we release our fake context active + * reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_set_policy); + +/* Check whether a state change has finished, and trace it as completed */ +static void +kbase_pm_trace_check_and_finish_state_change(struct kbase_device *kbdev) +{ + if ((kbdev->shader_available_bitmap & + kbdev->pm.backend.desired_shader_state) + == kbdev->pm.backend.desired_shader_state && + (kbdev->tiler_available_bitmap & + kbdev->pm.backend.desired_tiler_state) + == kbdev->pm.backend.desired_tiler_state) + kbase_timeline_pm_check_handle_event(kbdev, + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); +} + +void kbase_pm_request_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores) +{ + u64 cores; + + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + cores = shader_cores; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + + /* It should be almost impossible for this to overflow. It would + * require 2^32 atoms to request a particular core, which would + * require 2^24 contexts to submit. This would require an amount + * of memory that is impossible on a 32-bit system and extremely + * unlikely on a 64-bit system. */ + int cnt = ++kbdev->shader_needed_cnt[bitnum]; + + if (1 == cnt) { + kbdev->shader_needed_bitmap |= bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + cores &= ~bit; + } + + if (tiler_required) { + int cnt = ++kbdev->tiler_needed_cnt; + + if (1 == cnt) + change_gpu_state |= KBASE_PM_CHANGE_STATE_TILER; + + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt != 0); + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_REQUEST_CHANGE_SHADER_NEEDED, NULL, + NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_timeline_pm_cores_func(kbdev, + KBASE_PM_FUNC_ID_REQUEST_CORES_START, + change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, + KBASE_PM_FUNC_ID_REQUEST_CORES_END, + change_gpu_state); + } +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores); + +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores) +{ + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_needed_bitmap &= ~bit; + + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required) { + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + cnt = --kbdev->tiler_needed_cnt; + + if (0 == cnt) + change_gpu_state |= KBASE_PM_CHANGE_STATE_TILER; + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_UNREQUEST_CHANGE_SHADER_NEEDED, NULL, + NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_pm_update_cores_state_nolock(kbdev); + + /* Trace that any state change effectively completes immediately + * - no-one will wait on the state change */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } +} + +KBASE_EXPORT_TEST_API(kbase_pm_unrequest_cores); + +enum kbase_pm_cores_ready +kbase_pm_register_inuse_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores) +{ + u64 prev_shader_needed; /* Just for tracing */ + u64 prev_shader_inuse; /* Just for tracing */ + + lockdep_assert_held(&kbdev->hwaccess_lock); + + prev_shader_needed = kbdev->shader_needed_bitmap; + prev_shader_inuse = kbdev->shader_inuse_bitmap; + + /* If desired_shader_state does not contain the requested cores, then + * power management is not attempting to powering those cores (most + * likely due to core availability policy) and a new job affinity must + * be chosen */ + if ((kbdev->pm.backend.desired_shader_state & shader_cores) != + shader_cores) { + return (kbdev->pm.backend.poweroff_wait_in_progress || + kbdev->pm.backend.pm_current_policy == NULL) ? + KBASE_CORES_NOT_READY : KBASE_NEW_AFFINITY; + } + + if ((kbdev->shader_available_bitmap & shader_cores) != shader_cores || + (tiler_required && !kbdev->tiler_available_bitmap)) { + /* Trace ongoing core transition */ + kbase_timeline_pm_l2_transition_start(kbdev); + return KBASE_CORES_NOT_READY; + } + + /* If we started to trace a state change, then trace it has being + * finished by now, at the very latest */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + /* Trace core transition done */ + kbase_timeline_pm_l2_transition_done(kbdev); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) + kbdev->shader_needed_bitmap &= ~bit; + + /* shader_inuse_cnt should not overflow because there can only + * be a very limited number of jobs on the h/w at one time */ + + kbdev->shader_inuse_cnt[bitnum]++; + kbdev->shader_inuse_bitmap |= bit; + + shader_cores &= ~bit; + } + + if (tiler_required) { + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + --kbdev->tiler_needed_cnt; + + kbdev->tiler_inuse_cnt++; + + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt != 0); + } + + if (prev_shader_needed != kbdev->shader_needed_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_NEEDED, NULL, + NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + if (prev_shader_inuse != kbdev->shader_inuse_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_INUSE, NULL, + NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + return KBASE_CORES_READY; +} + +KBASE_EXPORT_TEST_API(kbase_pm_register_inuse_cores); + +void kbase_pm_release_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores) +{ + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + lockdep_assert_held(&kbdev->hwaccess_lock); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_inuse_cnt[bitnum] > 0); + + cnt = --kbdev->shader_inuse_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_inuse_bitmap &= ~bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required) { + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt > 0); + + cnt = --kbdev->tiler_inuse_cnt; + + if (0 == cnt) + change_gpu_state |= KBASE_PM_CHANGE_STATE_TILER; + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_RELEASE_CHANGE_SHADER_INUSE, NULL, + NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + kbase_timeline_pm_cores_func(kbdev, + KBASE_PM_FUNC_ID_RELEASE_CORES_START, + change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, + KBASE_PM_FUNC_ID_RELEASE_CORES_END, + change_gpu_state); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_cores); + +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, + bool tiler_required, + u64 shader_cores) +{ + unsigned long flags; + + kbase_pm_wait_for_poweroff_complete(kbdev); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_request_cores(kbdev, tiler_required, shader_cores); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + kbase_pm_check_transitions_sync(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores_sync); + +void kbase_pm_request_l2_caches(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 prior_l2_users_count; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + prior_l2_users_count = kbdev->l2_users_count++; + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count != 0); + + /* if the GPU is reset while the l2 is on, l2 will be off but + * prior_l2_users_count will be > 0. l2_available_bitmap will have been + * set to 0 though by kbase_pm_init_hw */ + if (!prior_l2_users_count || !kbdev->l2_available_bitmap) + kbase_pm_check_transitions_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + wait_event(kbdev->pm.backend.l2_powered_wait, + kbdev->pm.backend.l2_powered == 1); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches); + +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + kbdev->l2_users_count++; +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches_l2_is_on); + +void kbase_pm_release_l2_caches(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count > 0); + + --kbdev->l2_users_count; + + if (!kbdev->l2_users_count) { + kbase_pm_check_transitions_nolock(kbdev); + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_l2_caches); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.h new file mode 100644 index 000000000000..611a90e66e65 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.h @@ -0,0 +1,227 @@ +/* + * + * (C) COPYRIGHT 2010-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Power policy API definitions + */ + +#ifndef _KBASE_PM_POLICY_H_ +#define _KBASE_PM_POLICY_H_ + +/** + * kbase_pm_policy_init - Initialize power policy framework + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Must be called before calling any other policy function + * + * Return: 0 if the power policy framework was successfully + * initialized, -errno otherwise. + */ +int kbase_pm_policy_init(struct kbase_device *kbdev); + +/** + * kbase_pm_policy_term - Terminate power policy framework + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_policy_term(struct kbase_device *kbdev); + +/** + * kbase_pm_update_active - Update the active power state of the GPU + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Calls into the current power policy + */ +void kbase_pm_update_active(struct kbase_device *kbdev); + +/** + * kbase_pm_update_cores - Update the desired core state of the GPU + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Calls into the current power policy + */ +void kbase_pm_update_cores(struct kbase_device *kbdev); + + +enum kbase_pm_cores_ready { + KBASE_CORES_NOT_READY = 0, + KBASE_NEW_AFFINITY = 1, + KBASE_CORES_READY = 2 +}; + + +/** + * kbase_pm_request_cores_sync - Synchronous variant of kbase_pm_request_cores() + * + * @kbdev: The kbase device structure for the device + * @tiler_required: true if the tiler is required, false otherwise + * @shader_cores: A bitmask of shader cores which are necessary for the job + * + * When this function returns, the @shader_cores will be in the READY state. + * + * This is safe variant of kbase_pm_check_transitions_sync(): it handles the + * work of ensuring the requested cores will remain powered until a matching + * call to kbase_pm_unrequest_cores()/kbase_pm_release_cores() (as appropriate) + * is made. + */ +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores); + +/** + * kbase_pm_request_cores - Mark one or more cores as being required + * for jobs to be submitted + * + * @kbdev: The kbase device structure for the device + * @tiler_required: true if the tiler is required, false otherwise + * @shader_cores: A bitmask of shader cores which are necessary for the job + * + * This function is called by the job scheduler to mark one or more cores as + * being required to submit jobs that are ready to run. + * + * The cores requested are reference counted and a subsequent call to + * kbase_pm_register_inuse_cores() or kbase_pm_unrequest_cores() should be + * made to dereference the cores as being 'needed'. + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete/the cores might not be available + * until a Power Management IRQ. + * + * Return: 0 if the cores were successfully requested, or -errno otherwise. + */ +void kbase_pm_request_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores); + +/** + * kbase_pm_unrequest_cores - Unmark one or more cores as being required for + * jobs to be submitted. + * + * @kbdev: The kbase device structure for the device + * @tiler_required: true if the tiler is required, false otherwise + * @shader_cores: A bitmask of shader cores (as given to + * kbase_pm_request_cores() ) + * + * This function undoes the effect of kbase_pm_request_cores(). It should be + * used when a job is not going to be submitted to the hardware (e.g. the job is + * cancelled before it is enqueued). + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete until a Power Management IRQ. + * + * The policy may use this as an indication that it can power down cores. + */ +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores); + +/** + * kbase_pm_register_inuse_cores - Register a set of cores as in use by a job + * + * @kbdev: The kbase device structure for the device + * @tiler_required: true if the tiler is required, false otherwise + * @shader_cores: A bitmask of shader cores (as given to + * kbase_pm_request_cores() ) + * + * This function should be called after kbase_pm_request_cores() when the job + * is about to be submitted to the hardware. It will check that the necessary + * cores are available and if so update the 'needed' and 'inuse' bitmasks to + * reflect that the job is now committed to being run. + * + * If the necessary cores are not currently available then the function will + * return %KBASE_CORES_NOT_READY and have no effect. + * + * Return: %KBASE_CORES_NOT_READY if the cores are not immediately ready, + * + * %KBASE_NEW_AFFINITY if the affinity requested is not allowed, + * + * %KBASE_CORES_READY if the cores requested are already available + */ +enum kbase_pm_cores_ready kbase_pm_register_inuse_cores( + struct kbase_device *kbdev, + bool tiler_required, + u64 shader_cores); + +/** + * kbase_pm_release_cores - Release cores after a job has run + * + * @kbdev: The kbase device structure for the device + * @tiler_required: true if the tiler is required, false otherwise + * @shader_cores: A bitmask of shader cores (as given to + * kbase_pm_register_inuse_cores() ) + * + * This function should be called when a job has finished running on the + * hardware. A call to kbase_pm_register_inuse_cores() must have previously + * occurred. The reference counts of the specified cores will be decremented + * which may cause the bitmask of 'inuse' cores to be reduced. The power policy + * may then turn off any cores which are no longer 'inuse'. + */ +void kbase_pm_release_cores(struct kbase_device *kbdev, + bool tiler_required, u64 shader_cores); + +/** + * kbase_pm_request_l2_caches - Request l2 caches + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Request the use of l2 caches for all core groups, power up, wait and prevent + * the power manager from powering down the l2 caches. + * + * This tells the power management that the caches should be powered up, and + * they should remain powered, irrespective of the usage of shader cores. This + * does not return until the l2 caches are powered up. + * + * The caller must call kbase_pm_release_l2_caches() when they are finished + * to allow normal power management of the l2 caches to resume. + * + * This should only be used when power management is active. + */ +void kbase_pm_request_l2_caches(struct kbase_device *kbdev); + +/** + * kbase_pm_request_l2_caches_l2_is_on - Request l2 caches but don't power on + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Increment the count of l2 users but do not attempt to power on the l2 + * + * It is the callers responsibility to ensure that the l2 is already powered up + * and to eventually call kbase_pm_release_l2_caches() + */ +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev); + +/** + * kbase_pm_request_l2_caches - Release l2 caches + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * Release the use of l2 caches for all core groups and allow the power manager + * to power them down when necessary. + * + * This tells the power management that the caches can be powered down if + * necessary, with respect to the usage of shader cores. + * + * The caller must have called kbase_pm_request_l2_caches() prior to a call + * to this. + * + * This should only be used when power management is active. + */ +void kbase_pm_release_l2_caches(struct kbase_device *kbdev); + +#endif /* _KBASE_PM_POLICY_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c new file mode 100644 index 000000000000..d992989123e8 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c @@ -0,0 +1,103 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, + u64 *system_time, struct timespec *ts) +{ + u32 hi1, hi2; + + kbase_pm_request_gpu_cycle_counter(kbdev); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled + * correctly */ + do { + hi1 = kbase_reg_read(kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), + NULL); + *cycle_counter = kbase_reg_read(kbdev, + GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + hi2 = kbase_reg_read(kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), + NULL); + *cycle_counter |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled + * correctly */ + do { + hi1 = kbase_reg_read(kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), + NULL); + *system_time = kbase_reg_read(kbdev, + GPU_CONTROL_REG(TIMESTAMP_LO), NULL); + hi2 = kbase_reg_read(kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), + NULL); + *system_time |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Record the CPU's idea of current time */ + getrawmonotonic(ts); + + kbase_pm_release_gpu_cycle_counter(kbdev); +} + +/** + * kbase_wait_write_flush - Wait for GPU write flush + * @kctx: Context pointer + * + * Wait 1000 GPU clock cycles. This delay is known to give the GPU time to flush + * its write buffer. + * + * Only in use for BASE_HW_ISSUE_6367 + * + * Note : If GPU resets occur then the counters are reset to zero, the delay may + * not be as expected. + */ +#ifndef CONFIG_MALI_NO_MALI +void kbase_wait_write_flush(struct kbase_context *kctx) +{ + u32 base_count = 0; + + /* + * The caller must be holding onto the kctx or the call is from + * userspace. + */ + kbase_pm_context_active(kctx->kbdev); + kbase_pm_request_gpu_cycle_counter(kctx->kbdev); + + while (true) { + u32 new_count; + + new_count = kbase_reg_read(kctx->kbdev, + GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + /* First time around, just store the count. */ + if (base_count == 0) { + base_count = new_count; + continue; + } + + /* No need to handle wrapping, unsigned maths works for this. */ + if ((new_count - base_count) > 1000) + break; + } + + kbase_pm_release_gpu_cycle_counter(kctx->kbdev); + kbase_pm_context_idle(kctx->kbdev); +} +#endif /* CONFIG_MALI_NO_MALI */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h new file mode 100644 index 000000000000..35088abc8fe5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_BACKEND_TIME_H_ +#define _KBASE_BACKEND_TIME_H_ + +/** + * kbase_backend_get_gpu_time() - Get current GPU time + * @kbdev: Device pointer + * @cycle_counter: Pointer to u64 to store cycle counter in + * @system_time: Pointer to u64 to store system time in + * @ts: Pointer to struct timespec to store current monotonic + * time in + */ +void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, + u64 *system_time, struct timespec *ts); + +/** + * kbase_wait_write_flush() - Wait for GPU write flush + * @kctx: Context pointer + * + * Wait 1000 GPU clock cycles. This delay is known to give the GPU time to flush + * its write buffer. + * + * If GPU resets occur then the counters are reset to zero, the delay may not be + * as expected. + * + * This function is only in use for BASE_HW_ISSUE_6367 + */ +#ifdef CONFIG_MALI_NO_MALI +static inline void kbase_wait_write_flush(struct kbase_context *kctx) +{ +} +#else +void kbase_wait_write_flush(struct kbase_context *kctx); +#endif + +#endif /* _KBASE_BACKEND_TIME_H_ */ diff --git a/drivers/gpu/arm/bifrost/docs/Doxyfile b/drivers/gpu/arm/bifrost/docs/Doxyfile new file mode 100644 index 000000000000..35ff2f1ce4a0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/docs/Doxyfile @@ -0,0 +1,126 @@ +# +# (C) COPYRIGHT 2011-2013, 2015 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +############################################################################## + +# This file contains per-module Doxygen configuration. Please do not add +# extra settings to this file without consulting all stakeholders, as they +# may cause override project-wide settings. +# +# Additionally, when defining aliases, macros, sections etc, use the module +# name as a prefix e.g. gles_my_alias. + +############################################################################## + +@INCLUDE = ../../bldsys/Doxyfile_common + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += ../../kernel/drivers/gpu/arm/midgard/ + +############################################################################## +# Everything below here is optional, and in most cases not required +############################################################################## + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES += + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS += + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS += + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE += ../../kernel/drivers/gpu/arm/midgard/platform ../../kernel/drivers/gpu/arm/midgard/platform_dummy ../../kernel/drivers/gpu/arm/midgard/scripts ../../kernel/drivers/gpu/arm/midgard/tests ../../kernel/drivers/gpu/arm/midgard/Makefile ../../kernel/drivers/gpu/arm/midgard/Makefile.kbase ../../kernel/drivers/gpu/arm/midgard/Kbuild ../../kernel/drivers/gpu/arm/midgard/Kconfig ../../kernel/drivers/gpu/arm/midgard/sconscript ../../kernel/drivers/gpu/arm/midgard/docs ../../kernel/drivers/gpu/arm/midgard/pm_test_script.sh ../../kernel/drivers/gpu/arm/midgard/mali_uk.h ../../kernel/drivers/gpu/arm/midgard/Makefile + + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS += + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS += + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH += + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH += + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH += + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED += + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED += + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS += ../../kernel/drivers/gpu/arm/midgard/docs + diff --git a/drivers/gpu/arm/bifrost/docs/policy_operation_diagram.dot b/drivers/gpu/arm/bifrost/docs/policy_operation_diagram.dot new file mode 100644 index 000000000000..7ae05c2f8ded --- /dev/null +++ b/drivers/gpu/arm/bifrost/docs/policy_operation_diagram.dot @@ -0,0 +1,112 @@ +/* + * + * (C) COPYRIGHT 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR; + size="12,8"; + compound=true; + + node [ shape = box ]; + + subgraph cluster_policy_queues { + low_queue [ shape=record label = "LowP | {ctx_lo | ... | ctx_i | ... | ctx_hi}" ]; + queues_middle_sep [ label="" shape=plaintext width=0 height=0 ]; + + rt_queue [ shape=record label = "RT | {ctx_lo | ... | ctx_j | ... | ctx_hi}" ]; + + label = "Policy's Queue(s)"; + } + + call_enqueue [ shape=plaintext label="enqueue_ctx()" ]; + + { + rank=same; + ordering=out; + call_dequeue [ shape=plaintext label="dequeue_head_ctx()\n+ runpool_add_ctx()" ]; + call_ctxfinish [ shape=plaintext label="runpool_remove_ctx()" ]; + + call_ctxdone [ shape=plaintext label="don't requeue;\n/* ctx has no more jobs */" ]; + } + + subgraph cluster_runpool { + + as0 [ width=2 height = 0.25 label="AS0: Job_1, ..., Job_n" ]; + as1 [ width=2 height = 0.25 label="AS1: Job_1, ..., Job_m" ]; + as2 [ width=2 height = 0.25 label="AS2: Job_1, ..., Job_p" ]; + as3 [ width=2 height = 0.25 label="AS3: Job_1, ..., Job_q" ]; + + label = "Policy's Run Pool"; + } + + { + rank=same; + call_jdequeue [ shape=plaintext label="dequeue_job()" ]; + sstop_dotfixup [ shape=plaintext label="" width=0 height=0 ]; + } + + { + rank=same; + ordering=out; + sstop [ shape=ellipse label="SS-Timer expires" ] + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + irq [ label="IRQ" shape=ellipse ]; + + job_finish [ shape=plaintext label="don't requeue;\n/* job done */" ]; + } + + hstop [ shape=ellipse label="HS-Timer expires" ] + + /* + * Edges + */ + + call_enqueue -> queues_middle_sep [ lhead=cluster_policy_queues ]; + + low_queue:qr -> call_dequeue:w; + rt_queue:qr -> call_dequeue:w; + + call_dequeue -> as1 [lhead=cluster_runpool]; + + as1->call_jdequeue [ltail=cluster_runpool]; + call_jdequeue->jobslots:0; + call_jdequeue->sstop_dotfixup [ arrowhead=none]; + sstop_dotfixup->sstop [label="Spawn SS-Timer"]; + sstop->jobslots [label="SoftStop"]; + sstop->hstop [label="Spawn HS-Timer"]; + hstop->jobslots:ne [label="HardStop"]; + + + as3->call_ctxfinish:ne [ ltail=cluster_runpool ]; + call_ctxfinish:sw->rt_queue:qm [ lhead=cluster_policy_queues label="enqueue_ctx()\n/* ctx still has jobs */" ]; + + call_ctxfinish->call_ctxdone [constraint=false]; + + call_ctxdone->call_enqueue [weight=0.1 labeldistance=20.0 labelangle=0.0 taillabel="Job submitted to the ctx" style=dotted constraint=false]; + + + { + jobslots->irq [constraint=false]; + + irq->job_finish [constraint=false]; + } + + irq->as2 [lhead=cluster_runpool label="requeue_job()\n/* timeslice expired */" ]; + +} diff --git a/drivers/gpu/arm/bifrost/docs/policy_overview.dot b/drivers/gpu/arm/bifrost/docs/policy_overview.dot new file mode 100644 index 000000000000..159b993b7d61 --- /dev/null +++ b/drivers/gpu/arm/bifrost/docs/policy_overview.dot @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR + size="6,6" + compound=true; + + node [ shape = box ]; + + call_enqueue [ shape=plaintext label="enqueue ctx" ]; + + + policy_queue [ label="Policy's Queue" ]; + + { + rank=same; + runpool [ label="Policy's Run Pool" ]; + + ctx_finish [ label="ctx finished" ]; + } + + { + rank=same; + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + job_finish [ label="Job finished" ]; + } + + + + /* + * Edges + */ + + call_enqueue -> policy_queue; + + policy_queue->runpool [label="dequeue ctx" weight=0.1]; + runpool->policy_queue [label="requeue ctx" weight=0.1]; + + runpool->ctx_finish [ style=dotted ]; + + runpool->jobslots [label="dequeue job" weight=0.1]; + jobslots->runpool [label="requeue job" weight=0.1]; + + jobslots->job_finish [ style=dotted ]; +} diff --git a/drivers/gpu/arm/bifrost/ipa/Kbuild b/drivers/gpu/arm/bifrost/ipa/Kbuild new file mode 100644 index 000000000000..8e37f406433e --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/Kbuild @@ -0,0 +1,27 @@ +# +# (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +mali_kbase-y += \ + ipa/mali_kbase_ipa_simple.o \ + ipa/mali_kbase_ipa.o + +mali_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o + +ifneq ($(wildcard $(src)/ipa/mali_kbase_ipa_vinstr_g71.c),) + mali_kbase-y += \ + ipa/mali_kbase_ipa_vinstr_g71.o \ + ipa/mali_kbase_ipa_vinstr_common.o + +endif diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c new file mode 100644 index 000000000000..e7e22991f2a7 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c @@ -0,0 +1,583 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include +#include "mali_kbase.h" +#include "mali_kbase_ipa.h" +#include "mali_kbase_ipa_debugfs.h" +#include "mali_kbase_ipa_simple.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#include +#else +#include +#define dev_pm_opp_find_freq_exact opp_find_freq_exact +#define dev_pm_opp_get_voltage opp_get_voltage +#define dev_pm_opp opp +#endif + +#define KBASE_IPA_FALLBACK_MODEL_NAME "mali-simple-power-model" +#define KBASE_IPA_G71_MODEL_NAME "mali-g71-power-model" + +static struct kbase_ipa_model_ops *kbase_ipa_all_model_ops[] = { + &kbase_simple_ipa_model_ops, + &kbase_g71_ipa_model_ops +}; + +int kbase_ipa_model_recalculate(struct kbase_ipa_model *model) +{ + int err = 0; + + lockdep_assert_held(&model->kbdev->ipa.lock); + + if (model->ops->recalculate) { + err = model->ops->recalculate(model); + if (err) { + dev_err(model->kbdev->dev, + "recalculation of power model %s returned error %d\n", + model->ops->name, err); + } + } + + return err; +} + +static struct kbase_ipa_model_ops *kbase_ipa_model_ops_find(struct kbase_device *kbdev, + const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kbase_ipa_all_model_ops); ++i) { + struct kbase_ipa_model_ops *ops = kbase_ipa_all_model_ops[i]; + + if (!strcmp(ops->name, name)) + return ops; + } + + dev_err(kbdev->dev, "power model \'%s\' not found\n", name); + + return NULL; +} + +void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev) +{ + atomic_set(&kbdev->ipa_use_configured_model, false); +} + +void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev) +{ + atomic_set(&kbdev->ipa_use_configured_model, true); +} + +const char *kbase_ipa_model_name_from_id(u32 gpu_id) +{ + const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> + GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + if (GPU_ID_IS_NEW_FORMAT(prod_id)) { + switch (GPU_ID2_MODEL_MATCH_VALUE(prod_id)) { + case GPU_ID2_PRODUCT_TMIX: + return KBASE_IPA_G71_MODEL_NAME; + default: + return KBASE_IPA_FALLBACK_MODEL_NAME; + } + } + + return KBASE_IPA_FALLBACK_MODEL_NAME; +} + +static struct device_node *get_model_dt_node(struct kbase_ipa_model *model) +{ + struct device_node *model_dt_node; + char compat_string[64]; + + snprintf(compat_string, sizeof(compat_string), "arm,%s", + model->ops->name); + + model_dt_node = of_find_compatible_node(model->kbdev->dev->of_node, + NULL, compat_string); + if (!model_dt_node && !model->missing_dt_node_warning) { + dev_warn(model->kbdev->dev, + "Couldn't find power_model DT node matching \'%s\'\n", + compat_string); + model->missing_dt_node_warning = true; + } + + return model_dt_node; +} + +int kbase_ipa_model_add_param_s32(struct kbase_ipa_model *model, + const char *name, s32 *addr, + size_t num_elems, bool dt_required) +{ + int err, i; + struct device_node *model_dt_node = get_model_dt_node(model); + char *origin; + + err = of_property_read_u32_array(model_dt_node, name, addr, num_elems); + + if (err && dt_required) { + memset(addr, 0, sizeof(s32) * num_elems); + dev_warn(model->kbdev->dev, + "Error %d, no DT entry: %s.%s = %zu*[0]\n", + err, model->ops->name, name, num_elems); + origin = "zero"; + } else if (err && !dt_required) { + origin = "default"; + } else /* !err */ { + origin = "DT"; + } + + /* Create a unique debugfs entry for each element */ + for (i = 0; i < num_elems; ++i) { + char elem_name[32]; + + if (num_elems == 1) + snprintf(elem_name, sizeof(elem_name), "%s", name); + else + snprintf(elem_name, sizeof(elem_name), "%s.%d", + name, i); + + dev_dbg(model->kbdev->dev, "%s.%s = %d (%s)\n", + model->ops->name, elem_name, addr[i], origin); + + err = kbase_ipa_model_param_add(model, elem_name, + &addr[i], sizeof(s32), + PARAM_TYPE_S32); + if (err) + goto exit; + } +exit: + return err; +} + +int kbase_ipa_model_add_param_string(struct kbase_ipa_model *model, + const char *name, char *addr, + size_t size, bool dt_required) +{ + int err; + struct device_node *model_dt_node = get_model_dt_node(model); + const char *string_prop_value; + char *origin; + + err = of_property_read_string(model_dt_node, name, + &string_prop_value); + if (err && dt_required) { + strncpy(addr, "", size - 1); + dev_warn(model->kbdev->dev, + "Error %d, no DT entry: %s.%s = \'%s\'\n", + err, model->ops->name, name, addr); + err = 0; + origin = "zero"; + } else if (err && !dt_required) { + origin = "default"; + } else /* !err */ { + strncpy(addr, string_prop_value, size - 1); + origin = "DT"; + } + + addr[size - 1] = '\0'; + + dev_dbg(model->kbdev->dev, "%s.%s = \'%s\' (%s)\n", + model->ops->name, name, string_prop_value, origin); + + err = kbase_ipa_model_param_add(model, name, addr, size, + PARAM_TYPE_STRING); + + return err; +} + +void kbase_ipa_term_model(struct kbase_ipa_model *model) +{ + if (!model) + return; + + lockdep_assert_held(&model->kbdev->ipa.lock); + + if (model->ops->term) + model->ops->term(model); + + kbase_ipa_model_param_free_all(model); + + kfree(model); +} +KBASE_EXPORT_TEST_API(kbase_ipa_term_model); + +struct kbase_ipa_model *kbase_ipa_init_model(struct kbase_device *kbdev, + struct kbase_ipa_model_ops *ops) +{ + struct kbase_ipa_model *model; + int err; + + lockdep_assert_held(&kbdev->ipa.lock); + + if (!ops || !ops->name) + return NULL; + + model = kzalloc(sizeof(struct kbase_ipa_model), GFP_KERNEL); + if (!model) + return NULL; + + model->kbdev = kbdev; + model->ops = ops; + INIT_LIST_HEAD(&model->params); + + err = model->ops->init(model); + if (err) { + dev_err(kbdev->dev, + "init of power model \'%s\' returned error %d\n", + ops->name, err); + kfree(model); + return NULL; + } + + err = kbase_ipa_model_recalculate(model); + if (err) { + kbase_ipa_term_model(model); + return NULL; + } + + return model; +} +KBASE_EXPORT_TEST_API(kbase_ipa_init_model); + +static void kbase_ipa_term_locked(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->ipa.lock); + + /* Clean up the models */ + if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model) + kbase_ipa_term_model(kbdev->ipa.configured_model); + kbase_ipa_term_model(kbdev->ipa.fallback_model); + + kbdev->ipa.configured_model = NULL; + kbdev->ipa.fallback_model = NULL; +} + +int kbase_ipa_init(struct kbase_device *kbdev) +{ + + const char *model_name; + struct kbase_ipa_model_ops *ops; + struct kbase_ipa_model *default_model = NULL; + int err; + + mutex_init(&kbdev->ipa.lock); + /* + * Lock during init to avoid warnings from lockdep_assert_held (there + * shouldn't be any concurrent access yet). + */ + mutex_lock(&kbdev->ipa.lock); + + /* The simple IPA model must *always* be present.*/ + ops = kbase_ipa_model_ops_find(kbdev, KBASE_IPA_FALLBACK_MODEL_NAME); + + if (!ops->do_utilization_scaling_in_framework) { + dev_err(kbdev->dev, + "Fallback IPA model %s should not account for utilization\n", + ops->name); + err = -EINVAL; + goto end; + } + + default_model = kbase_ipa_init_model(kbdev, ops); + if (!default_model) { + err = -EINVAL; + goto end; + } + + kbdev->ipa.fallback_model = default_model; + err = of_property_read_string(kbdev->dev->of_node, + "ipa-model", + &model_name); + if (err) { + /* Attempt to load a match from GPU-ID */ + u32 gpu_id; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + model_name = kbase_ipa_model_name_from_id(gpu_id); + dev_dbg(kbdev->dev, + "Inferring model from GPU ID 0x%x: \'%s\'\n", + gpu_id, model_name); + err = 0; + } else { + dev_dbg(kbdev->dev, + "Using ipa-model parameter from DT: \'%s\'\n", + model_name); + } + + if (strcmp(KBASE_IPA_FALLBACK_MODEL_NAME, model_name) != 0) { + ops = kbase_ipa_model_ops_find(kbdev, model_name); + kbdev->ipa.configured_model = kbase_ipa_init_model(kbdev, ops); + if (!kbdev->ipa.configured_model) { + err = -EINVAL; + goto end; + } + } else { + kbdev->ipa.configured_model = default_model; + } + + kbase_ipa_model_use_configured_locked(kbdev); + +end: + if (err) + kbase_ipa_term_locked(kbdev); + else + dev_info(kbdev->dev, + "Using configured power model %s, and fallback %s\n", + kbdev->ipa.configured_model->ops->name, + kbdev->ipa.fallback_model->ops->name); + + mutex_unlock(&kbdev->ipa.lock); + return err; +} +KBASE_EXPORT_TEST_API(kbase_ipa_init); + +void kbase_ipa_term(struct kbase_device *kbdev) +{ + mutex_lock(&kbdev->ipa.lock); + kbase_ipa_term_locked(kbdev); + mutex_unlock(&kbdev->ipa.lock); +} +KBASE_EXPORT_TEST_API(kbase_ipa_term); + +/** + * kbase_scale_dynamic_power() - Scale a dynamic power coefficient to an OPP + * @c: Dynamic model coefficient, in pW/(Hz V^2). Should be in range + * 0 < c < 2^26 to prevent overflow. + * @freq: Frequency, in Hz. Range: 2^23 < freq < 2^30 (~8MHz to ~1GHz) + * @voltage: Voltage, in mV. Range: 2^9 < voltage < 2^13 (~0.5V to ~8V) + * + * Keep a record of the approximate range of each value at every stage of the + * calculation, to ensure we don't overflow. This makes heavy use of the + * approximations 1000 = 2^10 and 1000000 = 2^20, but does the actual + * calculations in decimal for increased accuracy. + * + * Return: Power consumption, in mW. Range: 0 < p < 2^13 (0W to ~8W) + */ +static u32 kbase_scale_dynamic_power(const u32 c, const u32 freq, + const u32 voltage) +{ + /* Range: 2^8 < v2 < 2^16 m(V^2) */ + const u32 v2 = (voltage * voltage) / 1000; + + /* Range: 2^3 < f_MHz < 2^10 MHz */ + const u32 f_MHz = freq / 1000000; + + /* Range: 2^11 < v2f_big < 2^26 kHz V^2 */ + const u32 v2f_big = v2 * f_MHz; + + /* Range: 2^1 < v2f < 2^16 MHz V^2 */ + const u32 v2f = v2f_big / 1000; + + /* Range (working backwards from next line): 0 < v2fc < 2^23 uW. + * Must be < 2^42 to avoid overflowing the return value. */ + const u64 v2fc = (u64) c * (u64) v2f; + + /* Range: 0 < v2fc / 1000 < 2^13 mW */ + return v2fc / 1000; +} + +/** + * kbase_scale_static_power() - Scale a static power coefficient to an OPP + * @c: Static model coefficient, in uW/V^3. Should be in range + * 0 < c < 2^32 to prevent overflow. + * @voltage: Voltage, in mV. Range: 2^9 < voltage < 2^13 (~0.5V to ~8V) + * + * Return: Power consumption, in mW. Range: 0 < p < 2^13 (0W to ~8W) + */ +u32 kbase_scale_static_power(const u32 c, const u32 voltage) +{ + /* Range: 2^8 < v2 < 2^16 m(V^2) */ + const u32 v2 = (voltage * voltage) / 1000; + + /* Range: 2^17 < v3_big < 2^29 m(V^2) mV */ + const u32 v3_big = v2 * voltage; + + /* Range: 2^7 < v3 < 2^19 m(V^3) */ + const u32 v3 = v3_big / 1000; + + /* + * Range (working backwards from next line): 0 < v3c_big < 2^33 nW. + * The result should be < 2^52 to avoid overflowing the return value. + */ + const u64 v3c_big = (u64) c * (u64) v3; + + /* Range: 0 < v3c_big / 1000000 < 2^13 mW */ + return v3c_big / 1000000; +} + +static struct kbase_ipa_model *get_current_model(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->ipa.lock); + + if (atomic_read(&kbdev->ipa_use_configured_model)) + return kbdev->ipa.configured_model; + else + return kbdev->ipa.fallback_model; +} + +static u32 get_static_power_locked(struct kbase_device *kbdev, + struct kbase_ipa_model *model, + unsigned long voltage) +{ + u32 power = 0; + int err; + u32 power_coeff; + + lockdep_assert_held(&model->kbdev->ipa.lock); + + if (!model->ops->get_static_coeff) + model = kbdev->ipa.fallback_model; + + if (model->ops->get_static_coeff) { + err = model->ops->get_static_coeff(model, &power_coeff); + if (!err) + power = kbase_scale_static_power(power_coeff, + (u32) voltage); + } + + return power; +} + +#ifdef CONFIG_MALI_PWRSOFT_765 +static unsigned long kbase_get_static_power(struct devfreq *df, + unsigned long voltage) +#else +static unsigned long kbase_get_static_power(unsigned long voltage) +#endif +{ + struct kbase_ipa_model *model; + u32 power = 0; +#ifdef CONFIG_MALI_PWRSOFT_765 + struct kbase_device *kbdev = dev_get_drvdata(&df->dev); +#else + struct kbase_device *kbdev = kbase_find_device(-1); +#endif + + mutex_lock(&kbdev->ipa.lock); + + model = get_current_model(kbdev); + power = get_static_power_locked(kbdev, model, voltage); + + mutex_unlock(&kbdev->ipa.lock); + +#ifndef CONFIG_MALI_PWRSOFT_765 + kbase_release_device(kbdev); +#endif + + return power; +} + +#ifdef CONFIG_MALI_PWRSOFT_765 +static unsigned long kbase_get_dynamic_power(struct devfreq *df, + unsigned long freq, + unsigned long voltage) +#else +static unsigned long kbase_get_dynamic_power(unsigned long freq, + unsigned long voltage) +#endif +{ + struct kbase_ipa_model *model; + u32 power_coeff = 0, power = 0; + int err = 0; +#ifdef CONFIG_MALI_PWRSOFT_765 + struct kbase_device *kbdev = dev_get_drvdata(&df->dev); +#else + struct kbase_device *kbdev = kbase_find_device(-1); +#endif + + mutex_lock(&kbdev->ipa.lock); + + model = kbdev->ipa.fallback_model; + + err = model->ops->get_dynamic_coeff(model, &power_coeff, freq); + + if (!err) + power = kbase_scale_dynamic_power(power_coeff, freq, voltage); + else + dev_err_ratelimited(kbdev->dev, + "Model %s returned error code %d\n", + model->ops->name, err); + + mutex_unlock(&kbdev->ipa.lock); + +#ifndef CONFIG_MALI_PWRSOFT_765 + kbase_release_device(kbdev); +#endif + + return power; +} + +int kbase_get_real_power(struct devfreq *df, u32 *power, + unsigned long freq, + unsigned long voltage) +{ + struct kbase_ipa_model *model; + u32 power_coeff = 0; + int err = 0; + struct kbase_device *kbdev = dev_get_drvdata(&df->dev); + + mutex_lock(&kbdev->ipa.lock); + + model = get_current_model(kbdev); + + err = model->ops->get_dynamic_coeff(model, &power_coeff, freq); + + /* If we switch to protected model between get_current_model() and + * get_dynamic_coeff(), counter reading could fail. If that happens + * (unlikely, but possible), revert to the fallback model. */ + if (err && model != kbdev->ipa.fallback_model) { + model = kbdev->ipa.fallback_model; + err = model->ops->get_dynamic_coeff(model, &power_coeff, freq); + } + + if (err) + goto exit_unlock; + + *power = kbase_scale_dynamic_power(power_coeff, freq, voltage); + + if (model->ops->do_utilization_scaling_in_framework) { + struct devfreq_dev_status *status = &df->last_status; + unsigned long total_time = max(status->total_time, 1ul); + u64 busy_time = min(status->busy_time, total_time); + + *power = ((u64) *power * (u64) busy_time) / total_time; + } + + *power += get_static_power_locked(kbdev, model, voltage); + +exit_unlock: + mutex_unlock(&kbdev->ipa.lock); + + return err; +} +KBASE_EXPORT_TEST_API(kbase_get_real_power); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) +struct devfreq_cooling_ops kbase_ipa_power_model_ops = { +#else +struct devfreq_cooling_power kbase_ipa_power_model_ops = { +#endif + .get_static_power = &kbase_get_static_power, + .get_dynamic_power = &kbase_get_dynamic_power, +#ifdef CONFIG_MALI_PWRSOFT_765 + .get_real_power = &kbase_get_real_power, +#endif +}; +KBASE_EXPORT_TEST_API(kbase_ipa_power_model_ops); diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h new file mode 100644 index 000000000000..469f33cbdcc6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h @@ -0,0 +1,165 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_IPA_H_ +#define _KBASE_IPA_H_ + +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) + +struct devfreq; + +struct kbase_ipa_model { + struct list_head link; + struct kbase_device *kbdev; + void *model_data; + struct kbase_ipa_model_ops *ops; + struct list_head params; + bool missing_dt_node_warning; +}; + +/** + * kbase_ipa_model_add_param_s32 - Add an integer model parameter + * @model: pointer to IPA model + * @name: name of corresponding debugfs entry + * @addr: address where the value is stored + * @num_elems: number of elements (1 if not an array) + * @dt_required: if false, a corresponding devicetree entry is not required, + * and the current value will be used. If true, a warning is + * output and the data is zeroed + * + * Return: 0 on success, or an error code + */ +int kbase_ipa_model_add_param_s32(struct kbase_ipa_model *model, + const char *name, s32 *addr, + size_t num_elems, bool dt_required); + +/** + * kbase_ipa_model_add_param_string - Add a string model parameter + * @model: pointer to IPA model + * @name: name of corresponding debugfs entry + * @addr: address where the value is stored + * @size: size, in bytes, of the value storage (so the maximum string + * length is size - 1) + * @dt_required: if false, a corresponding devicetree entry is not required, + * and the current value will be used. If true, a warning is + * output and the data is zeroed + * + * Return: 0 on success, or an error code + */ +int kbase_ipa_model_add_param_string(struct kbase_ipa_model *model, + const char *name, char *addr, + size_t size, bool dt_required); + +struct kbase_ipa_model_ops { + char *name; + /* The init, recalculate and term ops on the default model are always + * called. However, all the other models are only invoked if the model + * is selected in the device tree. Otherwise they are never + * initialized. Additional resources can be acquired by models in + * init(), however they must be terminated in the term(). + */ + int (*init)(struct kbase_ipa_model *model); + /* Called immediately after init(), or when a parameter is changed, so + * that any coefficients derived from model parameters can be + * recalculated. */ + int (*recalculate)(struct kbase_ipa_model *model); + void (*term)(struct kbase_ipa_model *model); + /* + * get_dynamic_coeff() - calculate dynamic power coefficient + * @model: pointer to model + * @coeffp: pointer to return value location + * @current_freq: frequency the GPU has been running at for the + * previous sampling period. + * + * Calculate a dynamic power coefficient, with units pW/(Hz V^2), which + * is then scaled by the IPA framework according to the current OPP's + * frequency and voltage. + * + * Return: 0 on success, or an error code. + */ + int (*get_dynamic_coeff)(struct kbase_ipa_model *model, u32 *coeffp, + u32 current_freq); + /* + * get_static_coeff() - calculate static power coefficient + * @model: pointer to model + * @coeffp: pointer to return value location + * + * Calculate a static power coefficient, with units uW/(V^3), which is + * scaled by the IPA framework according to the current OPP's voltage. + * + * Return: 0 on success, or an error code. + */ + int (*get_static_coeff)(struct kbase_ipa_model *model, u32 *coeffp); + /* If false, the model's get_dynamic_coeff() method accounts for how + * long the GPU was active over the sample period. If true, the + * framework will scale the calculated power according to the + * utilization stats recorded by devfreq in get_real_power(). */ + bool do_utilization_scaling_in_framework; +}; + +/* Models can be registered only in the platform's platform_init_func call */ +int kbase_ipa_model_ops_register(struct kbase_device *kbdev, + struct kbase_ipa_model_ops *new_model_ops); +struct kbase_ipa_model *kbase_ipa_get_model(struct kbase_device *kbdev, + const char *name); + +int kbase_ipa_init(struct kbase_device *kbdev); +void kbase_ipa_term(struct kbase_device *kbdev); +void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev); +void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev); +int kbase_ipa_model_recalculate(struct kbase_ipa_model *model); +struct kbase_ipa_model *kbase_ipa_init_model(struct kbase_device *kbdev, + struct kbase_ipa_model_ops *ops); +void kbase_ipa_term_model(struct kbase_ipa_model *model); + +extern struct kbase_ipa_model_ops kbase_g71_ipa_model_ops; + +#if MALI_UNIT_TEST +/** + * kbase_get_real_power() - get the real power consumption of the GPU + * @df: dynamic voltage and frequency scaling information for the GPU. + * @power: where to store the power consumption, in mW. + * @freq: a frequency, in HZ. + * @voltage: a voltage, in mV. + * + * This function is only exposed for use by unit tests. The returned value + * incorporates both static and dynamic power consumption. + * + * Return: 0 on success, or an error code. + */ +int kbase_get_real_power(struct devfreq *df, u32 *power, + unsigned long freq, + unsigned long voltage); +#endif /* MALI_UNIT_TEST */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) +extern struct devfreq_cooling_ops kbase_ipa_power_model_ops; +#else +extern struct devfreq_cooling_power kbase_ipa_power_model_ops; +#endif + +#else /* !(defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ + +static inline void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev) +{ } + +static inline void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev) +{ } + +#endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ + +#endif diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.c new file mode 100644 index 000000000000..eafc14009ddc --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.c @@ -0,0 +1,219 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include + +#include "mali_kbase.h" +#include "mali_kbase_ipa.h" +#include "mali_kbase_ipa_debugfs.h" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) +#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE +#endif + +struct kbase_ipa_model_param { + char *name; + union { + void *voidp; + s32 *s32p; + char *str; + } addr; + size_t size; + enum kbase_ipa_model_param_type type; + struct kbase_ipa_model *model; + struct list_head link; +}; + +static int param_int_get(void *data, u64 *val) +{ + struct kbase_ipa_model_param *param = data; + + mutex_lock(¶m->model->kbdev->ipa.lock); + *(s64 *) val = *param->addr.s32p; + mutex_unlock(¶m->model->kbdev->ipa.lock); + + return 0; +} + +static int param_int_set(void *data, u64 val) +{ + struct kbase_ipa_model_param *param = data; + struct kbase_ipa_model *model = param->model; + s64 sval = (s64) val; + int err = 0; + + if (sval < S32_MIN || sval > S32_MAX) + return -ERANGE; + + mutex_lock(¶m->model->kbdev->ipa.lock); + *param->addr.s32p = val; + err = kbase_ipa_model_recalculate(model); + mutex_unlock(¶m->model->kbdev->ipa.lock); + + return err; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, param_int_get, param_int_set, "%lld\n"); + +static ssize_t param_string_get(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct kbase_ipa_model_param *param = file->private_data; + ssize_t ret; + size_t len; + + mutex_lock(¶m->model->kbdev->ipa.lock); + len = strnlen(param->addr.str, param->size - 1) + 1; + ret = simple_read_from_buffer(user_buf, count, ppos, + param->addr.str, len); + mutex_unlock(¶m->model->kbdev->ipa.lock); + + return ret; +} + +static ssize_t param_string_set(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct kbase_ipa_model_param *param = file->private_data; + struct kbase_ipa_model *model = param->model; + ssize_t ret = count; + size_t buf_size; + int err; + + mutex_lock(&model->kbdev->ipa.lock); + + if (count > param->size) { + ret = -EINVAL; + goto end; + } + + buf_size = min(param->size - 1, count); + if (copy_from_user(param->addr.str, user_buf, buf_size)) { + ret = -EFAULT; + goto end; + } + + param->addr.str[buf_size] = '\0'; + + err = kbase_ipa_model_recalculate(model); + if (err < 0) + ret = err; + +end: + mutex_unlock(&model->kbdev->ipa.lock); + + return ret; +} + +static const struct file_operations fops_string = { + .read = param_string_get, + .write = param_string_set, + .open = simple_open, + .llseek = default_llseek, +}; + +int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name, + void *addr, size_t size, + enum kbase_ipa_model_param_type type) +{ + struct kbase_ipa_model_param *param; + + param = kzalloc(sizeof(*param), GFP_KERNEL); + + if (!param) + return -ENOMEM; + + /* 'name' is stack-allocated for array elements, so copy it into + * heap-allocated storage */ + param->name = kstrdup(name, GFP_KERNEL); + param->addr.voidp = addr; + param->size = size; + param->type = type; + param->model = model; + + list_add(¶m->link, &model->params); + + return 0; +} + +void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model) +{ + struct kbase_ipa_model_param *param_p, *param_n; + + list_for_each_entry_safe(param_p, param_n, &model->params, link) { + list_del(¶m_p->link); + kfree(param_p->name); + kfree(param_p); + } +} + +static void kbase_ipa_model_debugfs_init(struct kbase_ipa_model *model) +{ + struct list_head *it; + struct dentry *dir; + + lockdep_assert_held(&model->kbdev->ipa.lock); + + dir = debugfs_create_dir(model->ops->name, + model->kbdev->mali_debugfs_directory); + + if (!dir) { + dev_err(model->kbdev->dev, + "Couldn't create mali debugfs %s directory", + model->ops->name); + return; + } + + list_for_each(it, &model->params) { + struct kbase_ipa_model_param *param = + list_entry(it, + struct kbase_ipa_model_param, + link); + const struct file_operations *fops = NULL; + + switch (param->type) { + case PARAM_TYPE_S32: + fops = &fops_s32; + break; + case PARAM_TYPE_STRING: + fops = &fops_string; + break; + } + + if (unlikely(!fops)) { + dev_err(model->kbdev->dev, + "Type not set for %s parameter %s\n", + model->ops->name, param->name); + } else { + debugfs_create_file(param->name, S_IRUGO | S_IWUSR, + dir, param, fops); + } + } +} + +void kbase_ipa_debugfs_init(struct kbase_device *kbdev) +{ + mutex_lock(&kbdev->ipa.lock); + + if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model) + kbase_ipa_model_debugfs_init(kbdev->ipa.configured_model); + kbase_ipa_model_debugfs_init(kbdev->ipa.fallback_model); + + mutex_unlock(&kbdev->ipa.lock); +} diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.h new file mode 100644 index 000000000000..ec06e2096f94 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.h @@ -0,0 +1,49 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_IPA_DEBUGFS_H_ +#define _KBASE_IPA_DEBUGFS_H_ + +enum kbase_ipa_model_param_type { + PARAM_TYPE_S32 = 1, + PARAM_TYPE_STRING, +}; + +#ifdef CONFIG_DEBUG_FS + +void kbase_ipa_debugfs_init(struct kbase_device *kbdev); +int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name, + void *addr, size_t size, + enum kbase_ipa_model_param_type type); +void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model); + +#else /* CONFIG_DEBUG_FS */ + +static inline int kbase_ipa_model_param_add(struct kbase_ipa_model *model, + const char *name, void *addr, + size_t size, + enum kbase_ipa_model_param_type type) +{ + return 0; +} + +static inline void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model) +{ } + +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _KBASE_IPA_DEBUGFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c new file mode 100644 index 000000000000..de6c3e6ef7a8 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c @@ -0,0 +1,322 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#ifdef CONFIG_DEVFREQ_THERMAL +#include +#endif +#include +#include +#include + +#include "mali_kbase.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_ipa_simple.h" +#include "mali_kbase_ipa_debugfs.h" + +#if MALI_UNIT_TEST + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) +static unsigned long dummy_temp; + +static int kbase_simple_power_model_get_dummy_temp( + struct thermal_zone_device *tz, + unsigned long *temp) +{ + *temp = ACCESS_ONCE(dummy_temp); + return 0; +} + +#else +static int dummy_temp; + +static int kbase_simple_power_model_get_dummy_temp( + struct thermal_zone_device *tz, + int *dummy_temp) +{ + *temp = ACCESS_ONCE(dummy_temp); + return 0; +} +#endif + +/* Intercept calls to the kernel function using a macro */ +#ifdef thermal_zone_get_temp +#undef thermal_zone_get_temp +#endif +#define thermal_zone_get_temp(tz, temp) \ + kbase_simple_power_model_get_dummy_temp(tz, temp) + +void kbase_simple_power_model_set_dummy_temp(int temp) +{ + ACCESS_ONCE(dummy_temp) = temp; +} +KBASE_EXPORT_TEST_API(kbase_simple_power_model_set_dummy_temp); + +#endif /* MALI_UNIT_TEST */ + +/* + * This model is primarily designed for the Juno platform. It may not be + * suitable for other platforms. The additional resources in this model + * should preferably be minimal, as this model is rarely used when a dynamic + * model is available. + */ + +/** + * struct kbase_ipa_model_simple_data - IPA context per device + * @dynamic_coefficient: dynamic coefficient of the model + * @static_coefficient: static coefficient of the model + * @ts: Thermal scaling coefficients of the model + * @tz_name: Thermal zone name + * @gpu_tz: thermal zone device + * @poll_temperature_thread: Handle for temperature polling thread + * @current_temperature: Most recent value of polled temperature + * @temperature_poll_interval_ms: How often temperature should be checked, in ms + */ + +struct kbase_ipa_model_simple_data { + u32 dynamic_coefficient; + u32 static_coefficient; + s32 ts[4]; + char tz_name[16]; + struct thermal_zone_device *gpu_tz; + struct task_struct *poll_temperature_thread; + int current_temperature; + int temperature_poll_interval_ms; +}; +#define FALLBACK_STATIC_TEMPERATURE 55000 + +/** + * calculate_temp_scaling_factor() - Calculate temperature scaling coefficient + * @ts: Signed coefficients, in order t^0 to t^3, with units Deg^-N + * @t: Temperature, in mDeg C. Range: -2^17 < t < 2^17 + * + * Scale the temperature according to a cubic polynomial whose coefficients are + * provided in the device tree. The result is used to scale the static power + * coefficient, where 1000000 means no change. + * + * Return: Temperature scaling factor. Range 0 <= ret <= 10,000,000. + */ +static u32 calculate_temp_scaling_factor(s32 ts[4], s64 t) +{ + /* Range: -2^24 < t2 < 2^24 m(Deg^2) */ + const s64 t2 = (t * t) / 1000; + + /* Range: -2^31 < t3 < 2^31 m(Deg^3) */ + const s64 t3 = (t * t2) / 1000; + + /* + * Sum the parts. t^[1-3] are in m(Deg^N), but the coefficients are in + * Deg^-N, so we need to multiply the last coefficient by 1000. + * Range: -2^63 < res_big < 2^63 + */ + const s64 res_big = ts[3] * t3 /* +/- 2^62 */ + + ts[2] * t2 /* +/- 2^55 */ + + ts[1] * t /* +/- 2^48 */ + + ts[0] * 1000; /* +/- 2^41 */ + + /* Range: -2^60 < res_unclamped < 2^60 */ + s64 res_unclamped = res_big / 1000; + + /* Clamp to range of 0x to 10x the static power */ + return clamp(res_unclamped, (s64) 0, (s64) 10000000); +} + +/* We can't call thermal_zone_get_temp() directly in model_static_coeff(), + * because we don't know if tz->lock is held in the same thread. So poll it in + * a separate thread to get around this. */ +static int poll_temperature(void *data) +{ + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *) data; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) + unsigned long temp; +#else + int temp; +#endif + + while (!kthread_should_stop()) { + struct thermal_zone_device *tz = ACCESS_ONCE(model_data->gpu_tz); + + if (tz) { + int ret; + + ret = thermal_zone_get_temp(tz, &temp); + if (ret) { + pr_warn_ratelimited("Error reading temperature for gpu thermal zone: %d\n", + ret); + temp = FALLBACK_STATIC_TEMPERATURE; + } + } else { + temp = FALLBACK_STATIC_TEMPERATURE; + } + + ACCESS_ONCE(model_data->current_temperature) = temp; + + msleep_interruptible(ACCESS_ONCE(model_data->temperature_poll_interval_ms)); + } + + return 0; +} + +static int model_static_coeff(struct kbase_ipa_model *model, u32 *coeffp) +{ + u32 temp_scaling_factor; + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *) model->model_data; + u64 coeff_big; + int temp; + + temp = ACCESS_ONCE(model_data->current_temperature); + + /* Range: 0 <= temp_scaling_factor < 2^24 */ + temp_scaling_factor = calculate_temp_scaling_factor(model_data->ts, + temp); + + /* + * Range: 0 <= coeff_big < 2^52 to avoid overflowing *coeffp. This + * means static_coefficient must be in range + * 0 <= static_coefficient < 2^28. + */ + coeff_big = (u64) model_data->static_coefficient * (u64) temp_scaling_factor; + *coeffp = coeff_big / 1000000; + + return 0; +} + +static int model_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp, + u32 current_freq) +{ + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *) model->model_data; + + *coeffp = model_data->dynamic_coefficient; + + return 0; +} + +static int add_params(struct kbase_ipa_model *model) +{ + int err = 0; + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *)model->model_data; + + err = kbase_ipa_model_add_param_s32(model, "static-coefficient", + &model_data->static_coefficient, + 1, true); + if (err) + goto end; + + err = kbase_ipa_model_add_param_s32(model, "dynamic-coefficient", + &model_data->dynamic_coefficient, + 1, true); + if (err) + goto end; + + err = kbase_ipa_model_add_param_s32(model, "ts", + model_data->ts, 4, true); + if (err) + goto end; + + err = kbase_ipa_model_add_param_string(model, "thermal-zone", + model_data->tz_name, + sizeof(model_data->tz_name), true); + if (err) + goto end; + + model_data->temperature_poll_interval_ms = 200; + err = kbase_ipa_model_add_param_s32(model, "temp-poll-interval-ms", + &model_data->temperature_poll_interval_ms, + 1, false); + +end: + return err; +} + +static int kbase_simple_power_model_init(struct kbase_ipa_model *model) +{ + int err; + struct kbase_ipa_model_simple_data *model_data; + + model_data = kzalloc(sizeof(struct kbase_ipa_model_simple_data), + GFP_KERNEL); + if (!model_data) + return -ENOMEM; + + model->model_data = (void *) model_data; + + model_data->current_temperature = FALLBACK_STATIC_TEMPERATURE; + model_data->poll_temperature_thread = kthread_run(poll_temperature, + (void *) model_data, + "mali-simple-power-model-temp-poll"); + if (IS_ERR(model_data->poll_temperature_thread)) { + kfree(model_data); + return PTR_ERR(model_data->poll_temperature_thread); + } + + err = add_params(model); + if (err) { + kbase_ipa_model_param_free_all(model); + kthread_stop(model_data->poll_temperature_thread); + kfree(model_data); + } + + return err; +} + +static int kbase_simple_power_model_recalculate(struct kbase_ipa_model *model) +{ + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *)model->model_data; + struct thermal_zone_device *tz; + + if (!strnlen(model_data->tz_name, sizeof(model_data->tz_name))) { + tz = NULL; + } else { + tz = thermal_zone_get_zone_by_name(model_data->tz_name); + + if (IS_ERR_OR_NULL(tz)) { + pr_warn_ratelimited("Error %ld getting thermal zone \'%s\', not yet ready?\n", + PTR_ERR(tz), model_data->tz_name); + tz = NULL; + return -EPROBE_DEFER; + } + } + + ACCESS_ONCE(model_data->gpu_tz) = tz; + + return 0; +} + +static void kbase_simple_power_model_term(struct kbase_ipa_model *model) +{ + struct kbase_ipa_model_simple_data *model_data = + (struct kbase_ipa_model_simple_data *)model->model_data; + + kthread_stop(model_data->poll_temperature_thread); + + kfree(model_data); +} + +struct kbase_ipa_model_ops kbase_simple_ipa_model_ops = { + .name = "mali-simple-power-model", + .init = &kbase_simple_power_model_init, + .recalculate = &kbase_simple_power_model_recalculate, + .term = &kbase_simple_power_model_term, + .get_dynamic_coeff = &model_dynamic_coeff, + .get_static_coeff = &model_static_coeff, + .do_utilization_scaling_in_framework = true, +}; diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h new file mode 100644 index 000000000000..e78d6173300b --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_IPA_SIMPLE_H_ +#define _KBASE_IPA_SIMPLE_H_ + +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) + +extern struct kbase_ipa_model_ops kbase_simple_ipa_model_ops; + +#if MALI_UNIT_TEST +/** + * kbase_simple_power_model_set_dummy_temp() - set a dummy temperature value + * @temp: Temperature of the thermal zone, in millidegrees celsius. + * + * This is only intended for use in unit tests, to ensure that the temperature + * values used by the simple power model are predictable. Deterministic + * behavior is necessary to allow validation of the static power values + * computed by this model. + */ +void kbase_simple_power_model_set_dummy_temp(int temp); +#endif /* MALI_UNIT_TEST */ + +#endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ + +#endif /* _KBASE_IPA_SIMPLE_H_ */ diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.c new file mode 100644 index 000000000000..d3964d0d3c73 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.c @@ -0,0 +1,217 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase_ipa_vinstr_common.h" + +#if MALI_UNIT_TEST +static ktime_t dummy_time; + +/* Intercept calls to the kernel function using a macro */ +#ifdef ktime_get +#undef ktime_get +#endif +#define ktime_get() (ACCESS_ONCE(dummy_time)) + +void kbase_ipa_set_dummy_time(ktime_t t) +{ + ACCESS_ONCE(dummy_time) = t; +} +KBASE_EXPORT_TEST_API(kbase_ipa_set_dummy_time); + +#endif /* MALI_UNIT_TEST */ + +/** + * read_hwcnt() - read a counter value + * @model_data: pointer to model data + * @offset: offset, in bytes, into vinstr buffer + * + * Return: A 32-bit counter value. Range: 0 < value < 2^27 (worst case would be + * incrementing every cycle over a ~100ms sample period at a high frequency, + * e.g. 1 GHz: 2^30 * 0.1seconds ~= 2^27. + */ +static inline u32 kbase_ipa_read_hwcnt( + struct kbase_ipa_model_vinstr_data *model_data, + u32 offset) +{ + u8 *p = model_data->vinstr_buffer; + + return *(u32 *)&p[offset]; +} + +static inline s64 kbase_ipa_add_saturate(s64 a, s64 b) +{ + if (S64_MAX - a < b) + return S64_MAX; + return a + b; +} + +s64 kbase_ipa_sum_all_shader_cores( + struct kbase_ipa_model_vinstr_data *model_data, + s32 coeff, u32 counter) +{ + struct kbase_device *kbdev = model_data->kbdev; + u64 core_mask; + u32 base = 0; + s64 ret = 0; + + core_mask = kbdev->gpu_props.props.coherency_info.group[0].core_mask; + while (core_mask != 0ull) { + if ((core_mask & 1ull) != 0ull) { + /* 0 < counter_value < 2^27 */ + u32 counter_value = kbase_ipa_read_hwcnt(model_data, + base + counter); + + /* 0 < ret < 2^27 * max_num_cores = 2^32 */ + ret = kbase_ipa_add_saturate(ret, counter_value); + } + base += KBASE_IPA_NR_BYTES_PER_BLOCK; + core_mask >>= 1; + } + + /* Range: -2^54 < ret < 2^54 */ + ret *= coeff; + + return ret / 1000000; +} + +s64 kbase_ipa_single_counter( + struct kbase_ipa_model_vinstr_data *model_data, + s32 coeff, u32 counter) +{ + /* Range: 0 < counter_value < 2^27 */ + const u32 counter_value = kbase_ipa_read_hwcnt(model_data, counter); + + /* Range: -2^49 < ret < 2^49 */ + const s64 multiplied = (s64) counter_value * (s64) coeff; + + /* Range: -2^29 < return < 2^29 */ + return multiplied / 1000000; +} + +int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data) +{ + struct kbase_device *kbdev = model_data->kbdev; + struct kbase_uk_hwcnt_reader_setup setup; + size_t dump_size; + + dump_size = kbase_vinstr_dump_size(kbdev); + model_data->vinstr_buffer = kzalloc(dump_size, GFP_KERNEL); + if (!model_data->vinstr_buffer) { + dev_err(kbdev->dev, "Failed to allocate IPA dump buffer"); + return -1; + } + + setup.jm_bm = ~0u; + setup.shader_bm = ~0u; + setup.tiler_bm = ~0u; + setup.mmu_l2_bm = ~0u; + model_data->vinstr_cli = kbase_vinstr_hwcnt_kernel_setup(kbdev->vinstr_ctx, + &setup, model_data->vinstr_buffer); + if (!model_data->vinstr_cli) { + dev_err(kbdev->dev, "Failed to register IPA with vinstr core"); + kfree(model_data->vinstr_buffer); + model_data->vinstr_buffer = NULL; + return -1; + } + + model_data->last_sample_read_time = ktime_get(); + kbase_vinstr_hwc_clear(model_data->vinstr_cli); + + return 0; +} + +void kbase_ipa_detach_vinstr(struct kbase_ipa_model_vinstr_data *model_data) +{ + if (model_data->vinstr_cli) + kbase_vinstr_detach_client(model_data->vinstr_cli); + model_data->vinstr_cli = NULL; + kfree(model_data->vinstr_buffer); + model_data->vinstr_buffer = NULL; +} + +int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp, + u32 current_freq) +{ + struct kbase_ipa_model_vinstr_data *model_data = + (struct kbase_ipa_model_vinstr_data *)model->model_data; + s64 energy = 0; + size_t i; + ktime_t now = ktime_get(); + ktime_t time_since_last_sample = + ktime_sub(now, model_data->last_sample_read_time); + /* Range: 2^0 < time_since_last_sample_ms < 2^10 (1-1000ms) */ + s64 time_since_last_sample_ms = ktime_to_ms(time_since_last_sample); + u64 coeff = 0; + u64 num_cycles; + int err = 0; + + err = kbase_vinstr_hwc_dump(model_data->vinstr_cli, + BASE_HWCNT_READER_EVENT_MANUAL); + if (err) + goto err0; + + model_data->last_sample_read_time = now; + + /* Range of 'energy' is +/- 2^34 * number of IPA groups, so around + * -2^38 < energy < 2^38 */ + for (i = 0; i < model_data->groups_def_num; i++) { + const struct kbase_ipa_group *group = &model_data->groups_def[i]; + s32 coeff, group_energy; + + coeff = model_data->group_values[i]; + group_energy = group->op(model_data, coeff, group->counter); + + energy = kbase_ipa_add_saturate(energy, group_energy); + } + + /* Range: 0 <= coeff < 2^38 */ + if (energy > 0) + coeff = energy; + + /* Scale by user-specified factor and divide by 1000. But actually + * cancel the division out, because we want the num_cycles in KHz and + * don't want to lose precision. */ + + /* Range: 0 < coeff < 2^53 */ + coeff = coeff * model_data->scaling_factor; + + if (time_since_last_sample_ms == 0) { + time_since_last_sample_ms = 1; + } else if (time_since_last_sample_ms < 0) { + err = -ERANGE; + goto err0; + } + + /* Range: 2^20 < num_cycles < 2^40 mCycles */ + num_cycles = (u64) current_freq * (u64) time_since_last_sample_ms; + /* Range: 2^10 < num_cycles < 2^30 Cycles */ + num_cycles /= 1000000; + + /* num_cycles should never be 0 in _normal_ usage (because we expect + * frequencies on the order of MHz and >10ms polling intervals), but + * protect against divide-by-zero anyway. */ + if (num_cycles == 0) + num_cycles = 1; + + /* Range: 0 < coeff < 2^43 */ + coeff = div_u64(coeff, num_cycles); + +err0: + /* Clamp to a sensible range - 2^16 gives about 14W at 400MHz/750mV */ + *coeffp = clamp(coeff, (u64) 0, (u64) 1 << 16); + return err; +} diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.h new file mode 100644 index 000000000000..25b36c8e3089 --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_common.h @@ -0,0 +1,161 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_IPA_VINSTR_COMMON_H_ +#define _KBASE_IPA_VINSTR_COMMON_H_ + +#include "mali_kbase.h" + +/* Maximum length for the name of an IPA group. */ +#define KBASE_IPA_MAX_GROUP_NAME_LEN 15 + +/* Maximum number of IPA groups for an IPA model. */ +#define KBASE_IPA_MAX_GROUP_DEF_NUM 16 + +/* Number of bytes per hardware counter in a vinstr_buffer. */ +#define KBASE_IPA_NR_BYTES_PER_CNT 4 + +/* Number of hardware counters per block in a vinstr_buffer. */ +#define KBASE_IPA_NR_CNT_PER_BLOCK 64 + +/* Number of bytes per block in a vinstr_buffer. */ +#define KBASE_IPA_NR_BYTES_PER_BLOCK \ + (KBASE_IPA_NR_CNT_PER_BLOCK * KBASE_IPA_NR_BYTES_PER_CNT) + + + +/** + * struct kbase_ipa_model_vinstr_data - IPA context per device + * @kbdev: pointer to kbase device + * @groups_def: Array of IPA groups. + * @groups_def_num: Number of elements in the array of IPA groups. + * @vinstr_cli: vinstr client handle + * @vinstr_buffer: buffer to dump hardware counters onto + * @last_sample_read_time: timestamp of last vinstr buffer read + * @scaling_factor: user-specified power scaling factor. This is + * interpreted as a fraction where the denominator is + * 1000. Range approx 0.0-32.0: + * 0 < scaling_factor < 2^15 + */ +struct kbase_ipa_model_vinstr_data { + struct kbase_device *kbdev; + s32 group_values[KBASE_IPA_MAX_GROUP_DEF_NUM]; + const struct kbase_ipa_group *groups_def; + size_t groups_def_num; + struct kbase_vinstr_client *vinstr_cli; + void *vinstr_buffer; + ktime_t last_sample_read_time; + s32 scaling_factor; +}; + +/** + * struct ipa_group - represents a single IPA group + * @name: name of the IPA group + * @default_value: default value of coefficient for IPA group. + * Coefficients are interpreted as fractions where the + * denominator is 1000000. + * @op: which operation to be performed on the counter values + * @counter: counter used to calculate energy for IPA group + */ +struct kbase_ipa_group { + char name[KBASE_IPA_MAX_GROUP_NAME_LEN + 1]; + s32 default_value; + s64 (*op)(struct kbase_ipa_model_vinstr_data *, s32, u32); + u32 counter; +}; + +/* + * sum_all_shader_cores() - sum a counter over all cores + * @model_data pointer to model data + * @coeff model coefficient. Unity is ~2^20, so range approx + * +/- 4.0: -2^22 < coeff < 2^22 + + * Calculate energy estimation based on hardware counter `counter' + * across all shader cores. + * + * Return: Sum of counter values. Range: -2^34 < ret < 2^34 + */ +s64 kbase_ipa_sum_all_shader_cores( + struct kbase_ipa_model_vinstr_data *model_data, + s32 coeff, u32 counter); + +/* + * sum_single_counter() - sum a single counter + * @model_data pointer to model data + * @coeff model coefficient. Unity is ~2^20, so range approx + * +/- 4.0: -2^22 < coeff < 2^22 + + * Calculate energy estimation based on hardware counter `counter'. + * + * Return: Counter value. Range: -2^34 < ret < 2^34 + */ +s64 kbase_ipa_single_counter( + struct kbase_ipa_model_vinstr_data *model_data, + s32 coeff, u32 counter); + +/* + * attach_vinstr() - attach a vinstr_buffer to an IPA model. + * @model_data pointer to model data + * + * Attach a vinstr_buffer to an IPA model. The vinstr_buffer + * allows access to the hardware counters used to calculate + * energy consumption. + * + * Return: 0 on success, or an error code. + */ +int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data); + +/* + * detach_vinstr() - detach a vinstr_buffer from an IPA model. + * @model_data pointer to model data + * + * Detach a vinstr_buffer from an IPA model. + */ +void kbase_ipa_detach_vinstr(struct kbase_ipa_model_vinstr_data *model_data); + +/** + * kbase_ipa_vinstr_dynamic_coeff() - calculate dynamic power based on HW counters + * @model: pointer to instantiated model + * @coeffp: pointer to location where calculated power, in + * pW/(Hz V^2), is stored. + * @current_freq: frequency the GPU has been running at over the sample + * period. In Hz. Range: 10 MHz < 1GHz, + * 2^20 < current_freq < 2^30 + * + * This is a GPU-agnostic implementation of the get_dynamic_coeff() + * function of an IPA model. It relies on the model being populated + * with GPU-specific attributes at initialization time. + * + * Return: 0 on success, or an error code. + */ +int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp, + u32 current_freq); + +#if MALI_UNIT_TEST +/** + * kbase_ipa_set_dummy_time() - set a dummy monotonic time value + * @t: a monotonic time value + * + * This is only intended for use in unit tests, to ensure that the kernel time + * values used by a power model are predictable. Deterministic behavior is + * necessary to allow validation of the dynamic power values computed by the + * model. + */ +void kbase_ipa_set_dummy_time(ktime_t t); +#endif /* MALI_UNIT_TEST */ + +#endif /* _KBASE_IPA_VINSTR_COMMON_H_ */ diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_g71.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_g71.c new file mode 100644 index 000000000000..81f6fddbd79b --- /dev/null +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_vinstr_g71.c @@ -0,0 +1,136 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include + +#include "mali_kbase_ipa_vinstr_common.h" +#include "mali_kbase.h" +#include "mali_kbase_ipa_debugfs.h" + + +#define JM_BASE (0 * KBASE_IPA_NR_BYTES_PER_BLOCK) +#define TILER_BASE (1 * KBASE_IPA_NR_BYTES_PER_BLOCK) +#define MMU_BASE (2 * KBASE_IPA_NR_BYTES_PER_BLOCK) +#define SC0_BASE (3 * KBASE_IPA_NR_BYTES_PER_BLOCK) + +#define GPU_ACTIVE (JM_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 6) +#define TILER_ACTIVE (TILER_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 45) +#define L2_ANY_LOOKUP (MMU_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 25) +#define FRAG_ACTIVE (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 4) +#define EXEC_CORE_ACTIVE (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 26) +#define EXEC_INSTR_COUNT (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 28) +#define TEX_COORD_ISSUE (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 40) +#define VARY_SLOT_32 (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 50) +#define VARY_SLOT_16 (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 51) +#define BEATS_RD_LSC (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 56) +#define BEATS_WR_LSC (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 61) +#define BEATS_WR_TIB (SC0_BASE + KBASE_IPA_NR_BYTES_PER_CNT * 62) + +static const struct kbase_ipa_group ipa_groups_def[] = { + { + .name = "l2_access", + .default_value = 526300, + .op = kbase_ipa_single_counter, + .counter = L2_ANY_LOOKUP, + }, + { + .name = "exec_instr_count", + .default_value = 301100, + .op = kbase_ipa_sum_all_shader_cores, + .counter = EXEC_INSTR_COUNT, + }, + { + .name = "tex_issue", + .default_value = 197400, + .op = kbase_ipa_sum_all_shader_cores, + .counter = TEX_COORD_ISSUE, + }, + { + .name = "tile_wb", + .default_value = -156400, + .op = kbase_ipa_sum_all_shader_cores, + .counter = BEATS_WR_TIB, + }, + { + .name = "gpu_active", + .default_value = 115800, + .op = kbase_ipa_single_counter, + .counter = GPU_ACTIVE, + }, +}; + +static int kbase_g71_power_model_init(struct kbase_ipa_model *model) +{ + int i, err = 0; + struct kbase_ipa_model_vinstr_data *model_data; + + model_data = kzalloc(sizeof(*model_data), GFP_KERNEL); + if (!model_data) + return -ENOMEM; + + model_data->kbdev = model->kbdev; + model_data->groups_def = ipa_groups_def; + BUILD_BUG_ON(ARRAY_SIZE(ipa_groups_def) > KBASE_IPA_MAX_GROUP_DEF_NUM); + model_data->groups_def_num = ARRAY_SIZE(ipa_groups_def); + + model->model_data = (void *) model_data; + + for (i = 0; i < ARRAY_SIZE(ipa_groups_def); ++i) { + const struct kbase_ipa_group *group = &ipa_groups_def[i]; + + model_data->group_values[i] = group->default_value; + err = kbase_ipa_model_add_param_s32(model, group->name, + &model_data->group_values[i], + 1, false); + if (err) + goto exit; + } + + model_data->scaling_factor = 15000; + err = kbase_ipa_model_add_param_s32(model, "scale", + &model_data->scaling_factor, + 1, false); + if (err) + goto exit; + + err = kbase_ipa_attach_vinstr(model_data); + +exit: + if (err) { + kbase_ipa_model_param_free_all(model); + kfree(model_data); + } + return err; +} + +static void kbase_g71_power_model_term(struct kbase_ipa_model *model) +{ + struct kbase_ipa_model_vinstr_data *model_data = + (struct kbase_ipa_model_vinstr_data *)model->model_data; + + kbase_ipa_detach_vinstr(model_data); + kfree(model_data); +} + + +struct kbase_ipa_model_ops kbase_g71_ipa_model_ops = { + .name = "mali-g71-power-model", + .init = kbase_g71_power_model_init, + .term = kbase_g71_power_model_term, + .get_dynamic_coeff = kbase_ipa_vinstr_dynamic_coeff, + .do_utilization_scaling_in_framework = false, +}; +KBASE_EXPORT_TEST_API(kbase_g71_ipa_model_ops); diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h new file mode 100644 index 000000000000..219586d4d2da --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h @@ -0,0 +1,282 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update base/tools/hwconfig_generator/hwc_{issues,features}.py + * For more information see base/tools/hwconfig_generator/README + */ + +#ifndef _BASE_HWCONFIG_FEATURES_H_ +#define _BASE_HWCONFIG_FEATURES_H_ + +enum base_hw_feature { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_IMAGES_IN_FRAGMENT_SHADERS, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_V4, + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_MODE, + BASE_HW_FEATURE_COHERENCY_REG, + BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, + BASE_HW_FEATURE_AARCH64_MMU, + BASE_HW_FEATURE_TLS_HASHING, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_generic[] = { + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t60x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_V4, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t62x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_V4, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t72x[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_V4, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t76x[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tFxx[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t83x[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t82x[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tMIx[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_MODE, + BASE_HW_FEATURE_COHERENCY_REG, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tHEx[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_MODE, + BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, + BASE_HW_FEATURE_COHERENCY_REG, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tSIx[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_MODE, + BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, + BASE_HW_FEATURE_COHERENCY_REG, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tDVx[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_XAFFINITY, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_MODE, + BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, + BASE_HW_FEATURE_COHERENCY_REG, + BASE_HW_FEATURE_END +}; + + + + + +#endif /* _BASE_HWCONFIG_FEATURES_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h new file mode 100644 index 000000000000..1c5ee496ac85 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h @@ -0,0 +1,1126 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update base/tools/hwconfig_generator/hwc_{issues,features}.py + * For more information see base/tools/hwconfig_generator/README + */ + +#ifndef _BASE_HWCONFIG_ISSUES_H_ +#define _BASE_HWCONFIG_ISSUES_H_ + +enum base_hw_issue { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8879, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_7940, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TMIX_8138, + BASE_HW_ISSUE_TMIX_8206, + BASE_HW_ISSUE_TMIX_8343, + BASE_HW_ISSUE_TMIX_8463, + BASE_HW_ISSUE_TMIX_8456, + GPUCORE_1619, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_generic[] = { + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_15dev0[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_3964, + GPUCORE_1619, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_eac[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p1[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r0p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1_50rel0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p2[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p3[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r0p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t72x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t76x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t60x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t62x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3964, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r0p2[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r2p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tFRx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r0p2[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r2p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t86x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t83x_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t83x_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t83x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + GPUCORE_1619, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t82x_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3964, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t82x_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1909, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t82x_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T720_1386, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t82x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11051, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3979, + BASE_HW_ISSUE_TMIX_7891, + GPUCORE_1619, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tMIx_r0p0_05dev0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TMIX_8138, + BASE_HW_ISSUE_TMIX_8206, + BASE_HW_ISSUE_TMIX_8343, + BASE_HW_ISSUE_TMIX_8463, + BASE_HW_ISSUE_TMIX_8456, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tMIx_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_7940, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TMIX_8138, + BASE_HW_ISSUE_TMIX_8206, + BASE_HW_ISSUE_TMIX_8343, + BASE_HW_ISSUE_TMIX_8463, + BASE_HW_ISSUE_TMIX_8456, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tMIx_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_7940, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TMIX_8138, + BASE_HW_ISSUE_TMIX_8206, + BASE_HW_ISSUE_TMIX_8343, + BASE_HW_ISSUE_TMIX_8463, + BASE_HW_ISSUE_TMIX_8456, + BASE_HW_ISSUE_TMIX_8438, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tMIx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_7940, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TMIX_8138, + BASE_HW_ISSUE_TMIX_8206, + BASE_HW_ISSUE_TMIX_8343, + BASE_HW_ISSUE_TMIX_8456, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tHEx_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tHEx_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tHEx_r0p2[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tHEx_r0p3[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tHEx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TMIX_7891, + BASE_HW_ISSUE_TMIX_8042, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tSIx_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tSIx_r0p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tSIx_r1p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tSIx_r1p1[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tSIx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tDVx_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11054, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tDVx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TMIX_8133, + BASE_HW_ISSUE_TSIX_1116, + BASE_HW_ISSUE_END +}; + + + + + + + + + +#endif /* _BASE_HWCONFIG_ISSUES_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_base_kernel.h b/drivers/gpu/arm/bifrost/mali_base_kernel.h new file mode 100644 index 000000000000..6f5c68e288cd --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_base_kernel.h @@ -0,0 +1,1822 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base structures shared with the kernel. + */ + +#ifndef _BASE_KERNEL_H_ +#define _BASE_KERNEL_H_ + +/* Support UK10_2 IOCTLS */ +#define BASE_LEGACY_UK10_2_SUPPORT 1 + +/* Support UK10_4 IOCTLS */ +#define BASE_LEGACY_UK10_4_SUPPORT 1 + +typedef struct base_mem_handle { + struct { + u64 handle; + } basep; +} base_mem_handle; + +#include "mali_base_mem_priv.h" +#include "mali_kbase_profiling_gator_api.h" +#include "mali_midg_coherency.h" +#include "mali_kbase_gpu_id.h" + +/* + * Dependency stuff, keep it private for now. May want to expose it if + * we decide to make the number of semaphores a configurable + * option. + */ +#define BASE_JD_ATOM_COUNT 256 + +/* Set/reset values for a software event */ +#define BASE_JD_SOFT_EVENT_SET ((unsigned char)1) +#define BASE_JD_SOFT_EVENT_RESET ((unsigned char)0) + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +#if defined CDBG_ASSERT +#define LOCAL_ASSERT CDBG_ASSERT +#elif defined KBASE_DEBUG_ASSERT +#define LOCAL_ASSERT KBASE_DEBUG_ASSERT +#else +#error assert macro not defined! +#endif + +#if defined PAGE_MASK +#define LOCAL_PAGE_LSB ~PAGE_MASK +#else +#include + +#if defined OSU_CONFIG_CPU_PAGE_SIZE_LOG2 +#define LOCAL_PAGE_LSB ((1ul << OSU_CONFIG_CPU_PAGE_SIZE_LOG2) - 1) +#else +#error Failed to find page size +#endif +#endif + +/** + * @addtogroup base_user_api User-side Base APIs + * @{ + */ + +/** + * @addtogroup base_user_api_memory User-side Base Memory APIs + * @{ + */ + +/** + * typedef base_mem_alloc_flags - Memory allocation, access/hint flags. + * + * A combination of MEM_PROT/MEM_HINT flags must be passed to each allocator + * in order to determine the best cache policy. Some combinations are + * of course invalid (e.g. MEM_PROT_CPU_WR | MEM_HINT_CPU_RD), + * which defines a write-only region on the CPU side, which is + * heavily read by the CPU... + * Other flags are only meaningful to a particular allocator. + * More flags can be added to this list, as long as they don't clash + * (see BASE_MEM_FLAGS_NR_BITS for the number of the first free bit). + */ +typedef u32 base_mem_alloc_flags; + +/* Memory allocation, access/hint flags. + * + * See base_mem_alloc_flags. + */ + +/* IN */ +/* Read access CPU side + */ +#define BASE_MEM_PROT_CPU_RD ((base_mem_alloc_flags)1 << 0) + +/* Write access CPU side + */ +#define BASE_MEM_PROT_CPU_WR ((base_mem_alloc_flags)1 << 1) + +/* Read access GPU side + */ +#define BASE_MEM_PROT_GPU_RD ((base_mem_alloc_flags)1 << 2) + +/* Write access GPU side + */ +#define BASE_MEM_PROT_GPU_WR ((base_mem_alloc_flags)1 << 3) + +/* Execute allowed on the GPU side + */ +#define BASE_MEM_PROT_GPU_EX ((base_mem_alloc_flags)1 << 4) + + /* BASE_MEM_HINT flags have been removed, but their values are reserved + * for backwards compatibility with older user-space drivers. The values + * can be re-used once support for r5p0 user-space drivers is removed, + * presumably in r7p0. + * + * RESERVED: (1U << 5) + * RESERVED: (1U << 6) + * RESERVED: (1U << 7) + * RESERVED: (1U << 8) + */ + +/* Grow backing store on GPU Page Fault + */ +#define BASE_MEM_GROW_ON_GPF ((base_mem_alloc_flags)1 << 9) + +/* Page coherence Outer shareable, if available + */ +#define BASE_MEM_COHERENT_SYSTEM ((base_mem_alloc_flags)1 << 10) + +/* Page coherence Inner shareable + */ +#define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11) + +/* Should be cached on the CPU + */ +#define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12) + +/* IN/OUT */ +/* Must have same VA on both the GPU and the CPU + */ +#define BASE_MEM_SAME_VA ((base_mem_alloc_flags)1 << 13) + +/* OUT */ +/* Must call mmap to acquire a GPU address for the alloc + */ +#define BASE_MEM_NEED_MMAP ((base_mem_alloc_flags)1 << 14) + +/* IN */ +/* Page coherence Outer shareable, required. + */ +#define BASE_MEM_COHERENT_SYSTEM_REQUIRED ((base_mem_alloc_flags)1 << 15) + +/* Secure memory + */ +#define BASE_MEM_SECURE ((base_mem_alloc_flags)1 << 16) + +/* Not needed physical memory + */ +#define BASE_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 17) + +/* Must use shared CPU/GPU zone (SAME_VA zone) but doesn't require the + * addresses to be the same + */ +#define BASE_MEM_IMPORT_SHARED ((base_mem_alloc_flags)1 << 18) + +/** + * Bit 19 is reserved. + * + * Do not remove, use the next unreserved bit for new flags + **/ +#define BASE_MEM_RESERVED_BIT_19 ((base_mem_alloc_flags)1 << 19) + +/* Number of bits used as flags for base memory management + * + * Must be kept in sync with the base_mem_alloc_flags flags + */ +#define BASE_MEM_FLAGS_NR_BITS 20 + +/* A mask for all output bits, excluding IN/OUT bits. + */ +#define BASE_MEM_FLAGS_OUTPUT_MASK BASE_MEM_NEED_MMAP + +/* A mask for all input bits, including IN/OUT bits. + */ +#define BASE_MEM_FLAGS_INPUT_MASK \ + (((1 << BASE_MEM_FLAGS_NR_BITS) - 1) & ~BASE_MEM_FLAGS_OUTPUT_MASK) + +/* A mask for all the flags which are modifiable via the base_mem_set_flags + * interface. + */ +#define BASE_MEM_FLAGS_MODIFIABLE \ + (BASE_MEM_DONT_NEED | BASE_MEM_COHERENT_SYSTEM | \ + BASE_MEM_COHERENT_LOCAL) + +/** + * enum base_mem_import_type - Memory types supported by @a base_mem_import + * + * @BASE_MEM_IMPORT_TYPE_INVALID: Invalid type + * @BASE_MEM_IMPORT_TYPE_UMP: UMP import. Handle type is ump_secure_id. + * @BASE_MEM_IMPORT_TYPE_UMM: UMM import. Handle type is a file descriptor (int) + * @BASE_MEM_IMPORT_TYPE_USER_BUFFER: User buffer import. Handle is a + * base_mem_import_user_buffer + * + * Each type defines what the supported handle type is. + * + * If any new type is added here ARM must be contacted + * to allocate a numeric value for it. + * Do not just add a new type without synchronizing with ARM + * as future releases from ARM might include other new types + * which could clash with your custom types. + */ +typedef enum base_mem_import_type { + BASE_MEM_IMPORT_TYPE_INVALID = 0, + BASE_MEM_IMPORT_TYPE_UMP = 1, + BASE_MEM_IMPORT_TYPE_UMM = 2, + BASE_MEM_IMPORT_TYPE_USER_BUFFER = 3 +} base_mem_import_type; + +/** + * struct base_mem_import_user_buffer - Handle of an imported user buffer + * + * @ptr: address of imported user buffer + * @length: length of imported user buffer in bytes + * + * This structure is used to represent a handle of an imported user buffer. + */ + +struct base_mem_import_user_buffer { + u64 ptr; + u64 length; +}; + +/** + * @brief Invalid memory handle. + * + * Return value from functions returning @ref base_mem_handle on error. + * + * @warning @ref base_mem_handle_new_invalid must be used instead of this macro + * in C++ code or other situations where compound literals cannot be used. + */ +#define BASE_MEM_INVALID_HANDLE ((base_mem_handle) { {BASEP_MEM_INVALID_HANDLE} }) + +/** + * @brief Special write-alloc memory handle. + * + * A special handle is used to represent a region where a special page is mapped + * with a write-alloc cache setup, typically used when the write result of the + * GPU isn't needed, but the GPU must write anyway. + * + * @warning @ref base_mem_handle_new_write_alloc must be used instead of this macro + * in C++ code or other situations where compound literals cannot be used. + */ +#define BASE_MEM_WRITE_ALLOC_PAGES_HANDLE ((base_mem_handle) { {BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE} }) + +#define BASEP_MEM_INVALID_HANDLE (0ull << 12) +#define BASE_MEM_MMU_DUMP_HANDLE (1ull << 12) +#define BASE_MEM_TRACE_BUFFER_HANDLE (2ull << 12) +#define BASE_MEM_MAP_TRACKING_HANDLE (3ull << 12) +#define BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE (4ull << 12) +/* reserved handles ..-64< for future special handles */ +#define BASE_MEM_COOKIE_BASE (64ul << 12) +#define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << 12) + \ + BASE_MEM_COOKIE_BASE) + +/* Mask to detect 4GB boundary alignment */ +#define BASE_MEM_MASK_4GB 0xfffff000UL + + +/* Bit mask of cookies used for for memory allocation setup */ +#define KBASE_COOKIE_MASK ~1UL /* bit 0 is reserved */ + + +/** + * @brief Result codes of changing the size of the backing store allocated to a tmem region + */ +typedef enum base_backing_threshold_status { + BASE_BACKING_THRESHOLD_OK = 0, /**< Resize successful */ + BASE_BACKING_THRESHOLD_ERROR_OOM = -2, /**< Increase failed due to an out-of-memory condition */ + BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS = -4 /**< Invalid arguments (not tmem, illegal size request, etc.) */ +} base_backing_threshold_status; + +/** + * @addtogroup base_user_api_memory_defered User-side Base Defered Memory Coherency APIs + * @{ + */ + +/** + * @brief a basic memory operation (sync-set). + * + * The content of this structure is private, and should only be used + * by the accessors. + */ +typedef struct base_syncset { + struct basep_syncset basep_sset; +} base_syncset; + +/** @} end group base_user_api_memory_defered */ + +/** + * Handle to represent imported memory object. + * Simple opague handle to imported memory, can't be used + * with anything but base_external_resource_init to bind to an atom. + */ +typedef struct base_import_handle { + struct { + u64 handle; + } basep; +} base_import_handle; + +/** @} end group base_user_api_memory */ + +/** + * @addtogroup base_user_api_job_dispatch User-side Base Job Dispatcher APIs + * @{ + */ + +typedef int platform_fence_type; +#define INVALID_PLATFORM_FENCE ((platform_fence_type)-1) + +/** + * Base stream handle. + * + * References an underlying base stream object. + */ +typedef struct base_stream { + struct { + int fd; + } basep; +} base_stream; + +/** + * Base fence handle. + * + * References an underlying base fence object. + */ +typedef struct base_fence { + struct { + int fd; + int stream_fd; + } basep; +} base_fence; + +/** + * @brief Per-job data + * + * This structure is used to store per-job data, and is completely unused + * by the Base driver. It can be used to store things such as callback + * function pointer, data to handle job completion. It is guaranteed to be + * untouched by the Base driver. + */ +typedef struct base_jd_udata { + u64 blob[2]; /**< per-job data array */ +} base_jd_udata; + +/** + * @brief Memory aliasing info + * + * Describes a memory handle to be aliased. + * A subset of the handle can be chosen for aliasing, given an offset and a + * length. + * A special handle BASE_MEM_WRITE_ALLOC_PAGES_HANDLE is used to represent a + * region where a special page is mapped with a write-alloc cache setup, + * typically used when the write result of the GPU isn't needed, but the GPU + * must write anyway. + * + * Offset and length are specified in pages. + * Offset must be within the size of the handle. + * Offset+length must not overrun the size of the handle. + * + * @handle Handle to alias, can be BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * @offset Offset within the handle to start aliasing from, in pages. + * Not used with BASE_MEM_WRITE_ALLOC_PAGES_HANDLE. + * @length Length to alias, in pages. For BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * specifies the number of times the special page is needed. + */ +struct base_mem_aliasing_info { + base_mem_handle handle; + u64 offset; + u64 length; +}; + +/** + * struct base_jit_alloc_info - Structure which describes a JIT allocation + * request. + * @gpu_alloc_addr: The GPU virtual address to write the JIT + * allocated GPU virtual address to. + * @va_pages: The minimum number of virtual pages required. + * @commit_pages: The minimum number of physical pages which + * should back the allocation. + * @extent: Granularity of physical pages to grow the + * allocation by during a fault. + * @id: Unique ID provided by the caller, this is used + * to pair allocation and free requests. + * Zero is not a valid value. + */ +struct base_jit_alloc_info { + u64 gpu_alloc_addr; + u64 va_pages; + u64 commit_pages; + u64 extent; + u8 id; +}; + +/** + * @brief Job dependency type. + * + * A flags field will be inserted into the atom structure to specify whether a dependency is a data or + * ordering dependency (by putting it before/after 'core_req' in the structure it should be possible to add without + * changing the structure size). + * When the flag is set for a particular dependency to signal that it is an ordering only dependency then + * errors will not be propagated. + */ +typedef u8 base_jd_dep_type; + + +#define BASE_JD_DEP_TYPE_INVALID (0) /**< Invalid dependency */ +#define BASE_JD_DEP_TYPE_DATA (1U << 0) /**< Data dependency */ +#define BASE_JD_DEP_TYPE_ORDER (1U << 1) /**< Order dependency */ + +/** + * @brief Job chain hardware requirements. + * + * A job chain must specify what GPU features it needs to allow the + * driver to schedule the job correctly. By not specifying the + * correct settings can/will cause an early job termination. Multiple + * values can be ORed together to specify multiple requirements. + * Special case is ::BASE_JD_REQ_DEP, which is used to express complex + * dependencies, and that doesn't execute anything on the hardware. + */ +typedef u32 base_jd_core_req; + +/* Requirements that come from the HW */ + +/** + * No requirement, dependency only + */ +#define BASE_JD_REQ_DEP ((base_jd_core_req)0) + +/** + * Requires fragment shaders + */ +#define BASE_JD_REQ_FS ((base_jd_core_req)1 << 0) + +/** + * Requires compute shaders + * This covers any of the following Midgard Job types: + * - Vertex Shader Job + * - Geometry Shader Job + * - An actual Compute Shader Job + * + * Compare this with @ref BASE_JD_REQ_ONLY_COMPUTE, which specifies that the + * job is specifically just the "Compute Shader" job type, and not the "Vertex + * Shader" nor the "Geometry Shader" job type. + */ +#define BASE_JD_REQ_CS ((base_jd_core_req)1 << 1) +#define BASE_JD_REQ_T ((base_jd_core_req)1 << 2) /**< Requires tiling */ +#define BASE_JD_REQ_CF ((base_jd_core_req)1 << 3) /**< Requires cache flushes */ +#define BASE_JD_REQ_V ((base_jd_core_req)1 << 4) /**< Requires value writeback */ + +/* SW-only requirements - the HW does not expose these as part of the job slot capabilities */ + +/* Requires fragment job with AFBC encoding */ +#define BASE_JD_REQ_FS_AFBC ((base_jd_core_req)1 << 13) + +/** + * SW-only requirement: coalesce completion events. + * If this bit is set then completion of this atom will not cause an event to + * be sent to userspace, whether successful or not; completion events will be + * deferred until an atom completes which does not have this bit set. + * + * This bit may not be used in combination with BASE_JD_REQ_EXTERNAL_RESOURCES. + */ +#define BASE_JD_REQ_EVENT_COALESCE ((base_jd_core_req)1 << 5) + +/** + * SW Only requirement: the job chain requires a coherent core group. We don't + * mind which coherent core group is used. + */ +#define BASE_JD_REQ_COHERENT_GROUP ((base_jd_core_req)1 << 6) + +/** + * SW Only requirement: The performance counters should be enabled only when + * they are needed, to reduce power consumption. + */ + +#define BASE_JD_REQ_PERMON ((base_jd_core_req)1 << 7) + +/** + * SW Only requirement: External resources are referenced by this atom. + * When external resources are referenced no syncsets can be bundled with the atom + * but should instead be part of a NULL jobs inserted into the dependency tree. + * The first pre_dep object must be configured for the external resouces to use, + * the second pre_dep object can be used to create other dependencies. + * + * This bit may not be used in combination with BASE_JD_REQ_EVENT_COALESCE. + */ +#define BASE_JD_REQ_EXTERNAL_RESOURCES ((base_jd_core_req)1 << 8) + +/** + * SW Only requirement: Software defined job. Jobs with this bit set will not be submitted + * to the hardware but will cause some action to happen within the driver + */ +#define BASE_JD_REQ_SOFT_JOB ((base_jd_core_req)1 << 9) + +#define BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME (BASE_JD_REQ_SOFT_JOB | 0x1) +#define BASE_JD_REQ_SOFT_FENCE_TRIGGER (BASE_JD_REQ_SOFT_JOB | 0x2) +#define BASE_JD_REQ_SOFT_FENCE_WAIT (BASE_JD_REQ_SOFT_JOB | 0x3) + +/** + * SW Only requirement : Replay job. + * + * If the preceding job fails, the replay job will cause the jobs specified in + * the list of base_jd_replay_payload pointed to by the jc pointer to be + * replayed. + * + * A replay job will only cause jobs to be replayed up to BASEP_JD_REPLAY_LIMIT + * times. If a job fails more than BASEP_JD_REPLAY_LIMIT times then the replay + * job is failed, as well as any following dependencies. + * + * The replayed jobs will require a number of atom IDs. If there are not enough + * free atom IDs then the replay job will fail. + * + * If the preceding job does not fail, then the replay job is returned as + * completed. + * + * The replayed jobs will never be returned to userspace. The preceding failed + * job will be returned to userspace as failed; the status of this job should + * be ignored. Completion should be determined by the status of the replay soft + * job. + * + * In order for the jobs to be replayed, the job headers will have to be + * modified. The Status field will be reset to NOT_STARTED. If the Job Type + * field indicates a Vertex Shader Job then it will be changed to Null Job. + * + * The replayed jobs have the following assumptions : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - Pre-dependencies are created based on job order. + * - Atom numbers are automatically assigned. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + */ +#define BASE_JD_REQ_SOFT_REPLAY (BASE_JD_REQ_SOFT_JOB | 0x4) +/** + * SW only requirement: event wait/trigger job. + * + * - BASE_JD_REQ_SOFT_EVENT_WAIT: this job will block until the event is set. + * - BASE_JD_REQ_SOFT_EVENT_SET: this job sets the event, thus unblocks the + * other waiting jobs. It completes immediately. + * - BASE_JD_REQ_SOFT_EVENT_RESET: this job resets the event, making it + * possible for other jobs to wait upon. It completes immediately. + */ +#define BASE_JD_REQ_SOFT_EVENT_WAIT (BASE_JD_REQ_SOFT_JOB | 0x5) +#define BASE_JD_REQ_SOFT_EVENT_SET (BASE_JD_REQ_SOFT_JOB | 0x6) +#define BASE_JD_REQ_SOFT_EVENT_RESET (BASE_JD_REQ_SOFT_JOB | 0x7) + +#define BASE_JD_REQ_SOFT_DEBUG_COPY (BASE_JD_REQ_SOFT_JOB | 0x8) + +/** + * SW only requirement: Just In Time allocation + * + * This job requests a JIT allocation based on the request in the + * @base_jit_alloc_info structure which is passed via the jc element of + * the atom. + * + * It should be noted that the id entry in @base_jit_alloc_info must not + * be reused until it has been released via @BASE_JD_REQ_SOFT_JIT_FREE. + * + * Should this soft job fail it is expected that a @BASE_JD_REQ_SOFT_JIT_FREE + * soft job to free the JIT allocation is still made. + * + * The job will complete immediately. + */ +#define BASE_JD_REQ_SOFT_JIT_ALLOC (BASE_JD_REQ_SOFT_JOB | 0x9) +/** + * SW only requirement: Just In Time free + * + * This job requests a JIT allocation created by @BASE_JD_REQ_SOFT_JIT_ALLOC + * to be freed. The ID of the JIT allocation is passed via the jc element of + * the atom. + * + * The job will complete immediately. + */ +#define BASE_JD_REQ_SOFT_JIT_FREE (BASE_JD_REQ_SOFT_JOB | 0xa) + +/** + * SW only requirement: Map external resource + * + * This job requests external resource(s) are mapped once the dependencies + * of the job have been satisfied. The list of external resources are + * passed via the jc element of the atom which is a pointer to a + * @base_external_resource_list. + */ +#define BASE_JD_REQ_SOFT_EXT_RES_MAP (BASE_JD_REQ_SOFT_JOB | 0xb) +/** + * SW only requirement: Unmap external resource + * + * This job requests external resource(s) are unmapped once the dependencies + * of the job has been satisfied. The list of external resources are + * passed via the jc element of the atom which is a pointer to a + * @base_external_resource_list. + */ +#define BASE_JD_REQ_SOFT_EXT_RES_UNMAP (BASE_JD_REQ_SOFT_JOB | 0xc) + +/** + * HW Requirement: Requires Compute shaders (but not Vertex or Geometry Shaders) + * + * This indicates that the Job Chain contains Midgard Jobs of the 'Compute Shaders' type. + * + * In contrast to @ref BASE_JD_REQ_CS, this does \b not indicate that the Job + * Chain contains 'Geometry Shader' or 'Vertex Shader' jobs. + */ +#define BASE_JD_REQ_ONLY_COMPUTE ((base_jd_core_req)1 << 10) + +/** + * HW Requirement: Use the base_jd_atom::device_nr field to specify a + * particular core group + * + * If both @ref BASE_JD_REQ_COHERENT_GROUP and this flag are set, this flag takes priority + * + * This is only guaranteed to work for @ref BASE_JD_REQ_ONLY_COMPUTE atoms. + * + * If the core availability policy is keeping the required core group turned off, then + * the job will fail with a @ref BASE_JD_EVENT_PM_EVENT error code. + */ +#define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP ((base_jd_core_req)1 << 11) + +/** + * SW Flag: If this bit is set then the successful completion of this atom + * will not cause an event to be sent to userspace + */ +#define BASE_JD_REQ_EVENT_ONLY_ON_FAILURE ((base_jd_core_req)1 << 12) + +/** + * SW Flag: If this bit is set then completion of this atom will not cause an + * event to be sent to userspace, whether successful or not. + */ +#define BASEP_JD_REQ_EVENT_NEVER ((base_jd_core_req)1 << 14) + +/** + * SW Flag: Skip GPU cache clean and invalidation before starting a GPU job. + * + * If this bit is set then the GPU's cache will not be cleaned and invalidated + * until a GPU job starts which does not have this bit set or a job completes + * which does not have the @ref BASE_JD_REQ_SKIP_CACHE_END bit set. Do not use if + * the CPU may have written to memory addressed by the job since the last job + * without this bit set was submitted. + */ +#define BASE_JD_REQ_SKIP_CACHE_START ((base_jd_core_req)1 << 15) + +/** + * SW Flag: Skip GPU cache clean and invalidation after a GPU job completes. + * + * If this bit is set then the GPU's cache will not be cleaned and invalidated + * until a GPU job completes which does not have this bit set or a job starts + * which does not have the @ref BASE_JD_REQ_SKIP_CACHE_START bti set. Do not use if + * the CPU may read from or partially overwrite memory addressed by the job + * before the next job without this bit set completes. + */ +#define BASE_JD_REQ_SKIP_CACHE_END ((base_jd_core_req)1 << 16) + +/** + * These requirement bits are currently unused in base_jd_core_req + */ +#define BASEP_JD_REQ_RESERVED \ + (~(BASE_JD_REQ_ATOM_TYPE | BASE_JD_REQ_EXTERNAL_RESOURCES | \ + BASE_JD_REQ_EVENT_ONLY_ON_FAILURE | BASEP_JD_REQ_EVENT_NEVER | \ + BASE_JD_REQ_EVENT_COALESCE | \ + BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP | \ + BASE_JD_REQ_FS_AFBC | BASE_JD_REQ_PERMON | \ + BASE_JD_REQ_SKIP_CACHE_START | BASE_JD_REQ_SKIP_CACHE_END)) + +/** + * Mask of all bits in base_jd_core_req that control the type of the atom. + * + * This allows dependency only atoms to have flags set + */ +#define BASE_JD_REQ_ATOM_TYPE \ + (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T | BASE_JD_REQ_CF | \ + BASE_JD_REQ_V | BASE_JD_REQ_SOFT_JOB | BASE_JD_REQ_ONLY_COMPUTE) + +/** + * Mask of all bits in base_jd_core_req that control the type of a soft job. + */ +#define BASE_JD_REQ_SOFT_JOB_TYPE (BASE_JD_REQ_SOFT_JOB | 0x1f) + +/* + * Returns non-zero value if core requirements passed define a soft job or + * a dependency only job. + */ +#define BASE_JD_REQ_SOFT_JOB_OR_DEP(core_req) \ + ((core_req & BASE_JD_REQ_SOFT_JOB) || \ + (core_req & BASE_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) + +/** + * @brief States to model state machine processed by kbasep_js_job_check_ref_cores(), which + * handles retaining cores for power management and affinity management. + * + * The state @ref KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY prevents an attack + * where lots of atoms could be submitted before powerup, and each has an + * affinity chosen that causes other atoms to have an affinity + * violation. Whilst the affinity was not causing violations at the time it + * was chosen, it could cause violations thereafter. For example, 1000 jobs + * could have had their affinity chosen during the powerup time, so any of + * those 1000 jobs could cause an affinity violation later on. + * + * The attack would otherwise occur because other atoms/contexts have to wait for: + * -# the currently running atoms (which are causing the violation) to + * finish + * -# and, the atoms that had their affinity chosen during powerup to + * finish. These are run preferentially because they don't cause a + * violation, but instead continue to cause the violation in others. + * -# or, the attacker is scheduled out (which might not happen for just 2 + * contexts) + * + * By re-choosing the affinity (which is designed to avoid violations at the + * time it's chosen), we break condition (2) of the wait, which minimizes the + * problem to just waiting for current jobs to finish (which can be bounded if + * the Job Scheduling Policy has a timer). + */ +enum kbase_atom_coreref_state { + /** Starting state: No affinity chosen, and cores must be requested. kbase_jd_atom::affinity==0 */ + KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED, + /** Cores requested, but waiting for them to be powered. Requested cores given by kbase_jd_atom::affinity */ + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES, + /** Cores given by kbase_jd_atom::affinity are powered, but affinity might be out-of-date, so must recheck */ + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY, + /** Cores given by kbase_jd_atom::affinity are powered, and affinity is up-to-date, but must check for violations */ + KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS, + /** Cores are powered, kbase_jd_atom::affinity up-to-date, no affinity violations: atom can be submitted to HW */ + KBASE_ATOM_COREREF_STATE_READY +}; + +/* + * Base Atom priority + * + * Only certain priority levels are actually implemented, as specified by the + * BASE_JD_PRIO_<...> definitions below. It is undefined to use a priority + * level that is not one of those defined below. + * + * Priority levels only affect scheduling between atoms of the same type within + * a base context, and only after the atoms have had dependencies resolved. + * Fragment atoms does not affect non-frament atoms with lower priorities, and + * the other way around. For example, a low priority atom that has had its + * dependencies resolved might run before a higher priority atom that has not + * had its dependencies resolved. + * + * The scheduling between base contexts/processes and between atoms from + * different base contexts/processes is unaffected by atom priority. + * + * The atoms are scheduled as follows with respect to their priorities: + * - Let atoms 'X' and 'Y' be for the same job slot who have dependencies + * resolved, and atom 'X' has a higher priority than atom 'Y' + * - If atom 'Y' is currently running on the HW, then it is interrupted to + * allow atom 'X' to run soon after + * - If instead neither atom 'Y' nor atom 'X' are running, then when choosing + * the next atom to run, atom 'X' will always be chosen instead of atom 'Y' + * - Any two atoms that have the same priority could run in any order with + * respect to each other. That is, there is no ordering constraint between + * atoms of the same priority. + */ +typedef u8 base_jd_prio; + +/* Medium atom priority. This is a priority higher than BASE_JD_PRIO_LOW */ +#define BASE_JD_PRIO_MEDIUM ((base_jd_prio)0) +/* High atom priority. This is a priority higher than BASE_JD_PRIO_MEDIUM and + * BASE_JD_PRIO_LOW */ +#define BASE_JD_PRIO_HIGH ((base_jd_prio)1) +/* Low atom priority. */ +#define BASE_JD_PRIO_LOW ((base_jd_prio)2) + +/* Count of the number of priority levels. This itself is not a valid + * base_jd_prio setting */ +#define BASE_JD_NR_PRIO_LEVELS 3 + +enum kbase_jd_atom_state { + /** Atom is not used */ + KBASE_JD_ATOM_STATE_UNUSED, + /** Atom is queued in JD */ + KBASE_JD_ATOM_STATE_QUEUED, + /** Atom has been given to JS (is runnable/running) */ + KBASE_JD_ATOM_STATE_IN_JS, + /** Atom has been completed, but not yet handed back to job dispatcher + * for dependency resolution */ + KBASE_JD_ATOM_STATE_HW_COMPLETED, + /** Atom has been completed, but not yet handed back to userspace */ + KBASE_JD_ATOM_STATE_COMPLETED +}; + +typedef u8 base_atom_id; /**< Type big enough to store an atom number in */ + +struct base_dependency { + base_atom_id atom_id; /**< An atom number */ + base_jd_dep_type dependency_type; /**< Dependency type */ +}; + +/* This structure has changed since UK 10.2 for which base_jd_core_req was a u16 value. + * In order to keep the size of the structure same, padding field has been adjusted + * accordingly and core_req field of a u32 type (to which UK 10.3 base_jd_core_req defines) + * is added at the end of the structure. Place in the structure previously occupied by u16 core_req + * is kept but renamed to compat_core_req and as such it can be used in ioctl call for job submission + * as long as UK 10.2 legacy is supported. Once when this support ends, this field can be left + * for possible future use. */ +typedef struct base_jd_atom_v2 { + u64 jc; /**< job-chain GPU address */ + struct base_jd_udata udata; /**< user data */ + u64 extres_list; /**< list of external resources */ + u16 nr_extres; /**< nr of external resources */ + u16 compat_core_req; /**< core requirements which correspond to the legacy support for UK 10.2 */ + struct base_dependency pre_dep[2]; /**< pre-dependencies, one need to use SETTER function to assign this field, + this is done in order to reduce possibility of improper assigment of a dependency field */ + base_atom_id atom_number; /**< unique number to identify the atom */ + base_jd_prio prio; /**< Atom priority. Refer to @ref base_jd_prio for more details */ + u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */ + u8 padding[1]; + base_jd_core_req core_req; /**< core requirements */ +} base_jd_atom_v2; + +typedef enum base_external_resource_access { + BASE_EXT_RES_ACCESS_SHARED, + BASE_EXT_RES_ACCESS_EXCLUSIVE +} base_external_resource_access; + +typedef struct base_external_resource { + u64 ext_resource; +} base_external_resource; + + +/** + * The maximum number of external resources which can be mapped/unmapped + * in a single request. + */ +#define BASE_EXT_RES_COUNT_MAX 10 + +/** + * struct base_external_resource_list - Structure which describes a list of + * external resources. + * @count: The number of resources. + * @ext_res: Array of external resources which is + * sized at allocation time. + */ +struct base_external_resource_list { + u64 count; + struct base_external_resource ext_res[1]; +}; + +struct base_jd_debug_copy_buffer { + u64 address; + u64 size; + struct base_external_resource extres; +}; + +/** + * @brief Setter for a dependency structure + * + * @param[in] dep The kbase jd atom dependency to be initialized. + * @param id The atom_id to be assigned. + * @param dep_type The dep_type to be assigned. + * + */ +static inline void base_jd_atom_dep_set(struct base_dependency *dep, + base_atom_id id, base_jd_dep_type dep_type) +{ + LOCAL_ASSERT(dep != NULL); + + /* + * make sure we don't set not allowed combinations + * of atom_id/dependency_type. + */ + LOCAL_ASSERT((id == 0 && dep_type == BASE_JD_DEP_TYPE_INVALID) || + (id > 0 && dep_type != BASE_JD_DEP_TYPE_INVALID)); + + dep->atom_id = id; + dep->dependency_type = dep_type; +} + +/** + * @brief Make a copy of a dependency structure + * + * @param[in,out] dep The kbase jd atom dependency to be written. + * @param[in] from The dependency to make a copy from. + * + */ +static inline void base_jd_atom_dep_copy(struct base_dependency *dep, + const struct base_dependency *from) +{ + LOCAL_ASSERT(dep != NULL); + + base_jd_atom_dep_set(dep, from->atom_id, from->dependency_type); +} + +/** + * @brief Soft-atom fence trigger setup. + * + * Sets up an atom to be a SW-only atom signaling a fence + * when it reaches the run state. + * + * Using the existing base dependency system the fence can + * be set to trigger when a GPU job has finished. + * + * The base fence object must not be terminated until the atom + * has been submitted to @ref base_jd_submit and @ref base_jd_submit + * has returned. + * + * @a fence must be a valid fence set up with @a base_fence_init. + * Calling this function with a uninitialized fence results in undefined behavior. + * + * @param[out] atom A pre-allocated atom to configure as a fence trigger SW atom + * @param[in] fence The base fence object to trigger. + * + * @pre @p fence must reference a @ref base_fence successfully initialized by + * calling @ref base_fence_init. + * @pre @p fence was @e not initialized by calling @ref base_fence_import, nor + * is it associated with a fence-trigger job that was already submitted + * by calling @ref base_jd_submit. + * @post @p atom can be submitted by calling @ref base_jd_submit. + */ +static inline void base_jd_fence_trigger_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd == INVALID_PLATFORM_FENCE); + LOCAL_ASSERT(fence->basep.stream_fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_TRIGGER; +} + +/** + * @brief Soft-atom fence wait setup. + * + * Sets up an atom to be a SW-only atom waiting on a fence. + * When the fence becomes triggered the atom becomes runnable + * and completes immediately. + * + * Using the existing base dependency system the fence can + * be set to block a GPU job until it has been triggered. + * + * The base fence object must not be terminated until the atom + * has been submitted to @ref base_jd_submit and + * @ref base_jd_submit has returned. + * + * @param[out] atom A pre-allocated atom to configure as a fence wait SW atom + * @param[in] fence The base fence object to wait on + * + * @pre @p fence must reference a @ref base_fence successfully initialized by + * calling @ref base_fence_import, or it must be associated with a + * fence-trigger job that was already submitted by calling + * @ref base_jd_submit. + * @post @p atom can be submitted by calling @ref base_jd_submit. + */ +static inline void base_jd_fence_wait_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_WAIT; +} + +/** + * @brief External resource info initialization. + * + * Sets up an external resource object to reference + * a memory allocation and the type of access requested. + * + * @param[in] res The resource object to initialize + * @param handle The handle to the imported memory object, must be + * obtained by calling @ref base_mem_as_import_handle(). + * @param access The type of access requested + */ +static inline void base_external_resource_init(struct base_external_resource *res, struct base_import_handle handle, base_external_resource_access access) +{ + u64 address; + + address = handle.basep.handle; + + LOCAL_ASSERT(res != NULL); + LOCAL_ASSERT(0 == (address & LOCAL_PAGE_LSB)); + LOCAL_ASSERT(access == BASE_EXT_RES_ACCESS_SHARED || access == BASE_EXT_RES_ACCESS_EXCLUSIVE); + + res->ext_resource = address | (access & LOCAL_PAGE_LSB); +} + +/** + * @brief Job chain event code bits + * Defines the bits used to create ::base_jd_event_code + */ +enum { + BASE_JD_SW_EVENT_KERNEL = (1u << 15), /**< Kernel side event */ + BASE_JD_SW_EVENT = (1u << 14), /**< SW defined event */ + BASE_JD_SW_EVENT_SUCCESS = (1u << 13), /**< Event idicates success (SW events only) */ + BASE_JD_SW_EVENT_JOB = (0u << 11), /**< Job related event */ + BASE_JD_SW_EVENT_BAG = (1u << 11), /**< Bag related event */ + BASE_JD_SW_EVENT_INFO = (2u << 11), /**< Misc/info event */ + BASE_JD_SW_EVENT_RESERVED = (3u << 11), /**< Reserved event type */ + BASE_JD_SW_EVENT_TYPE_MASK = (3u << 11) /**< Mask to extract the type from an event code */ +}; + +/** + * @brief Job chain event codes + * + * HW and low-level SW events are represented by event codes. + * The status of jobs which succeeded are also represented by + * an event code (see ::BASE_JD_EVENT_DONE). + * Events are usually reported as part of a ::base_jd_event. + * + * The event codes are encoded in the following way: + * @li 10:0 - subtype + * @li 12:11 - type + * @li 13 - SW success (only valid if the SW bit is set) + * @li 14 - SW event (HW event if not set) + * @li 15 - Kernel event (should never be seen in userspace) + * + * Events are split up into ranges as follows: + * - BASE_JD_EVENT_RANGE_\_START + * - BASE_JD_EVENT_RANGE_\_END + * + * \a code is in \'s range when: + * - BASE_JD_EVENT_RANGE_\_START <= code < BASE_JD_EVENT_RANGE_\_END + * + * Ranges can be asserted for adjacency by testing that the END of the previous + * is equal to the START of the next. This is useful for optimizing some tests + * for range. + * + * A limitation is that the last member of this enum must explicitly be handled + * (with an assert-unreachable statement) in switch statements that use + * variables of this type. Otherwise, the compiler warns that we have not + * handled that enum value. + */ +typedef enum base_jd_event_code { + /* HW defined exceptions */ + + /** Start of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_START = 0, + + /* non-fatal exceptions */ + BASE_JD_EVENT_NOT_STARTED = 0x00, /**< Can't be seen by userspace, treated as 'previous job done' */ + BASE_JD_EVENT_DONE = 0x01, + BASE_JD_EVENT_STOPPED = 0x03, /**< Can't be seen by userspace, becomes TERMINATED, DONE or JOB_CANCELLED */ + BASE_JD_EVENT_TERMINATED = 0x04, /**< This is actually a fault status code - the job was hard stopped */ + BASE_JD_EVENT_ACTIVE = 0x08, /**< Can't be seen by userspace, jobs only returned on complete/fail/cancel */ + + /** End of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_END = 0x40, + + /** Start of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START = 0x40, + + /* job exceptions */ + BASE_JD_EVENT_JOB_CONFIG_FAULT = 0x40, + BASE_JD_EVENT_JOB_POWER_FAULT = 0x41, + BASE_JD_EVENT_JOB_READ_FAULT = 0x42, + BASE_JD_EVENT_JOB_WRITE_FAULT = 0x43, + BASE_JD_EVENT_JOB_AFFINITY_FAULT = 0x44, + BASE_JD_EVENT_JOB_BUS_FAULT = 0x48, + BASE_JD_EVENT_INSTR_INVALID_PC = 0x50, + BASE_JD_EVENT_INSTR_INVALID_ENC = 0x51, + BASE_JD_EVENT_INSTR_TYPE_MISMATCH = 0x52, + BASE_JD_EVENT_INSTR_OPERAND_FAULT = 0x53, + BASE_JD_EVENT_INSTR_TLS_FAULT = 0x54, + BASE_JD_EVENT_INSTR_BARRIER_FAULT = 0x55, + BASE_JD_EVENT_INSTR_ALIGN_FAULT = 0x56, + BASE_JD_EVENT_DATA_INVALID_FAULT = 0x58, + BASE_JD_EVENT_TILE_RANGE_FAULT = 0x59, + BASE_JD_EVENT_STATE_FAULT = 0x5A, + BASE_JD_EVENT_OUT_OF_MEMORY = 0x60, + BASE_JD_EVENT_UNKNOWN = 0x7F, + + /* GPU exceptions */ + BASE_JD_EVENT_DELAYED_BUS_FAULT = 0x80, + BASE_JD_EVENT_SHAREABILITY_FAULT = 0x88, + + /* MMU exceptions */ + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1 = 0xC1, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2 = 0xC2, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3 = 0xC3, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4 = 0xC4, + BASE_JD_EVENT_PERMISSION_FAULT = 0xC8, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1 = 0xD1, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2 = 0xD2, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3 = 0xD3, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4 = 0xD4, + BASE_JD_EVENT_ACCESS_FLAG = 0xD8, + + /* SW defined exceptions */ + BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_TIMED_OUT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x001, + BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002, + BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003, + BASE_JD_EVENT_PM_EVENT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x004, + BASE_JD_EVENT_FORCE_REPLAY = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x005, + + BASE_JD_EVENT_BAG_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_BAG | 0x003, + + /** End of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000, + + BASE_JD_EVENT_PROGRESS_REPORT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_BAG_DONE = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_BAG | 0x000, + BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_INFO | 0x000, + + /** End of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of Kernel-only status codes. Such codes are never returned to user-space */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | 0x000, + BASE_JD_EVENT_REMOVED_FROM_NEXT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_JOB | 0x000, + + /** End of Kernel-only status codes. */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_RESERVED | 0x3FF +} base_jd_event_code; + +/** + * @brief Event reporting structure + * + * This structure is used by the kernel driver to report information + * about GPU events. The can either be HW-specific events or low-level + * SW events, such as job-chain completion. + * + * The event code contains an event type field which can be extracted + * by ANDing with ::BASE_JD_SW_EVENT_TYPE_MASK. + * + * Based on the event type base_jd_event::data holds: + * @li ::BASE_JD_SW_EVENT_JOB : the offset in the ring-buffer for the completed + * job-chain + * @li ::BASE_JD_SW_EVENT_BAG : The address of the ::base_jd_bag that has + * been completed (ie all contained job-chains have been completed). + * @li ::BASE_JD_SW_EVENT_INFO : base_jd_event::data not used + */ +typedef struct base_jd_event_v2 { + base_jd_event_code event_code; /**< event code */ + base_atom_id atom_number; /**< the atom number that has completed */ + struct base_jd_udata udata; /**< user data */ +} base_jd_event_v2; + +/** + * @brief Structure for BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS jobs. + * + * This structure is stored into the memory pointed to by the @c jc field + * of @ref base_jd_atom. + * + * It must not occupy the same CPU cache line(s) as any neighboring data. + * This is to avoid cases where access to pages containing the structure + * is shared between cached and un-cached memory regions, which would + * cause memory corruption. + */ + +typedef struct base_dump_cpu_gpu_counters { + u64 system_time; + u64 cycle_counter; + u64 sec; + u32 usec; + u8 padding[36]; +} base_dump_cpu_gpu_counters; + +/** @} end group base_user_api_job_dispatch */ + +#define GPU_MAX_JOB_SLOTS 16 + +/** + * @page page_base_user_api_gpuprops User-side Base GPU Property Query API + * + * The User-side Base GPU Property Query API encapsulates two + * sub-modules: + * + * - @ref base_user_api_gpuprops_dyn "Dynamic GPU Properties" + * - @ref base_plat_config_gpuprops "Base Platform Config GPU Properties" + * + * There is a related third module outside of Base, which is owned by the MIDG + * module: + * - @ref gpu_props_static "Midgard Compile-time GPU Properties" + * + * Base only deals with properties that vary between different Midgard + * implementations - the Dynamic GPU properties and the Platform Config + * properties. + * + * For properties that are constant for the Midgard Architecture, refer to the + * MIDG module. However, we will discuss their relevance here just to + * provide background information. + * + * @section sec_base_user_api_gpuprops_about About the GPU Properties in Base and MIDG modules + * + * The compile-time properties (Platform Config, Midgard Compile-time + * properties) are exposed as pre-processor macros. + * + * Complementing the compile-time properties are the Dynamic GPU + * Properties, which act as a conduit for the Midgard Configuration + * Discovery. + * + * In general, the dynamic properties are present to verify that the platform + * has been configured correctly with the right set of Platform Config + * Compile-time Properties. + * + * As a consistent guide across the entire DDK, the choice for dynamic or + * compile-time should consider the following, in order: + * -# Can the code be written so that it doesn't need to know the + * implementation limits at all? + * -# If you need the limits, get the information from the Dynamic Property + * lookup. This should be done once as you fetch the context, and then cached + * as part of the context data structure, so it's cheap to access. + * -# If there's a clear and arguable inefficiency in using Dynamic Properties, + * then use a Compile-Time Property (Platform Config, or Midgard Compile-time + * property). Examples of where this might be sensible follow: + * - Part of a critical inner-loop + * - Frequent re-use throughout the driver, causing significant extra load + * instructions or control flow that would be worthwhile optimizing out. + * + * We cannot provide an exhaustive set of examples, neither can we provide a + * rule for every possible situation. Use common sense, and think about: what + * the rest of the driver will be doing; how the compiler might represent the + * value if it is a compile-time constant; whether an OEM shipping multiple + * devices would benefit much more from a single DDK binary, instead of + * insignificant micro-optimizations. + * + * @section sec_base_user_api_gpuprops_dyn Dynamic GPU Properties + * + * Dynamic GPU properties are presented in two sets: + * -# the commonly used properties in @ref base_gpu_props, which have been + * unpacked from GPU register bitfields. + * -# The full set of raw, unprocessed properties in @ref gpu_raw_gpu_props + * (also a member of @ref base_gpu_props). All of these are presented in + * the packed form, as presented by the GPU registers themselves. + * + * @usecase The raw properties in @ref gpu_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + * The properties returned extend the Midgard Configuration Discovery + * registers. For example, GPU clock speed is not specified in the Midgard + * Architecture, but is necessary for OpenCL's clGetDeviceInfo() function. + * + * The GPU properties are obtained by a call to + * _mali_base_get_gpu_props(). This simply returns a pointer to a const + * base_gpu_props structure. It is constant for the life of a base + * context. Multiple calls to _mali_base_get_gpu_props() to a base context + * return the same pointer to a constant structure. This avoids cache pollution + * of the common data. + * + * This pointer must not be freed, because it does not point to the start of a + * region allocated by the memory allocator; instead, just close the @ref + * base_context. + * + * + * @section sec_base_user_api_gpuprops_config Platform Config Compile-time Properties + * + * The Platform Config File sets up gpu properties that are specific to a + * certain platform. Properties that are 'Implementation Defined' in the + * Midgard Architecture spec are placed here. + * + * @note Reference configurations are provided for Midgard Implementations, such as + * the Mali-T600 family. The customer need not repeat this information, and can select one of + * these reference configurations. For example, VA_BITS, PA_BITS and the + * maximum number of samples per pixel might vary between Midgard Implementations, but + * \b not for platforms using the Mali-T604. This information is placed in + * the reference configuration files. + * + * The System Integrator creates the following structure: + * - platform_XYZ + * - platform_XYZ/plat + * - platform_XYZ/plat/plat_config.h + * + * They then edit plat_config.h, using the example plat_config.h files as a + * guide. + * + * At the very least, the customer must set @ref CONFIG_GPU_CORE_TYPE, and will + * receive a helpful \#error message if they do not do this correctly. This + * selects the Reference Configuration for the Midgard Implementation. The rationale + * behind this decision (against asking the customer to write \#include + * in their plat_config.h) is as follows: + * - This mechanism 'looks' like a regular config file (such as Linux's + * .config) + * - It is difficult to get wrong in a way that will produce strange build + * errors: + * - They need not know where the mali_t600.h, other_midg_gpu.h etc. files are stored - and + * so they won't accidentally pick another file with 'mali_t600' in its name + * - When the build doesn't work, the System Integrator may think the DDK is + * doesn't work, and attempt to fix it themselves: + * - For the @ref CONFIG_GPU_CORE_TYPE mechanism, the only way to get past the + * error is to set @ref CONFIG_GPU_CORE_TYPE, and this is what the \#error tells + * you. + * - For a \#include mechanism, checks must still be made elsewhere, which the + * System Integrator may try working around by setting \#defines (such as + * VA_BITS) themselves in their plat_config.h. In the worst case, they may + * set the prevention-mechanism \#define of + * "A_CORRECT_MIDGARD_CORE_WAS_CHOSEN". + * - In this case, they would believe they are on the right track, because + * the build progresses with their fix, but with errors elsewhere. + * + * However, there is nothing to prevent the customer using \#include to organize + * their own configurations files hierarchically. + * + * The mechanism for the header file processing is as follows: + * + * @dot + digraph plat_config_mechanism { + rankdir=BT + size="6,6" + + "mali_base.h"; + "gpu/mali_gpu.h"; + + node [ shape=box ]; + { + rank = same; ordering = out; + + "gpu/mali_gpu_props.h"; + "base/midg_gpus/mali_t600.h"; + "base/midg_gpus/other_midg_gpu.h"; + } + { rank = same; "plat/plat_config.h"; } + { + rank = same; + "gpu/mali_gpu.h" [ shape=box ]; + gpu_chooser [ label="" style="invisible" width=0 height=0 fixedsize=true ]; + select_gpu [ label="Mali-T600 | Other\n(select_gpu.h)" shape=polygon,sides=4,distortion=0.25 width=3.3 height=0.99 fixedsize=true ] ; + } + node [ shape=box ]; + { rank = same; "plat/plat_config.h"; } + { rank = same; "mali_base.h"; } + + "mali_base.h" -> "gpu/mali_gpu.h" -> "gpu/mali_gpu_props.h"; + "mali_base.h" -> "plat/plat_config.h" ; + "mali_base.h" -> select_gpu ; + + "plat/plat_config.h" -> gpu_chooser [style="dotted,bold" dir=none weight=4] ; + gpu_chooser -> select_gpu [style="dotted,bold"] ; + + select_gpu -> "base/midg_gpus/mali_t600.h" ; + select_gpu -> "base/midg_gpus/other_midg_gpu.h" ; + } + @enddot + * + * + * @section sec_base_user_api_gpuprops_kernel Kernel Operation + * + * During Base Context Create time, user-side makes a single kernel call: + * - A call to fill user memory with GPU information structures + * + * The kernel-side will fill the provided the entire processed @ref base_gpu_props + * structure, because this information is required in both + * user and kernel side; it does not make sense to decode it twice. + * + * Coherency groups must be derived from the bitmasks, but this can be done + * kernel side, and just once at kernel startup: Coherency groups must already + * be known kernel-side, to support chains that specify a 'Only Coherent Group' + * SW requirement, or 'Only Coherent Group with Tiler' SW requirement. + * + * @section sec_base_user_api_gpuprops_cocalc Coherency Group calculation + * Creation of the coherent group data is done at device-driver startup, and so + * is one-time. This will most likely involve a loop with CLZ, shifting, and + * bit clearing on the L2_PRESENT mask, depending on whether the + * system is L2 Coherent. The number of shader cores is done by a + * population count, since faulty cores may be disabled during production, + * producing a non-contiguous mask. + * + * The memory requirements for this algorithm can be determined either by a u64 + * population count on the L2_PRESENT mask (a LUT helper already is + * required for the above), or simple assumption that there can be no more than + * 16 coherent groups, since core groups are typically 4 cores. + */ + +/** + * @addtogroup base_user_api_gpuprops User-side Base GPU Property Query APIs + * @{ + */ + +/** + * @addtogroup base_user_api_gpuprops_dyn Dynamic HW Properties + * @{ + */ + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +struct mali_base_gpu_core_props { + /** + * Product specific value. + */ + u32 product_id; + + /** + * Status of the GPU release. + * No defined values, but starts at 0 and increases by one for each + * release status (alpha, beta, EAC, etc.). + * 4 bit values (0-15). + */ + u16 version_status; + + /** + * Minor release number of the GPU. "P" part of an "RnPn" release number. + * 8 bit values (0-255). + */ + u16 minor_revision; + + /** + * Major release number of the GPU. "R" part of an "RnPn" release number. + * 4 bit values (0-15). + */ + u16 major_revision; + + u16 padding; + + /** + * This property is deprecated since it has not contained the real current + * value of GPU clock speed. It is kept here only for backwards compatibility. + * For the new ioctl interface, it is ignored and is treated as a padding + * to keep the structure of the same size and retain the placement of its + * members. + */ + u32 gpu_speed_mhz; + + /** + * @usecase GPU clock max/min speed is required for computing best/worst case + * in tasks as job scheduling ant irq_throttling. (It is not specified in the + * Midgard Architecture). + * Also, GPU clock max speed is used for OpenCL's clGetDeviceInfo() function. + */ + u32 gpu_freq_khz_max; + u32 gpu_freq_khz_min; + + /** + * Size of the shader program counter, in bits. + */ + u32 log2_program_counter_size; + + /** + * TEXTURE_FEATURES_x registers, as exposed by the GPU. This is a + * bitpattern where a set bit indicates that the format is supported. + * + * Before using a texture format, it is recommended that the corresponding + * bit be checked. + */ + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + + /** + * Theoretical maximum memory available to the GPU. It is unlikely that a + * client will be able to allocate all of this memory for their own + * purposes, but this at least provides an upper bound on the memory + * available to the GPU. + * + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The + * client will not be expecting to allocate anywhere near this value. + */ + u64 gpu_available_memory_size; +}; + +/** + * + * More information is possible - but associativity and bus width are not + * required by upper-level apis. + */ +struct mali_base_gpu_l2_cache_props { + u8 log2_line_size; + u8 log2_cache_size; + u8 num_l2_slices; /* Number of L2C slices. 1 or higher */ + u8 padding[5]; +}; + +struct mali_base_gpu_tiler_props { + u32 bin_size_bytes; /* Max is 4*2^15 */ + u32 max_active_levels; /* Max is 2^15 */ +}; + +/** + * GPU threading system details. + */ +struct mali_base_gpu_thread_props { + u32 max_threads; /* Max. number of threads per core */ + u32 max_workgroup_size; /* Max. number of threads per workgroup */ + u32 max_barrier_size; /* Max. number of threads that can synchronize on a simple barrier */ + u16 max_registers; /* Total size [1..65535] of the register file available per core. */ + u8 max_task_queue; /* Max. tasks [1..255] which may be sent to a core before it becomes blocked. */ + u8 max_thread_group_split; /* Max. allowed value [1..15] of the Thread Group Split field. */ + u8 impl_tech; /* 0 = Not specified, 1 = Silicon, 2 = FPGA, 3 = SW Model/Emulation */ + u8 padding[7]; +}; + +/** + * @brief descriptor for a coherent group + * + * \c core_mask exposes all cores in that coherent group, and \c num_cores + * provides a cached population-count for that mask. + * + * @note Whilst all cores are exposed in the mask, not all may be available to + * the application, depending on the Kernel Power policy. + * + * @note if u64s must be 8-byte aligned, then this structure has 32-bits of wastage. + */ +struct mali_base_gpu_coherent_group { + u64 core_mask; /**< Core restriction mask required for the group */ + u16 num_cores; /**< Number of cores in the group */ + u16 padding[3]; +}; + +/** + * @brief Coherency group information + * + * Note that the sizes of the members could be reduced. However, the \c group + * member might be 8-byte aligned to ensure the u64 core_mask is 8-byte + * aligned, thus leading to wastage if the other members sizes were reduced. + * + * The groups are sorted by core mask. The core masks are non-repeating and do + * not intersect. + */ +struct mali_base_gpu_coherent_group_info { + u32 num_groups; + + /** + * Number of core groups (coherent or not) in the GPU. Equivalent to the number of L2 Caches. + * + * The GPU Counter dumping writes 2048 bytes per core group, regardless of + * whether the core groups are coherent or not. Hence this member is needed + * to calculate how much memory is required for dumping. + * + * @note Do not use it to work out how many valid elements are in the + * group[] member. Use num_groups instead. + */ + u32 num_core_groups; + + /** + * Coherency features of the memory, accessed by @ref gpu_mem_features + * methods + */ + u32 coherency; + + u32 padding; + + /** + * Descriptors of coherent groups + */ + struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; +}; + +/** + * A complete description of the GPU's Hardware Configuration Discovery + * registers. + * + * The information is presented inefficiently for access. For frequent access, + * the values should be better expressed in an unpacked form in the + * base_gpu_props structure. + * + * @usecase The raw properties in @ref gpu_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + */ +struct gpu_raw_gpu_props { + u64 shader_present; + u64 tiler_present; + u64 l2_present; + u64 stack_present; + + u32 l2_features; + u32 suspend_size; /* API 8.2+ */ + u32 mem_features; + u32 mmu_features; + + u32 as_present; + + u32 js_present; + u32 js_features[GPU_MAX_JOB_SLOTS]; + u32 tiler_features; + u32 texture_features[3]; + + u32 gpu_id; + + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + + /* + * Note: This is the _selected_ coherency mode rather than the + * available modes as exposed in the coherency_features register. + */ + u32 coherency_mode; +}; + +/** + * Return structure for _mali_base_get_gpu_props(). + * + * NOTE: the raw_props member in this data structure contains the register + * values from which the value of the other members are derived. The derived + * members exist to allow for efficient access and/or shielding the details + * of the layout of the registers. + * + */ +typedef struct mali_base_gpu_props { + struct mali_base_gpu_core_props core_props; + struct mali_base_gpu_l2_cache_props l2_props; + u64 unused_1; /* keep for backwards compatibility */ + struct mali_base_gpu_tiler_props tiler_props; + struct mali_base_gpu_thread_props thread_props; + + /** This member is large, likely to be 128 bytes */ + struct gpu_raw_gpu_props raw_props; + + /** This must be last member of the structure */ + struct mali_base_gpu_coherent_group_info coherency_info; +} base_gpu_props; + +/** @} end group base_user_api_gpuprops_dyn */ + +/** @} end group base_user_api_gpuprops */ + +/** + * @addtogroup base_user_api_core User-side Base core APIs + * @{ + */ + +/** + * \enum base_context_create_flags + * + * Flags to pass to ::base_context_init. + * Flags can be ORed together to enable multiple things. + * + * These share the same space as BASEP_CONTEXT_FLAG_*, and so must + * not collide with them. + */ +enum base_context_create_flags { + /** No flags set */ + BASE_CONTEXT_CREATE_FLAG_NONE = 0, + + /** Base context is embedded in a cctx object (flag used for CINSTR software counter macros) */ + BASE_CONTEXT_CCTX_EMBEDDED = (1u << 0), + + /** Base context is a 'System Monitor' context for Hardware counters. + * + * One important side effect of this is that job submission is disabled. */ + BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED = (1u << 1) +}; + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to base_context_init() + */ +#define BASE_CONTEXT_CREATE_ALLOWED_FLAGS \ + (((u32)BASE_CONTEXT_CCTX_EMBEDDED) | \ + ((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED)) + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to the kernel + */ +#define BASE_CONTEXT_CREATE_KERNEL_FLAGS \ + ((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) + +/* + * Private flags used on the base context + * + * These start at bit 31, and run down to zero. + * + * They share the same space as @ref base_context_create_flags, and so must + * not collide with them. + */ +/** Private flag tracking whether job descriptor dumping is disabled */ +#define BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED ((u32)(1 << 31)) + +/** @} end group base_user_api_core */ + +/** @} end group base_user_api */ + +/** + * @addtogroup base_plat_config_gpuprops Base Platform Config GPU Properties + * @{ + * + * C Pre-processor macros are exposed here to do with Platform + * Config. + * + * These include: + * - GPU Properties that are constant on a particular Midgard Family + * Implementation e.g. Maximum samples per pixel on Mali-T600. + * - General platform config for the GPU, such as the GPU major and minor + * revison. + */ + +/** @} end group base_plat_config_gpuprops */ + +/** + * @addtogroup base_api Base APIs + * @{ + */ + +/** + * @brief The payload for a replay job. This must be in GPU memory. + */ +typedef struct base_jd_replay_payload { + /** + * Pointer to the first entry in the base_jd_replay_jc list. These + * will be replayed in @b reverse order (so that extra ones can be added + * to the head in future soft jobs without affecting this soft job) + */ + u64 tiler_jc_list; + + /** + * Pointer to the fragment job chain. + */ + u64 fragment_jc; + + /** + * Pointer to the tiler heap free FBD field to be modified. + */ + u64 tiler_heap_free; + + /** + * Hierarchy mask for the replayed fragment jobs. May be zero. + */ + u16 fragment_hierarchy_mask; + + /** + * Hierarchy mask for the replayed tiler jobs. May be zero. + */ + u16 tiler_hierarchy_mask; + + /** + * Default weight to be used for hierarchy levels not in the original + * mask. + */ + u32 hierarchy_default_weight; + + /** + * Core requirements for the tiler job chain + */ + base_jd_core_req tiler_core_req; + + /** + * Core requirements for the fragment job chain + */ + base_jd_core_req fragment_core_req; +} base_jd_replay_payload; + +#ifdef BASE_LEGACY_UK10_2_SUPPORT +typedef struct base_jd_replay_payload_uk10_2 { + u64 tiler_jc_list; + u64 fragment_jc; + u64 tiler_heap_free; + u16 fragment_hierarchy_mask; + u16 tiler_hierarchy_mask; + u32 hierarchy_default_weight; + u16 tiler_core_req; + u16 fragment_core_req; + u8 padding[4]; +} base_jd_replay_payload_uk10_2; +#endif /* BASE_LEGACY_UK10_2_SUPPORT */ + +/** + * @brief An entry in the linked list of job chains to be replayed. This must + * be in GPU memory. + */ +typedef struct base_jd_replay_jc { + /** + * Pointer to next entry in the list. A setting of NULL indicates the + * end of the list. + */ + u64 next; + + /** + * Pointer to the job chain. + */ + u64 jc; + +} base_jd_replay_jc; + +/* Maximum number of jobs allowed in a fragment chain in the payload of a + * replay job */ +#define BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT 256 + +/** @} end group base_api */ + +typedef struct base_profiling_controls { + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +} base_profiling_controls; + +/* Enable additional tracepoints for latency measurements (TL_ATOM_READY, + * TL_ATOM_DONE, TL_ATOM_PRIO_CHANGE, TL_ATOM_EVENT_POST) */ +#define BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS (1 << 0) + +/* Indicate that job dumping is enabled. This could affect certain timers + * to account for the performance impact. */ +#define BASE_TLSTREAM_JOB_DUMPING_ENABLED (1 << 1) + +#define BASE_TLSTREAM_FLAGS_MASK (BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS | \ + BASE_TLSTREAM_JOB_DUMPING_ENABLED) + +#endif /* _BASE_KERNEL_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_base_mem_priv.h b/drivers/gpu/arm/bifrost/mali_base_mem_priv.h new file mode 100644 index 000000000000..4a98a72cc37a --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_base_mem_priv.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _BASE_MEM_PRIV_H_ +#define _BASE_MEM_PRIV_H_ + +#define BASE_SYNCSET_OP_MSYNC (1U << 0) +#define BASE_SYNCSET_OP_CSYNC (1U << 1) + +/* + * This structure describe a basic memory coherency operation. + * It can either be: + * @li a sync from CPU to Memory: + * - type = ::BASE_SYNCSET_OP_MSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes + * - offset is ignored. + * @li a sync from Memory to CPU: + * - type = ::BASE_SYNCSET_OP_CSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes. + * - offset is ignored. + */ +struct basep_syncset { + base_mem_handle mem_handle; + u64 user_addr; + u64 size; + u8 type; + u8 padding[7]; +}; + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_base_vendor_specific_func.h b/drivers/gpu/arm/bifrost/mali_base_vendor_specific_func.h new file mode 100644 index 000000000000..be454a216a39 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_base_vendor_specific_func.h @@ -0,0 +1,24 @@ +/* + * + * (C) COPYRIGHT 2010, 2012-2013, 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _BASE_VENDOR_SPEC_FUNC_H_ +#define _BASE_VENDOR_SPEC_FUNC_H_ + +int kbase_get_vendor_specific_cpu_clock_speed(u32 * const); + +#endif /*_BASE_VENDOR_SPEC_FUNC_H_*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase.h b/drivers/gpu/arm/bifrost/mali_kbase.h new file mode 100644 index 000000000000..56b364e505d1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase.h @@ -0,0 +1,616 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_H_ +#define _KBASE_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) +#include +#endif +#include +#include +#include +#include +#include + +#include "mali_base_kernel.h" +#include +#include + +/* + * Include mali_kbase_defs.h first as this provides types needed by other local + * header files. + */ +#include "mali_kbase_defs.h" + +#include "mali_kbase_context.h" +#include "mali_kbase_strings.h" +#include "mali_kbase_mem_lowlevel.h" +#include "mali_kbase_trace_timeline.h" +#include "mali_kbase_js.h" +#include "mali_kbase_mem.h" +#include "mali_kbase_utility.h" +#include "mali_kbase_gpu_memory_debugfs.h" +#include "mali_kbase_mem_profile_debugfs.h" +#include "mali_kbase_debug_job_fault.h" +#include "mali_kbase_jd_debugfs.h" +#include "mali_kbase_gpuprops.h" +#include "mali_kbase_jm.h" +#include "mali_kbase_vinstr.h" + +#include "ipa/mali_kbase_ipa.h" + +#ifdef CONFIG_GPU_TRACEPOINTS +#include +#endif + +#ifndef u64_to_user_ptr +/* Introduced in Linux v4.6 */ +#define u64_to_user_ptr(x) ((void __user *)(uintptr_t)x) +#endif + +/* + * Kernel-side Base (KBase) APIs + */ + +struct kbase_device *kbase_device_alloc(void); +/* +* note: configuration attributes member of kbdev needs to have +* been setup before calling kbase_device_init +*/ + +/* +* API to acquire device list semaphore and return pointer +* to the device list head +*/ +const struct list_head *kbase_dev_list_get(void); +/* API to release the device list semaphore */ +void kbase_dev_list_put(const struct list_head *dev_list); + +int kbase_device_init(struct kbase_device * const kbdev); +void kbase_device_term(struct kbase_device *kbdev); +void kbase_device_free(struct kbase_device *kbdev); +int kbase_device_has_feature(struct kbase_device *kbdev, u32 feature); + +/* Needed for gator integration and for reporting vsync information */ +struct kbase_device *kbase_find_device(int minor); +void kbase_release_device(struct kbase_device *kbdev); + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value); + +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat); +void kbase_destroy_context(struct kbase_context *kctx); + +int kbase_jd_init(struct kbase_context *kctx); +void kbase_jd_exit(struct kbase_context *kctx); + +/** + * kbase_jd_submit - Submit atoms to the job dispatcher + * + * @kctx: The kbase context to submit to + * @user_addr: The address in user space of the struct base_jd_atom_v2 array + * @nr_atoms: The number of atoms in the array + * @stride: sizeof(struct base_jd_atom_v2) + * @uk6_atom: true if the atoms are legacy atoms (struct base_jd_atom_v2_uk6) + * + * Return: 0 on success or error code + */ +int kbase_jd_submit(struct kbase_context *kctx, + void __user *user_addr, u32 nr_atoms, u32 stride, + bool uk6_atom); + +/** + * kbase_jd_done_worker - Handle a job completion + * @data: a &struct work_struct + * + * This function requeues the job from the runpool (if it was soft-stopped or + * removed from NEXT registers). + * + * Removes it from the system if it finished/failed/was cancelled. + * + * Resolves dependencies to add dependent jobs to the context, potentially + * starting them if necessary (which may add more references to the context) + * + * Releases the reference to the context from the no-longer-running job. + * + * Handles retrying submission outside of IRQ context if it failed from within + * IRQ context. + */ +void kbase_jd_done_worker(struct work_struct *data); + +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code); +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom); +void kbase_jd_zap_context(struct kbase_context *kctx); +bool jd_done_nolock(struct kbase_jd_atom *katom, + struct list_head *completed_jobs_ctx); +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom); +bool jd_submit_atom(struct kbase_context *kctx, + const struct base_jd_atom_v2 *user_atom, + struct kbase_jd_atom *katom); +void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom); + +void kbase_job_done(struct kbase_device *kbdev, u32 done); + +/** + * kbase_job_slot_ctx_priority_check_locked(): - Check for lower priority atoms + * and soft stop them + * @kctx: Pointer to context to check. + * @katom: Pointer to priority atom. + * + * Atoms from @kctx on the same job slot as @katom, which have lower priority + * than @katom will be soft stopped and put back in the queue, so that atoms + * with higher priority can run. + * + * The hwaccess_lock must be held when calling this function. + */ +void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, + struct kbase_jd_atom *katom); + +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags); +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom); +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom); + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *event); +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent); +int kbase_event_pending(struct kbase_context *ctx); +int kbase_event_init(struct kbase_context *kctx); +void kbase_event_close(struct kbase_context *kctx); +void kbase_event_cleanup(struct kbase_context *kctx); +void kbase_event_wakeup(struct kbase_context *kctx); + +int kbase_process_soft_job(struct kbase_jd_atom *katom); +int kbase_prepare_soft_job(struct kbase_jd_atom *katom); +void kbase_finish_soft_job(struct kbase_jd_atom *katom); +void kbase_cancel_soft_job(struct kbase_jd_atom *katom); +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev); +void kbasep_remove_waiting_soft_job(struct kbase_jd_atom *katom); +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom); +#endif +int kbase_soft_event_update(struct kbase_context *kctx, + u64 event, + unsigned char new_status); + +bool kbase_replay_process(struct kbase_jd_atom *katom); + +void kbasep_soft_job_timeout_worker(unsigned long data); +void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt); + +/* api used internally for register access. Contains validation and tracing */ +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value); +int kbase_device_trace_buffer_install( + struct kbase_context *kctx, u32 *tb, size_t size); +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx); + +/* api to be ported per OS, only need to do the raw register access */ +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value); +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset); + +void kbasep_as_do_poke(struct work_struct *work); + +/** Returns the name associated with a Mali exception code + * + * This function is called from the interrupt handler when a GPU fault occurs. + * It reports the details of the fault using KBASE_DEBUG_PRINT_WARN. + * + * @param[in] kbdev The kbase device that the GPU fault occurred from. + * @param[in] exception_code exception code + * @return name associated with the exception code + */ +const char *kbase_exception_name(struct kbase_device *kbdev, + u32 exception_code); + +/** + * Check whether a system suspend is in progress, or has already been suspended + * + * The caller should ensure that either kbdev->pm.active_count_lock is held, or + * a dmb was executed recently (to ensure the value is most + * up-to-date). However, without a lock the value could change afterwards. + * + * @return false if a suspend is not in progress + * @return !=false otherwise + */ +static inline bool kbase_pm_is_suspending(struct kbase_device *kbdev) +{ + return kbdev->pm.suspending; +} + +/** + * Return the atom's ID, as was originally supplied by userspace in + * base_jd_atom_v2::atom_number + */ +static inline int kbase_jd_atom_id(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + int result; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->kctx == kctx); + + result = katom - &kctx->jctx.atoms[0]; + KBASE_DEBUG_ASSERT(result >= 0 && result <= BASE_JD_ATOM_COUNT); + return result; +} + +/** + * kbase_jd_atom_from_id - Return the atom structure for the given atom ID + * @kctx: Context pointer + * @id: ID of atom to retrieve + * + * Return: Pointer to struct kbase_jd_atom associated with the supplied ID + */ +static inline struct kbase_jd_atom *kbase_jd_atom_from_id( + struct kbase_context *kctx, int id) +{ + return &kctx->jctx.atoms[id]; +} + +/** + * Initialize the disjoint state + * + * The disjoint event count and state are both set to zero. + * + * Disjoint functions usage: + * + * The disjoint event count should be incremented whenever a disjoint event occurs. + * + * There are several cases which are regarded as disjoint behavior. Rather than just increment + * the counter during disjoint events we also increment the counter when jobs may be affected + * by what the GPU is currently doing. To facilitate this we have the concept of disjoint state. + * + * Disjoint state is entered during GPU reset and for the entire time that an atom is replaying + * (as part of the replay workaround). Increasing the disjoint state also increases the count of + * disjoint events. + * + * The disjoint state is then used to increase the count of disjoint events during job submission + * and job completion. Any atom submitted or completed while the disjoint state is greater than + * zero is regarded as a disjoint event. + * + * The disjoint event counter is also incremented immediately whenever a job is soft stopped + * and during context creation. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_init(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events + * called when a disjoint event has happened + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events only if the GPU is in a disjoint state + * + * This should be called when something happens which could be disjoint if the GPU + * is in a disjoint state. The state refcount keeps track of this. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev); + +/** + * Returns the count of disjoint events + * + * @param kbdev The kbase device + * @return the count of disjoint events + */ +u32 kbase_disjoint_event_get(struct kbase_device *kbdev); + +/** + * Increment the refcount state indicating that the GPU is in a disjoint state. + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * eventually after the disjoint state has completed @ref kbase_disjoint_state_down + * should be called + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_up(struct kbase_device *kbdev); + +/** + * Decrement the refcount state + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * + * Called after @ref kbase_disjoint_state_up once the disjoint state is over + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_down(struct kbase_device *kbdev); + +/** + * If a job is soft stopped and the number of contexts is >= this value + * it is reported as a disjoint event + */ +#define KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD 2 + +#if !defined(UINT64_MAX) + #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#endif + +#if KBASE_TRACE_ENABLE +void kbasep_trace_debugfs_init(struct kbase_device *kbdev); + +#ifndef CONFIG_MALI_SYSTEM_TRACE +/** Add trace values about a job-slot + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, 0) + +/** Add trace values about a job-slot, with info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, info_val) + +/** Add trace values about a ctx refcount + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, 0) +/** Add trace values about a ctx refcount, and info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, info_val) + +/** Add trace values (no slot or refcount) + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + 0, 0, 0, info_val) + +/** Clear the trace */ +#define KBASE_TRACE_CLEAR(kbdev) \ + kbasep_trace_clear(kbdev) + +/** Dump the slot trace */ +#define KBASE_TRACE_DUMP(kbdev) \ + kbasep_trace_dump(kbdev) + +/** PRIVATE - do not use directly. Use KBASE_TRACE_ADD() instead */ +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val); +/** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */ +void kbasep_trace_clear(struct kbase_device *kbdev); +#else /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +/* Dispatch kbase trace events as system trace events */ +#include +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + trace_mali_##code(jobslot, 0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + trace_mali_##code(jobslot, info_val) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + trace_mali_##code(refcount, 0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + trace_mali_##code(refcount, info_val) + +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val)\ + trace_mali_##code(gpu_addr, info_val) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) + +#endif /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +#else +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + } while (0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(refcount);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD(kbdev, code, subcode, ctx, katom, val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(subcode);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#endif /* KBASE_TRACE_ENABLE */ +/** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */ +void kbasep_trace_dump(struct kbase_device *kbdev); + +#ifdef CONFIG_MALI_DEBUG +/** + * kbase_set_driver_inactive - Force driver to go inactive + * @kbdev: Device pointer + * @inactive: true if driver should go inactive, false otherwise + * + * Forcing the driver inactive will cause all future IOCTLs to wait until the + * driver is made active again. This is intended solely for the use of tests + * which require that no jobs are running while the test executes. + */ +void kbase_set_driver_inactive(struct kbase_device *kbdev, bool inactive); +#endif /* CONFIG_MALI_DEBUG */ + + +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) + +/* kbase_io_history_init - initialize data struct for register access history + * + * @kbdev The register history to initialize + * @n The number of register accesses that the buffer could hold + * + * @return 0 if successfully initialized, failure otherwise + */ +int kbase_io_history_init(struct kbase_io_history *h, u16 n); + +/* kbase_io_history_term - uninit all resources for the register access history + * + * @h The register history to terminate + */ +void kbase_io_history_term(struct kbase_io_history *h); + +/* kbase_io_history_dump - print the register history to the kernel ring buffer + * + * @kbdev Pointer to kbase_device containing the register history to dump + */ +void kbase_io_history_dump(struct kbase_device *kbdev); + +/** + * kbase_io_history_resize - resize the register access history buffer. + * + * @h: Pointer to a valid register history to resize + * @new_size: Number of accesses the buffer could hold + * + * A successful resize will clear all recent register accesses. + * If resizing fails for any reason (e.g., could not allocate memory, invalid + * buffer size) then the original buffer will be kept intact. + * + * @return 0 if the buffer was resized, failure otherwise + */ +int kbase_io_history_resize(struct kbase_io_history *h, u16 new_size); + +#else /* CONFIG_DEBUG_FS */ + +#define kbase_io_history_init(...) ((int)0) + +#define kbase_io_history_term CSTD_NOP + +#define kbase_io_history_dump CSTD_NOP + +#define kbase_io_history_resize CSTD_NOP + +#endif /* CONFIG_DEBUG_FS */ + + +#endif + + + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.c b/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.c new file mode 100644 index 000000000000..6b3559d93351 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.c @@ -0,0 +1,210 @@ +/* + * + * (C) COPYRIGHT 2013-2015,2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include + +/* This function is used to solve an HW issue with single iterator GPUs. + * If a fragment job is soft-stopped on the edge of its bounding box, can happen that the + * restart index is out of bounds and the rerun causes a tile range fault. If this happens + * we try to clamp the restart index to a correct value and rerun the job. + */ +/* Mask of X and Y coordinates for the coordinates words in the descriptors*/ +#define X_COORDINATE_MASK 0x00000FFF +#define Y_COORDINATE_MASK 0x0FFF0000 +/* Max number of words needed from the fragment shader job descriptor */ +#define JOB_HEADER_SIZE_IN_WORDS 10 +#define JOB_HEADER_SIZE (JOB_HEADER_SIZE_IN_WORDS*sizeof(u32)) + +/* Word 0: Status Word */ +#define JOB_DESC_STATUS_WORD 0 +/* Word 1: Restart Index */ +#define JOB_DESC_RESTART_INDEX_WORD 1 +/* Word 2: Fault address low word */ +#define JOB_DESC_FAULT_ADDR_LOW_WORD 2 +/* Word 8: Minimum Tile Coordinates */ +#define FRAG_JOB_DESC_MIN_TILE_COORD_WORD 8 +/* Word 9: Maximum Tile Coordinates */ +#define FRAG_JOB_DESC_MAX_TILE_COORD_WORD 9 + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom) +{ + struct device *dev = katom->kctx->kbdev->dev; + u32 clamped = 0; + struct kbase_va_region *region; + struct tagged_addr *page_array; + u64 page_index; + u32 offset = katom->jc & (~PAGE_MASK); + u32 *page_1 = NULL; + u32 *page_2 = NULL; + u32 job_header[JOB_HEADER_SIZE_IN_WORDS]; + void *dst = job_header; + u32 minX, minY, maxX, maxY; + u32 restartX, restartY; + struct page *p; + u32 copy_size; + + dev_warn(dev, "Called TILE_RANGE_FAULT workaround clamping function.\n"); + if (!(katom->core_req & BASE_JD_REQ_FS)) + return 0; + + kbase_gpu_vm_lock(katom->kctx); + region = kbase_region_tracker_find_region_enclosing_address(katom->kctx, + katom->jc); + if (!region || (region->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_array = kbase_get_cpu_phy_pages(region); + if (!page_array) + goto out_unlock; + + page_index = (katom->jc >> PAGE_SHIFT) - region->start_pfn; + + p = phys_to_page(as_phys_addr_t(page_array[page_index])); + + /* we need the first 10 words of the fragment shader job descriptor. + * We need to check that the offset + 10 words is less that the page + * size otherwise we need to load the next page. + * page_size_overflow will be equal to 0 in case the whole descriptor + * is within the page > 0 otherwise. + */ + copy_size = MIN(PAGE_SIZE - offset, JOB_HEADER_SIZE); + + page_1 = kmap_atomic(p); + + /* page_1 is a u32 pointer, offset is expressed in bytes */ + page_1 += offset>>2; + + kbase_sync_single_for_cpu(katom->kctx->kbdev, + kbase_dma_addr(p) + offset, + copy_size, DMA_BIDIRECTIONAL); + + memcpy(dst, page_1, copy_size); + + /* The data needed overflows page the dimension, + * need to map the subsequent page */ + if (copy_size < JOB_HEADER_SIZE) { + p = phys_to_page(as_phys_addr_t(page_array[page_index + 1])); + page_2 = kmap_atomic(p); + + kbase_sync_single_for_cpu(katom->kctx->kbdev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, DMA_BIDIRECTIONAL); + + memcpy(dst + copy_size, page_2, JOB_HEADER_SIZE - copy_size); + } + + /* We managed to correctly map one or two pages (in case of overflow) */ + /* Get Bounding Box data and restart index from fault address low word */ + minX = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & X_COORDINATE_MASK; + minY = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & Y_COORDINATE_MASK; + maxX = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & X_COORDINATE_MASK; + maxY = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & Y_COORDINATE_MASK; + restartX = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & X_COORDINATE_MASK; + restartY = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & Y_COORDINATE_MASK; + + dev_warn(dev, "Before Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Set the restart index to the one which generated the fault*/ + job_header[JOB_DESC_RESTART_INDEX_WORD] = + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD]; + + if (restartX < minX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minX) | restartY; + dev_warn(dev, + "Clamping restart X index to minimum. %08x clamped to %08x\n", + restartX, minX); + clamped = 1; + } + if (restartY < minY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minY) | restartX; + dev_warn(dev, + "Clamping restart Y index to minimum. %08x clamped to %08x\n", + restartY, minY); + clamped = 1; + } + if (restartX > maxX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxX) | restartY; + dev_warn(dev, + "Clamping restart X index to maximum. %08x clamped to %08x\n", + restartX, maxX); + clamped = 1; + } + if (restartY > maxY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxY) | restartX; + dev_warn(dev, + "Clamping restart Y index to maximum. %08x clamped to %08x\n", + restartY, maxY); + clamped = 1; + } + + if (clamped) { + /* Reset the fault address low word + * and set the job status to STOPPED */ + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] = 0x0; + job_header[JOB_DESC_STATUS_WORD] = BASE_JD_EVENT_STOPPED; + dev_warn(dev, "After Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Flush CPU cache to update memory for future GPU reads*/ + memcpy(page_1, dst, copy_size); + p = phys_to_page(as_phys_addr_t(page_array[page_index])); + + kbase_sync_single_for_device(katom->kctx->kbdev, + kbase_dma_addr(p) + offset, + copy_size, DMA_TO_DEVICE); + + if (copy_size < JOB_HEADER_SIZE) { + memcpy(page_2, dst + copy_size, + JOB_HEADER_SIZE - copy_size); + p = phys_to_page(as_phys_addr_t(page_array[page_index + + 1])); + + kbase_sync_single_for_device(katom->kctx->kbdev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, + DMA_TO_DEVICE); + } + } + if (copy_size < JOB_HEADER_SIZE) + kunmap_atomic(page_2); + + kunmap_atomic(page_1); + +out_unlock: + kbase_gpu_vm_unlock(katom->kctx); + return clamped; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.h b/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.h new file mode 100644 index 000000000000..099a29861672 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_10969_workaround.h @@ -0,0 +1,23 @@ +/* + * + * (C) COPYRIGHT 2013-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_10969_WORKAROUND_ +#define _KBASE_10969_WORKAROUND_ + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom); + +#endif /* _KBASE_10969_WORKAROUND_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c new file mode 100644 index 000000000000..f910fe970feb --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c @@ -0,0 +1,102 @@ +/* + * + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include +#include + +#ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_MALI_DEBUG + +static int kbase_as_fault_read(struct seq_file *sfile, void *data) +{ + uintptr_t as_no = (uintptr_t) sfile->private; + + struct list_head *entry; + const struct list_head *kbdev_list; + struct kbase_device *kbdev = NULL; + + kbdev_list = kbase_dev_list_get(); + + list_for_each(entry, kbdev_list) { + kbdev = list_entry(entry, struct kbase_device, entry); + + if(kbdev->debugfs_as_read_bitmap & (1ULL << as_no)) { + + /* don't show this one again until another fault occors */ + kbdev->debugfs_as_read_bitmap &= ~(1ULL << as_no); + + /* output the last page fault addr */ + seq_printf(sfile, "%llu\n", (u64) kbdev->as[as_no].fault_addr); + } + + } + + kbase_dev_list_put(kbdev_list); + + return 0; +} + +static int kbase_as_fault_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbase_as_fault_read , in->i_private); +} + +static const struct file_operations as_fault_fops = { + .open = kbase_as_fault_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_DEBUG_FS */ + +/* + * Initialize debugfs entry for each address space + */ +void kbase_as_fault_debugfs_init(struct kbase_device *kbdev) +{ +#ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_MALI_DEBUG + uint i; + char as_name[64]; + struct dentry *debugfs_directory; + + kbdev->debugfs_as_read_bitmap = 0ULL; + + KBASE_DEBUG_ASSERT(kbdev->nr_hw_address_spaces); + KBASE_DEBUG_ASSERT(sizeof(kbdev->as[0].fault_addr) == sizeof(u64)); + + debugfs_directory = debugfs_create_dir("address_spaces", + kbdev->mali_debugfs_directory); + + if(debugfs_directory) { + for(i = 0; i < kbdev->nr_hw_address_spaces; i++) { + snprintf(as_name, ARRAY_SIZE(as_name), "as%u", i); + debugfs_create_file(as_name, S_IRUGO, + debugfs_directory, (void*) ((uintptr_t) i), &as_fault_fops); + } + } + else + dev_warn(kbdev->dev, "unable to create address_spaces debugfs directory"); + +#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_DEBUG_FS */ + return; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h new file mode 100644 index 000000000000..3ed2248897fc --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h @@ -0,0 +1,45 @@ +/* + * + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_AS_FAULT_DEBUG_FS_H +#define _KBASE_AS_FAULT_DEBUG_FS_H + +/** + * kbase_as_fault_debugfs_init() - Add debugfs files for reporting page faults + * + * @kbdev: Pointer to kbase_device + */ +void kbase_as_fault_debugfs_init(struct kbase_device *kbdev); + +/** + * kbase_as_fault_debugfs_new() - make the last fault available on debugfs + * + * @kbdev: Pointer to kbase_device + * @as_no: The address space the fault occurred on + */ +static inline void +kbase_as_fault_debugfs_new(struct kbase_device *kbdev, int as_no) +{ +#ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_MALI_DEBUG + kbdev->debugfs_as_read_bitmap |= (1ULL << as_no); +#endif /* CONFIG_DEBUG_FS */ +#endif /* CONFIG_MALI_DEBUG */ + return; +} + +#endif /*_KBASE_AS_FAULT_DEBUG_FS_H*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.c b/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.c new file mode 100644 index 000000000000..1d11de67aa80 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.c @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Cache Policy API. + */ + +#include "mali_kbase_cache_policy.h" + +/* + * The output flags should be a combination of the following values: + * KBASE_REG_CPU_CACHED: CPU cache should be enabled. + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages) +{ + u32 cache_flags = 0; + + CSTD_UNUSED(nr_pages); + + if (flags & BASE_MEM_CACHED_CPU) + cache_flags |= KBASE_REG_CPU_CACHED; + + return cache_flags; +} + + +void kbase_sync_single_for_device(struct kbase_device *kbdev, dma_addr_t handle, + size_t size, enum dma_data_direction dir) +{ + dma_sync_single_for_device(kbdev->dev, handle, size, dir); +} + + +void kbase_sync_single_for_cpu(struct kbase_device *kbdev, dma_addr_t handle, + size_t size, enum dma_data_direction dir) +{ + dma_sync_single_for_cpu(kbdev->dev, handle, size, dir); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.h b/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.h new file mode 100644 index 000000000000..0c18bdb357b0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_cache_policy.h @@ -0,0 +1,45 @@ +/* + * + * (C) COPYRIGHT 2012-2013, 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Cache Policy API. + */ + +#ifndef _KBASE_CACHE_POLICY_H_ +#define _KBASE_CACHE_POLICY_H_ + +#include "mali_kbase.h" +#include "mali_base_kernel.h" + +/** + * kbase_cache_enabled - Choose the cache policy for a specific region + * @flags: flags describing attributes of the region + * @nr_pages: total number of pages (backed or not) for the region + * + * Tells whether the CPU and GPU caches should be enabled or not for a specific + * region. + * This function can be modified to customize the cache policy depending on the + * flags and size of the region. + * + * Return: a combination of %KBASE_REG_CPU_CACHED and %KBASE_REG_GPU_CACHED + * depending on the cache policy + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages); + +#endif /* _KBASE_CACHE_POLICY_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_config.c b/drivers/gpu/arm/bifrost/mali_kbase_config.c new file mode 100644 index 000000000000..fb615ae02ead --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_config.c @@ -0,0 +1,51 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +int kbasep_platform_device_init(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs_p; + + platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; + if (platform_funcs_p && platform_funcs_p->platform_init_func) + return platform_funcs_p->platform_init_func(kbdev); + + return 0; +} + +void kbasep_platform_device_term(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs_p; + + platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; + if (platform_funcs_p && platform_funcs_p->platform_term_func) + platform_funcs_p->platform_term_func(kbdev); +} + +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed) +{ + KBASE_DEBUG_ASSERT(NULL != clock_speed); + + *clock_speed = 100; + return 0; +} + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_config.h b/drivers/gpu/arm/bifrost/mali_kbase_config.h new file mode 100644 index 000000000000..212e3b14d96c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_config.h @@ -0,0 +1,343 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_config.h + * Configuration API and Attributes for KBase + */ + +#ifndef _KBASE_CONFIG_H_ +#define _KBASE_CONFIG_H_ + +#include + +#include +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_config Configuration API and Attributes + * @{ + */ + +#include + +/* Forward declaration of struct kbase_device */ +struct kbase_device; + +/** + * kbase_platform_funcs_conf - Specifies platform init/term function pointers + * + * Specifies the functions pointers for platform specific initialization and + * termination. By default no functions are required. No additional platform + * specific control is necessary. + */ +struct kbase_platform_funcs_conf { + /** + * platform_init_func - platform specific init function pointer + * @kbdev - kbase_device pointer + * + * Returns 0 on success, negative error code otherwise. + * + * Function pointer for platform specific initialization or NULL if no + * initialization function is required. At the point this the GPU is + * not active and its power and clocks are in unknown (platform specific + * state) as kbase doesn't yet have control of power and clocks. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed (and possibly initialized) in here. + */ + int (*platform_init_func)(struct kbase_device *kbdev); + /** + * platform_term_func - platform specific termination function pointer + * @kbdev - kbase_device pointer + * + * Function pointer for platform specific termination or NULL if no + * termination function is required. At the point this the GPU will be + * idle but still powered and clocked. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed (and possibly terminated) in here. + */ + void (*platform_term_func)(struct kbase_device *kbdev); +}; + +/* + * @brief Specifies the callbacks for power management + * + * By default no callbacks will be made and the GPU must not be powered off. + */ +struct kbase_pm_callback_conf { + /** Callback for when the GPU is idle and the power to it can be switched off. + * + * The system integrator can decide whether to either do nothing, just switch off + * the clocks to the GPU, or to completely power down the GPU. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsibility to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + */ + void (*power_off_callback)(struct kbase_device *kbdev); + + /** Callback for when the GPU is about to become active and power must be supplied. + * + * This function must not return until the GPU is powered and clocked sufficiently for register access to + * succeed. The return value specifies whether the GPU was powered down since the call to power_off_callback. + * If the GPU state has been lost then this function must return 1, otherwise it should return 0. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsibility to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + * + * The return value of the first call to this function is ignored. + * + * @return 1 if the GPU state may have been lost, 0 otherwise. + */ + int (*power_on_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is requesting a suspend and GPU power + * must be switched off. + * + * Note that if this callback is present, then this may be called + * without a preceding call to power_off_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_off_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_suspend_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is resuming from a suspend and GPU + * power must be switched on. + * + * Note that if this callback is present, then this may be called + * without a following call to power_on_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_on_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_resume_callback)(struct kbase_device *kbdev); + + /** Callback for handling runtime power management initialization. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * will become active from calls made to the OS from within this function. + * The runtime calls can be triggered by calls from @ref power_off_callback and @ref power_on_callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return 0 on success, else int error code. + */ + int (*power_runtime_init_callback)(struct kbase_device *kbdev); + + /** Callback for handling runtime power management termination. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * should no longer be called by the OS on completion of this function. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + void (*power_runtime_term_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-off power management callback + * + * For linux this callback will be called by the kernel runtime_suspend callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return 0 on success, else OS error code. + */ + void (*power_runtime_off_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-on power management callback + * + * For linux this callback will be called by the kernel runtime_resume callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + int (*power_runtime_on_callback)(struct kbase_device *kbdev); + + /* + * Optional callback for checking if GPU can be suspended when idle + * + * This callback will be called by the runtime power management core + * when the reference count goes to 0 to provide notification that the + * GPU now seems idle. + * + * If this callback finds that the GPU can't be powered off, or handles + * suspend by powering off directly or queueing up a power off, a + * non-zero value must be returned to prevent the runtime PM core from + * also triggering a suspend. + * + * Returning 0 will cause the runtime PM core to conduct a regular + * autosuspend. + * + * This callback is optional and if not provided regular autosuspend + * will be triggered. + * + * Note: The Linux kernel must have CONFIG_PM_RUNTIME enabled to use + * this feature. + * + * Return 0 if GPU can be suspended, positive value if it can not be + * suspeneded by runtime PM, else OS error code + */ + int (*power_runtime_idle_callback)(struct kbase_device *kbdev); +}; + +/** + * kbase_cpuprops_get_default_clock_speed - default for CPU_SPEED_FUNC + * @clock_speed - see kbase_cpu_clk_speed_func for details on the parameters + * + * Returns 0 on success, negative error code otherwise. + * + * Default implementation of CPU_SPEED_FUNC. This function sets clock_speed + * to 100, so will be an underestimate for any real system. + */ +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed); + +/** + * kbase_cpu_clk_speed_func - Type of the function pointer for CPU_SPEED_FUNC + * @param clock_speed - pointer to store the current CPU clock speed in MHz + * + * Returns 0 on success, otherwise negative error code. + * + * This is mainly used to implement OpenCL's clGetDeviceInfo(). + */ +typedef int (*kbase_cpu_clk_speed_func) (u32 *clock_speed); + +/** + * kbase_gpu_clk_speed_func - Type of the function pointer for GPU_SPEED_FUNC + * @param clock_speed - pointer to store the current GPU clock speed in MHz + * + * Returns 0 on success, otherwise negative error code. + * When an error is returned the caller assumes maximum GPU speed stored in + * gpu_freq_khz_max. + * + * If the system timer is not available then this function is required + * for the OpenCL queue profiling to return correct timing information. + * + */ +typedef int (*kbase_gpu_clk_speed_func) (u32 *clock_speed); + +#ifdef CONFIG_OF +struct kbase_platform_config { +}; +#else + +/* + * @brief Specifies start and end of I/O memory region. + */ +struct kbase_io_memory_region { + u64 start; + u64 end; +}; + +/* + * @brief Specifies I/O related resources like IRQs and memory region for I/O operations. + */ +struct kbase_io_resources { + u32 job_irq_number; + u32 mmu_irq_number; + u32 gpu_irq_number; + struct kbase_io_memory_region io_memory_region; +}; + +struct kbase_platform_config { + const struct kbase_io_resources *io_resources; +}; + +#endif /* CONFIG_OF */ + +/** + * @brief Gets the pointer to platform config. + * + * @return Pointer to the platform config + */ +struct kbase_platform_config *kbase_get_platform_config(void); + +/** + * kbasep_platform_device_init: - Platform specific call to initialize hardware + * @kbdev: kbase device pointer + * + * Function calls a platform defined routine if specified in the configuration + * attributes. The routine can initialize any hardware and context state that + * is required for the GPU block to function. + * + * Return: 0 if no errors have been found in the config. + * Negative error code otherwise. + */ +int kbasep_platform_device_init(struct kbase_device *kbdev); + +/** + * kbasep_platform_device_term - Platform specific call to terminate hardware + * @kbdev: Kbase device pointer + * + * Function calls a platform defined routine if specified in the configuration + * attributes. The routine can destroy any platform specific context state and + * shut down any hardware functionality that are outside of the Power Management + * callbacks. + * + */ +void kbasep_platform_device_term(struct kbase_device *kbdev); + + +/** + * kbase_platform_early_init - Early initialisation of the platform code + * + * This function will be called when the module is loaded to perform any + * early initialisation required by the platform code. Such as reading + * platform specific device tree entries for the GPU. + * + * Return: 0 for success, any other fail causes module initialisation to fail + */ +int kbase_platform_early_init(void); + +#ifndef CONFIG_OF +/** + * kbase_platform_register - Register a platform device for the GPU + * + * This can be used to register a platform device on systems where device tree + * is not enabled and the platform initialisation code in the kernel doesn't + * create the GPU device. Where possible device tree should be used instead. + * + * Return: 0 for success, any other fail causes module initialisation to fail + */ +int kbase_platform_register(void); + +/** + * kbase_platform_unregister - Unregister a fake platform device + * + * Unregister the platform device created with kbase_platform_register() + */ +void kbase_platform_unregister(void); +#endif + + /** @} *//* end group kbase_config */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_CONFIG_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h new file mode 100644 index 000000000000..69079e7d9680 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h @@ -0,0 +1,226 @@ +/* + * + * (C) COPYRIGHT 2013-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_config_defaults.h + * + * Default values for configuration settings + * + */ + +#ifndef _KBASE_CONFIG_DEFAULTS_H_ +#define _KBASE_CONFIG_DEFAULTS_H_ + +/* Include mandatory definitions per platform */ +#include + +/** +* Boolean indicating whether the driver is configured to be secure at +* a potential loss of performance. +* +* This currently affects only r0p0-15dev0 HW and earlier. +* +* On r0p0-15dev0 HW and earlier, there are tradeoffs between security and +* performance: +* +* - When this is set to true, the driver remains fully secure, +* but potentially loses performance compared with setting this to +* false. +* - When set to false, the driver is open to certain security +* attacks. +* +* From r0p0-00rel0 and onwards, there is no security loss by setting +* this to false, and no performance loss by setting it to +* true. +*/ +#define DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE false + +enum { + /** + * Use unrestricted Address ID width on the AXI bus. + */ + KBASE_AID_32 = 0x0, + + /** + * Restrict GPU to a half of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_16 = 0x3, + + /** + * Restrict GPU to a quarter of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_8 = 0x2, + + /** + * Restrict GPU to an eighth of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_4 = 0x1 +}; + +/** + * Default setting for read Address ID limiting on AXI bus. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_ARID_LIMIT KBASE_AID_32 + +/** + * Default setting for write Address ID limiting on AXI. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_AWID_LIMIT KBASE_AID_32 + +/** + * Default UMP device mapping. A UMP_DEVICE__SHIFT value which + * defines which UMP device this GPU should be mapped to. + */ +#define DEFAULT_UMP_GPU_DEVICE_SHIFT UMP_DEVICE_Z_SHIFT + +/* + * Default period for DVFS sampling + */ +#define DEFAULT_PM_DVFS_PERIOD 100 /* 100ms */ + +/* + * Power Management poweroff tick granuality. This is in nanoseconds to + * allow HR timer support. + * + * On each scheduling tick, the power manager core may decide to: + * -# Power off one or more shader cores + * -# Power off the entire GPU + */ +#define DEFAULT_PM_GPU_POWEROFF_TICK_NS (400000) /* 400us */ + +/* + * Power Manager number of ticks before shader cores are powered off + */ +#define DEFAULT_PM_POWEROFF_TICK_SHADER (2) /* 400-800us */ + +/* + * Power Manager number of ticks before GPU is powered off + */ +#define DEFAULT_PM_POWEROFF_TICK_GPU (2) /* 400-800us */ + +/* + * Default scheduling tick granuality + */ +#define DEFAULT_JS_SCHEDULING_PERIOD_NS (100000000u) /* 100ms */ + +/* + * Default minimum number of scheduling ticks before jobs are soft-stopped. + * + * This defines the time-slice for a job (which may be different from that of a + * context) + */ +#define DEFAULT_JS_SOFT_STOP_TICKS (1) /* 100ms-200ms */ + +/* + * Default minimum number of scheduling ticks before CL jobs are soft-stopped. + */ +#define DEFAULT_JS_SOFT_STOP_TICKS_CL (1) /* 100ms-200ms */ + +/* + * Default minimum number of scheduling ticks before jobs are hard-stopped + */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS (50) /* 5s */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS_8408 (300) /* 30s */ + +/* + * Default minimum number of scheduling ticks before CL jobs are hard-stopped. + */ +#define DEFAULT_JS_HARD_STOP_TICKS_CL (50) /* 5s */ + +/* + * Default minimum number of scheduling ticks before jobs are hard-stopped + * during dumping + */ +#define DEFAULT_JS_HARD_STOP_TICKS_DUMPING (15000) /* 1500s */ + +/* + * Default timeout for some software jobs, after which the software event wait + * jobs will be cancelled. + */ +#define DEFAULT_JS_SOFT_JOB_TIMEOUT (3000) /* 3s */ + +/* + * Default minimum number of scheduling ticks before the GPU is reset to clear a + * "stuck" job + */ +#define DEFAULT_JS_RESET_TICKS_SS (55) /* 5.5s */ +#define DEFAULT_JS_RESET_TICKS_SS_8408 (450) /* 45s */ + +/* + * Default minimum number of scheduling ticks before the GPU is reset to clear a + * "stuck" CL job. + */ +#define DEFAULT_JS_RESET_TICKS_CL (55) /* 5.5s */ + +/* + * Default minimum number of scheduling ticks before the GPU is reset to clear a + * "stuck" job during dumping. + */ +#define DEFAULT_JS_RESET_TICKS_DUMPING (15020) /* 1502s */ + +/* + * Default number of milliseconds given for other jobs on the GPU to be + * soft-stopped when the GPU needs to be reset. + */ +#define DEFAULT_RESET_TIMEOUT_MS (3000) /* 3s */ + +/* + * Default timeslice that a context is scheduled in for, in nanoseconds. + * + * When a context has used up this amount of time across its jobs, it is + * scheduled out to let another run. + * + * @note the resolution is nanoseconds (ns) here, because that's the format + * often used by the OS. + */ +#define DEFAULT_JS_CTX_TIMESLICE_NS (50000000) /* 50ms */ + +/* + * Perform GPU power down using only platform specific code, skipping DDK power + * management. + * + * If this is non-zero then kbase will avoid powering down shader cores, the + * tiler, and the L2 cache, instead just powering down the entire GPU through + * platform specific code. This may be required for certain platform + * integrations. + * + * Note that as this prevents kbase from powering down shader cores, this limits + * the available power policies to coarse_demand and always_on. + */ +#define PLATFORM_POWER_DOWN_ONLY (0) + +#endif /* _KBASE_CONFIG_DEFAULTS_H_ */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_context.c b/drivers/gpu/arm/bifrost/mali_kbase_context.c new file mode 100644 index 000000000000..ad20e6135ba5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_context.c @@ -0,0 +1,362 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel context APIs + */ + +#include +#include +#include +#include +#include + +/** + * kbase_create_context() - Create a kernel base context. + * @kbdev: Kbase device + * @is_compat: Force creation of a 32-bit context + * + * Allocate and init a kernel base context. + * + * Return: new kbase context + */ +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat) +{ + struct kbase_context *kctx; + int err; + struct page *p; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* zero-inited as lot of code assume it's zero'ed out on create */ + kctx = vzalloc(sizeof(*kctx)); + + if (!kctx) + goto out; + + /* creating a context is considered a disjoint event */ + kbase_disjoint_event(kbdev); + + kctx->kbdev = kbdev; + kctx->as_nr = KBASEP_AS_NR_INVALID; + atomic_set(&kctx->refcount, 0); + if (is_compat) + kbase_ctx_flag_set(kctx, KCTX_COMPAT); +#ifdef CONFIG_MALI_TRACE_TIMELINE + kctx->timeline.owner_tgid = task_tgid_nr(current); +#endif + atomic_set(&kctx->setup_complete, 0); + atomic_set(&kctx->setup_in_progress, 0); + spin_lock_init(&kctx->mm_update_lock); + kctx->process_mm = NULL; + atomic_set(&kctx->nonmapped_pages, 0); + kctx->slots_pullable = 0; + kctx->tgid = current->tgid; + kctx->pid = current->pid; + + err = kbase_mem_pool_init(&kctx->mem_pool, + kbdev->mem_pool_max_size_default, + KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER, + kctx->kbdev, + &kbdev->mem_pool); + if (err) + goto free_kctx; + + err = kbase_mem_pool_init(&kctx->lp_mem_pool, + (kbdev->mem_pool_max_size_default >> 9), + KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, + kctx->kbdev, + &kbdev->lp_mem_pool); + if (err) + goto free_mem_pool; + + err = kbase_mem_evictable_init(kctx); + if (err) + goto free_both_pools; + + atomic_set(&kctx->used_pages, 0); + + err = kbase_jd_init(kctx); + if (err) + goto deinit_evictable; + + err = kbasep_js_kctx_init(kctx); + if (err) + goto free_jd; /* safe to call kbasep_js_kctx_term in this case */ + + err = kbase_event_init(kctx); + if (err) + goto free_jd; + + atomic_set(&kctx->drain_pending, 0); + + mutex_init(&kctx->reg_lock); + + mutex_init(&kctx->mem_partials_lock); + INIT_LIST_HEAD(&kctx->mem_partials); + + INIT_LIST_HEAD(&kctx->waiting_soft_jobs); + spin_lock_init(&kctx->waiting_soft_jobs_lock); +#ifdef CONFIG_KDS + INIT_LIST_HEAD(&kctx->waiting_kds_resource); +#endif + err = kbase_dma_fence_init(kctx); + if (err) + goto free_event; + + err = kbase_mmu_init(kctx); + if (err) + goto term_dma_fence; + + do { + err = kbase_mem_pool_grow(&kctx->mem_pool, + MIDGARD_MMU_BOTTOMLEVEL); + if (err) + goto pgd_no_mem; + + mutex_lock(&kctx->mmu_lock); + kctx->pgd = kbase_mmu_alloc_pgd(kctx); + mutex_unlock(&kctx->mmu_lock); + } while (!kctx->pgd); + + p = kbase_mem_alloc_page(&kctx->mem_pool); + if (!p) + goto no_sink_page; + kctx->aliasing_sink_page = as_tagged(page_to_phys(p)); + + init_waitqueue_head(&kctx->event_queue); + + kctx->cookies = KBASE_COOKIE_MASK; + + /* Make sure page 0 is not used... */ + err = kbase_region_tracker_init(kctx); + if (err) + goto no_region_tracker; + + err = kbase_sticky_resource_init(kctx); + if (err) + goto no_sticky; + + err = kbase_jit_init(kctx); + if (err) + goto no_jit; +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_set(&kctx->jctx.work_id, 0); +#endif +#ifdef CONFIG_MALI_TRACE_TIMELINE + atomic_set(&kctx->timeline.jd_atoms_in_flight, 0); +#endif + + kctx->id = atomic_add_return(1, &(kbdev->ctx_num)) - 1; + + mutex_init(&kctx->vinstr_cli_lock); + + setup_timer(&kctx->soft_job_timeout, + kbasep_soft_job_timeout_worker, + (uintptr_t)kctx); + + return kctx; + +no_jit: + kbase_gpu_vm_lock(kctx); + kbase_sticky_resource_term(kctx); + kbase_gpu_vm_unlock(kctx); +no_sticky: + kbase_region_tracker_term(kctx); +no_region_tracker: + kbase_mem_pool_free(&kctx->mem_pool, p, false); +no_sink_page: + /* VM lock needed for the call to kbase_mmu_free_pgd */ + kbase_gpu_vm_lock(kctx); + kbase_mmu_free_pgd(kctx); + kbase_gpu_vm_unlock(kctx); +pgd_no_mem: + kbase_mmu_term(kctx); +term_dma_fence: + kbase_dma_fence_term(kctx); +free_event: + kbase_event_cleanup(kctx); +free_jd: + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + kbase_jd_exit(kctx); +deinit_evictable: + kbase_mem_evictable_deinit(kctx); +free_both_pools: + kbase_mem_pool_term(&kctx->lp_mem_pool); +free_mem_pool: + kbase_mem_pool_term(&kctx->mem_pool); +free_kctx: + vfree(kctx); +out: + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_create_context); + +static void kbase_reg_pending_dtor(struct kbase_va_region *reg) +{ + dev_dbg(reg->kctx->kbdev->dev, "Freeing pending unmapped region\n"); + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); + kfree(reg); +} + +/** + * kbase_destroy_context - Destroy a kernel base context. + * @kctx: Context to destroy + * + * Calls kbase_destroy_os_context() to free OS specific structures. + * Will release all outstanding regions. + */ +void kbase_destroy_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + int pages; + unsigned long pending_regions_to_clean; + unsigned long flags; + struct page *p; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_CTX_DESTROY, kctx, NULL, 0u, 0u); + + /* Ensure the core is powered up for the destroy process */ + /* A suspend won't happen here, because we're in a syscall from a userspace + * thread. */ + kbase_pm_context_active(kbdev); + + kbase_jd_zap_context(kctx); + +#ifdef CONFIG_DEBUG_FS + /* Removing the rest of the debugfs entries here as we want to keep the + * atom debugfs interface alive until all atoms have completed. This + * is useful for debugging hung contexts. */ + debugfs_remove_recursive(kctx->kctx_dentry); +#endif + + kbase_event_cleanup(kctx); + + /* + * JIT must be terminated before the code below as it must be called + * without the region lock being held. + * The code above ensures no new JIT allocations can be made by + * by the time we get to this point of context tear down. + */ + kbase_jit_term(kctx); + + kbase_gpu_vm_lock(kctx); + + kbase_sticky_resource_term(kctx); + + /* MMU is disabled as part of scheduling out the context */ + kbase_mmu_free_pgd(kctx); + + /* drop the aliasing sink page now that it can't be mapped anymore */ + p = phys_to_page(as_phys_addr_t(kctx->aliasing_sink_page)); + kbase_mem_pool_free(&kctx->mem_pool, p, false); + + /* free pending region setups */ + pending_regions_to_clean = (~kctx->cookies) & KBASE_COOKIE_MASK; + while (pending_regions_to_clean) { + unsigned int cookie = __ffs(pending_regions_to_clean); + + BUG_ON(!kctx->pending_regions[cookie]); + + kbase_reg_pending_dtor(kctx->pending_regions[cookie]); + + kctx->pending_regions[cookie] = NULL; + pending_regions_to_clean &= ~(1UL << cookie); + } + + kbase_region_tracker_term(kctx); + kbase_gpu_vm_unlock(kctx); + + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + + kbase_jd_exit(kctx); + + kbase_pm_context_idle(kbdev); + + kbase_dma_fence_term(kctx); + + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags); + kbase_ctx_sched_remove_ctx(kctx); + spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + kbase_mmu_term(kctx); + + pages = atomic_read(&kctx->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); + + kbase_mem_evictable_deinit(kctx); + kbase_mem_pool_term(&kctx->mem_pool); + kbase_mem_pool_term(&kctx->lp_mem_pool); + WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0); + + vfree(kctx); +} +KBASE_EXPORT_SYMBOL(kbase_destroy_context); + +/** + * kbase_context_set_create_flags - Set creation flags on a context + * @kctx: Kbase context + * @flags: Flags to set + * + * Return: 0 on success + */ +int kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags) +{ + int err = 0; + struct kbasep_js_kctx_info *js_kctx_info; + unsigned long irq_flags; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + js_kctx_info = &kctx->jctx.sched_info; + + /* Validate flags */ + if (flags != (flags & BASE_CONTEXT_CREATE_KERNEL_FLAGS)) { + err = -EINVAL; + goto out; + } + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags); + + /* Translate the flags */ + if ((flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0) + kbase_ctx_flag_clear(kctx, KCTX_SUBMIT_DISABLED); + + /* Latch the initial attributes into the Job Scheduler */ + kbasep_js_ctx_attr_set_initial_attrs(kctx->kbdev, kctx); + + spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_context_set_create_flags); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_context.h b/drivers/gpu/arm/bifrost/mali_kbase_context.h new file mode 100644 index 000000000000..a3f5bb0ce0da --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_context.h @@ -0,0 +1,90 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_CONTEXT_H_ +#define _KBASE_CONTEXT_H_ + +#include + + +int kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags); + +/** + * kbase_ctx_flag - Check if @flag is set on @kctx + * @kctx: Pointer to kbase context to check + * @flag: Flag to check + * + * Return: true if @flag is set on @kctx, false if not. + */ +static inline bool kbase_ctx_flag(struct kbase_context *kctx, + enum kbase_context_flags flag) +{ + return atomic_read(&kctx->flags) & flag; +} + +/** + * kbase_ctx_flag_clear - Clear @flag on @kctx + * @kctx: Pointer to kbase context + * @flag: Flag to clear + * + * Clear the @flag on @kctx. This is done atomically, so other flags being + * cleared or set at the same time will be safe. + * + * Some flags have locking requirements, check the documentation for the + * respective flags. + */ +static inline void kbase_ctx_flag_clear(struct kbase_context *kctx, + enum kbase_context_flags flag) +{ +#if KERNEL_VERSION(4, 3, 0) > LINUX_VERSION_CODE + /* + * Earlier kernel versions doesn't have atomic_andnot() or + * atomic_and(). atomic_clear_mask() was only available on some + * architectures and removed on arm in v3.13 on arm and arm64. + * + * Use a compare-exchange loop to clear the flag on pre 4.3 kernels, + * when atomic_andnot() becomes available. + */ + int old, new; + + do { + old = atomic_read(&kctx->flags); + new = old & ~flag; + + } while (atomic_cmpxchg(&kctx->flags, old, new) != old); +#else + atomic_andnot(flag, &kctx->flags); +#endif +} + +/** + * kbase_ctx_flag_set - Set @flag on @kctx + * @kctx: Pointer to kbase context + * @flag: Flag to clear + * + * Set the @flag on @kctx. This is done atomically, so other flags being + * cleared or set at the same time will be safe. + * + * Some flags have locking requirements, check the documentation for the + * respective flags. + */ +static inline void kbase_ctx_flag_set(struct kbase_context *kctx, + enum kbase_context_flags flag) +{ + atomic_or(flag, &kctx->flags); +} +#endif /* _KBASE_CONTEXT_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c new file mode 100644 index 000000000000..3da2b6c4e7dc --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -0,0 +1,4979 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MALI_DEVFREQ +#include +#include +#ifdef CONFIG_DEVFREQ_THERMAL +#include +#endif /* CONFIG_DEVFREQ_THERMAL */ +#endif /* CONFIG_MALI_DEVFREQ */ +#ifdef CONFIG_MALI_NO_MALI +#include "mali_kbase_model_linux.h" +#endif /* CONFIG_MALI_NO_MALI */ +#include "mali_kbase_mem_profile_debugfs_buf_size.h" +#include "mali_kbase_debug_mem_view.h" +#include "mali_kbase_mem.h" +#include "mali_kbase_mem_pool_debugfs.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_regs_dump_debugfs.h" +#endif /* !MALI_CUSTOMER_RELEASE */ +#include "mali_kbase_regs_history_debugfs.h" +#include +#include +#include +#include +#include "mali_kbase_ioctl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* is_compat_task */ +#include +#include +#include +#include +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#include +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ +#include +#include + +#include + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#include +#else +#include +#endif + +#include + +#include + +/* GPU IRQ Tags */ +#define JOB_IRQ_TAG 0 +#define MMU_IRQ_TAG 1 +#define GPU_IRQ_TAG 2 + +#if MALI_UNIT_TEST +static struct kbase_exported_test_data shared_kernel_test_data; +EXPORT_SYMBOL(shared_kernel_test_data); +#endif /* MALI_UNIT_TEST */ + +static int kbase_dev_nr; + +static DEFINE_MUTEX(kbase_dev_list_lock); +static LIST_HEAD(kbase_dev_list); + +#define KERNEL_SIDE_DDK_VERSION_STRING "K:" MALI_RELEASE_NAME "(GPL)" +static inline void __compile_time_asserts(void) +{ + CSTD_COMPILE_TIME_ASSERT(sizeof(KERNEL_SIDE_DDK_VERSION_STRING) <= KBASE_GET_VERSION_BUFFER_SIZE); +} + +static int kbase_api_handshake(struct kbase_context *kctx, + struct kbase_ioctl_version_check *version) +{ + switch (version->major) { + case BASE_UK_VERSION_MAJOR: + /* set minor to be the lowest common */ + version->minor = min_t(int, BASE_UK_VERSION_MINOR, + (int)version->minor); + break; + default: + /* We return our actual version regardless if it + * matches the version returned by userspace - + * userspace can bail if it can't handle this + * version */ + version->major = BASE_UK_VERSION_MAJOR; + version->minor = BASE_UK_VERSION_MINOR; + break; + } + + /* save the proposed version number for later use */ + kctx->api_version = KBASE_API_VERSION(version->major, version->minor); + + return 0; +} + +/** + * enum mali_error - Mali error codes shared with userspace + * + * This is subset of those common Mali errors that can be returned to userspace. + * Values of matching user and kernel space enumerators MUST be the same. + * MALI_ERROR_NONE is guaranteed to be 0. + * + * @MALI_ERROR_NONE: Success + * @MALI_ERROR_OUT_OF_GPU_MEMORY: Not used in the kernel driver + * @MALI_ERROR_OUT_OF_MEMORY: Memory allocation failure + * @MALI_ERROR_FUNCTION_FAILED: Generic error code + */ +enum mali_error { + MALI_ERROR_NONE = 0, + MALI_ERROR_OUT_OF_GPU_MEMORY, + MALI_ERROR_OUT_OF_MEMORY, + MALI_ERROR_FUNCTION_FAILED, +}; + +enum { + inited_mem = (1u << 0), + inited_js = (1u << 1), + inited_pm_runtime_init = (1u << 2), +#ifdef CONFIG_MALI_DEVFREQ + inited_devfreq = (1u << 3), +#endif /* CONFIG_MALI_DEVFREQ */ + inited_tlstream = (1u << 4), + inited_backend_early = (1u << 5), + inited_backend_late = (1u << 6), + inited_device = (1u << 7), + inited_vinstr = (1u << 8), + + inited_job_fault = (1u << 10), + inited_sysfs_group = (1u << 11), + inited_misc_register = (1u << 12), + inited_get_device = (1u << 13), + inited_dev_list = (1u << 14), + inited_debugfs = (1u << 15), + inited_gpu_device = (1u << 16), + inited_registers_map = (1u << 17), + inited_io_history = (1u << 18), + inited_power_control = (1u << 19), + inited_buslogger = (1u << 20), + inited_protected = (1u << 21), + inited_ctx_sched = (1u << 22) +}; + + +#ifdef CONFIG_MALI_DEBUG +#define INACTIVE_WAIT_MS (5000) + +void kbase_set_driver_inactive(struct kbase_device *kbdev, bool inactive) +{ + kbdev->driver_inactive = inactive; + wake_up(&kbdev->driver_inactive_wait); + + /* Wait for any running IOCTLs to complete */ + if (inactive) + msleep(INACTIVE_WAIT_MS); +} +KBASE_EXPORT_TEST_API(kbase_set_driver_inactive); +#endif /* CONFIG_MALI_DEBUG */ + +/** + * kbase_legacy_dispatch - UKK dispatch function + * + * This is the dispatch function for the legacy UKK ioctl interface. No new + * ioctls should be added to this function, see kbase_ioctl instead. + * + * @kctx: The kernel context structure + * @args: Pointer to the data structure passed from/to user space + * @args_size: Size of the data structure + */ +static int kbase_legacy_dispatch(struct kbase_context *kctx, + void * const args, u32 args_size) +{ + struct kbase_device *kbdev; + union uk_header *ukh = args; + u32 id; + int ret = 0; + + KBASE_DEBUG_ASSERT(ukh != NULL); + + kbdev = kctx->kbdev; + id = ukh->id; + ukh->ret = MALI_ERROR_NONE; /* Be optimistic */ + +#ifdef CONFIG_MALI_DEBUG + wait_event(kbdev->driver_inactive_wait, + kbdev->driver_inactive == false); +#endif /* CONFIG_MALI_DEBUG */ + + if (UKP_FUNC_ID_CHECK_VERSION == id) { + struct uku_version_check_args *version_check; + struct kbase_ioctl_version_check version; + + if (args_size != sizeof(struct uku_version_check_args)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + return 0; + } + version_check = (struct uku_version_check_args *)args; + version.minor = version_check->minor; + version.major = version_check->major; + + kbase_api_handshake(kctx, &version); + + version_check->minor = version.minor; + version_check->major = version.major; + ukh->ret = MALI_ERROR_NONE; + return 0; + } + + /* block calls until version handshake */ + if (kctx->api_version == 0) + return -EINVAL; + + if (!atomic_read(&kctx->setup_complete)) { + struct kbase_uk_set_flags *kbase_set_flags; + + /* setup pending, try to signal that we'll do the setup, + * if setup was already in progress, err this call + */ + if (atomic_cmpxchg(&kctx->setup_in_progress, 0, 1) != 0) + return -EINVAL; + + /* if unexpected call, will stay stuck in setup mode + * (is it the only call we accept?) + */ + if (id != KBASE_FUNC_SET_FLAGS) + return -EINVAL; + + kbase_set_flags = (struct kbase_uk_set_flags *)args; + + /* if not matching the expected call, stay in setup mode */ + if (sizeof(*kbase_set_flags) != args_size) + goto bad_size; + + /* if bad flags, will stay stuck in setup mode */ + if (kbase_context_set_create_flags(kctx, + kbase_set_flags->create_flags) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + atomic_set(&kctx->setup_complete, 1); + return 0; + } + + /* setup complete, perform normal operation */ + switch (id) { + case KBASE_FUNC_MEM_JIT_INIT: + { + struct kbase_uk_mem_jit_init *jit_init = args; + + if (sizeof(*jit_init) != args_size) + goto bad_size; + + if (kbase_region_tracker_init_jit(kctx, + jit_init->va_pages)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_MEM_ALLOC: + { + struct kbase_uk_mem_alloc *mem = args; + struct kbase_va_region *reg; + + if (sizeof(*mem) != args_size) + goto bad_size; + +#if defined(CONFIG_64BIT) + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* force SAME_VA if a 64-bit client */ + mem->flags |= BASE_MEM_SAME_VA; + } +#endif + + reg = kbase_mem_alloc(kctx, mem->va_pages, + mem->commit_pages, mem->extent, + &mem->flags, &mem->gpu_va); + mem->va_alignment = 0; + + if (!reg) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_MEM_IMPORT: { + struct kbase_uk_mem_import *mem_import = args; + void __user *phandle; + + if (sizeof(*mem_import) != args_size) + goto bad_size; +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + phandle = compat_ptr(mem_import->phandle); + else +#endif + phandle = u64_to_user_ptr(mem_import->phandle); + + if (mem_import->type == BASE_MEM_IMPORT_TYPE_INVALID) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_import(kctx, + (enum base_mem_import_type) + mem_import->type, + phandle, + 0, + &mem_import->gpu_va, + &mem_import->va_pages, + &mem_import->flags)) { + mem_import->type = BASE_MEM_IMPORT_TYPE_INVALID; + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_MEM_ALIAS: { + struct kbase_uk_mem_alias *alias = args; + struct base_mem_aliasing_info __user *user_ai; + struct base_mem_aliasing_info *ai; + + if (sizeof(*alias) != args_size) + goto bad_size; + + if (alias->nents > 2048) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + if (!alias->nents) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + user_ai = compat_ptr(alias->ai); + else +#endif + user_ai = u64_to_user_ptr(alias->ai); + + ai = vmalloc(sizeof(*ai) * alias->nents); + + if (!ai) { + ukh->ret = MALI_ERROR_OUT_OF_MEMORY; + break; + } + + if (copy_from_user(ai, user_ai, + sizeof(*ai) * alias->nents)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto copy_failed; + } + + alias->gpu_va = kbase_mem_alias(kctx, &alias->flags, + alias->stride, + alias->nents, ai, + &alias->va_pages); + if (!alias->gpu_va) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto no_alias; + } +no_alias: +copy_failed: + vfree(ai); + break; + } + case KBASE_FUNC_MEM_COMMIT: + { + struct kbase_uk_mem_commit *commit = args; + int ret; + + if (sizeof(*commit) != args_size) + goto bad_size; + + ret = kbase_mem_commit(kctx, commit->gpu_addr, + commit->pages); + + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + commit->result_subcode = + BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS; + + if (ret == 0) { + ukh->ret = MALI_ERROR_NONE; + commit->result_subcode = + BASE_BACKING_THRESHOLD_OK; + } else if (ret == -ENOMEM) { + commit->result_subcode = + BASE_BACKING_THRESHOLD_ERROR_OOM; + } + + break; + } + + case KBASE_FUNC_MEM_QUERY: + { + struct kbase_uk_mem_query *query = args; + + if (sizeof(*query) != args_size) + goto bad_size; + + if (kbase_mem_query(kctx, query->gpu_addr, + query->query, &query->value) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + ukh->ret = MALI_ERROR_NONE; + break; + } + break; + + case KBASE_FUNC_MEM_FLAGS_CHANGE: + { + struct kbase_uk_mem_flags_change *fc = args; + + if (sizeof(*fc) != args_size) + goto bad_size; + + if (kbase_mem_flags_change(kctx, fc->gpu_va, + fc->flags, fc->mask) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + case KBASE_FUNC_MEM_FREE: + { + struct kbase_uk_mem_free *mem = args; + + if (sizeof(*mem) != args_size) + goto bad_size; + + if (kbase_mem_free(kctx, mem->gpu_addr) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_JOB_SUBMIT: + { + struct kbase_uk_job_submit *job = args; + char __user *user_buf; + + if (sizeof(*job) != args_size) + goto bad_size; + +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + user_buf = compat_ptr(job->addr); + else +#endif + user_buf = u64_to_user_ptr(job->addr); + + if (kbase_jd_submit(kctx, user_buf, + job->nr_atoms, + job->stride, + false) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_SYNC: + { + struct kbase_uk_sync_now *sn = args; + + if (sizeof(*sn) != args_size) + goto bad_size; + + if (kbase_sync_now(kctx, &sn->sset.basep_sset) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_DISJOINT_QUERY: + { + struct kbase_uk_disjoint_query *dquery = args; + + if (sizeof(*dquery) != args_size) + goto bad_size; + + /* Get the disjointness counter value. */ + dquery->counter = kbase_disjoint_event_get(kctx->kbdev); + break; + } + + case KBASE_FUNC_POST_TERM: + { + kbase_event_close(kctx); + break; + } + + case KBASE_FUNC_HWCNT_SETUP: + { + struct kbase_uk_hwcnt_setup *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + mutex_lock(&kctx->vinstr_cli_lock); + if (kbase_vinstr_legacy_hwc_setup(kbdev->vinstr_ctx, + &kctx->vinstr_cli, setup) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + mutex_unlock(&kctx->vinstr_cli_lock); + break; + } + + case KBASE_FUNC_HWCNT_DUMP: + { + /* args ignored */ + mutex_lock(&kctx->vinstr_cli_lock); + if (kbase_vinstr_hwc_dump(kctx->vinstr_cli, + BASE_HWCNT_READER_EVENT_MANUAL) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + mutex_unlock(&kctx->vinstr_cli_lock); + break; + } + + case KBASE_FUNC_HWCNT_CLEAR: + { + /* args ignored */ + mutex_lock(&kctx->vinstr_cli_lock); + if (kbase_vinstr_hwc_clear(kctx->vinstr_cli) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + mutex_unlock(&kctx->vinstr_cli_lock); + break; + } + + case KBASE_FUNC_HWCNT_READER_SETUP: + { + struct kbase_uk_hwcnt_reader_setup *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + mutex_lock(&kctx->vinstr_cli_lock); + if (kbase_vinstr_hwcnt_reader_setup(kbdev->vinstr_ctx, + setup) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + mutex_unlock(&kctx->vinstr_cli_lock); + break; + } + + case KBASE_FUNC_GPU_PROPS_REG_DUMP: + { + struct kbase_uk_gpuprops *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (kbase_gpuprops_uk_get_props(kctx, setup) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_FIND_CPU_OFFSET: + { + struct kbase_uk_find_cpu_offset *find = args; + + if (sizeof(*find) != args_size) + goto bad_size; + + if (find->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_legacy_dispatch case KBASE_FUNC_FIND_CPU_OFFSET: find->gpu_addr: passed parameter is invalid"); + goto out_bad; + } + + if (find->size > SIZE_MAX || find->cpu_addr > ULONG_MAX) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } else { + int err; + + err = kbasep_find_enclosing_cpu_mapping_offset( + kctx, + find->cpu_addr, + find->size, + &find->offset); + + if (err) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_GET_VERSION: + { + struct kbase_uk_get_ddk_version *get_version = (struct kbase_uk_get_ddk_version *)args; + + if (sizeof(*get_version) != args_size) + goto bad_size; + + /* version buffer size check is made in compile time assert */ + memcpy(get_version->version_buffer, KERNEL_SIDE_DDK_VERSION_STRING, sizeof(KERNEL_SIDE_DDK_VERSION_STRING)); + get_version->version_string_size = sizeof(KERNEL_SIDE_DDK_VERSION_STRING); + break; + } + + case KBASE_FUNC_STREAM_CREATE: + { +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + struct kbase_uk_stream_create *screate = (struct kbase_uk_stream_create *)args; + + if (sizeof(*screate) != args_size) + goto bad_size; + + if (strnlen(screate->name, sizeof(screate->name)) >= sizeof(screate->name)) { + /* not NULL terminated */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_sync_fence_stream_create(screate->name, + &screate->fd) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + ukh->ret = MALI_ERROR_NONE; +#else /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + break; + } + case KBASE_FUNC_FENCE_VALIDATE: + { +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + struct kbase_uk_fence_validate *fence_validate = (struct kbase_uk_fence_validate *)args; + + if (sizeof(*fence_validate) != args_size) + goto bad_size; + + if (kbase_sync_fence_validate(fence_validate->fd) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + ukh->ret = MALI_ERROR_NONE; +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + break; + } + + case KBASE_FUNC_SET_TEST_DATA: + { +#if MALI_UNIT_TEST + struct kbase_uk_set_test_data *set_data = args; + + shared_kernel_test_data = set_data->test_data; + shared_kernel_test_data.kctx = (uintptr_t)kctx; + shared_kernel_test_data.mm = (uintptr_t)current->mm; + ukh->ret = MALI_ERROR_NONE; +#endif /* MALI_UNIT_TEST */ + break; + } + + case KBASE_FUNC_INJECT_ERROR: + { +#ifdef CONFIG_MALI_ERROR_INJECT + unsigned long flags; + struct kbase_error_params params = ((struct kbase_uk_error_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + if (job_atom_inject_error(¶ms) != 0) + ukh->ret = MALI_ERROR_OUT_OF_MEMORY; + else + ukh->ret = MALI_ERROR_NONE; + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_ERROR_INJECT */ + break; + } + + case KBASE_FUNC_MODEL_CONTROL: + { +#ifdef CONFIG_MALI_NO_MALI + unsigned long flags; + struct kbase_model_control_params params = + ((struct kbase_uk_model_control_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + if (gpu_model_control(kbdev->model, ¶ms) != 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + ukh->ret = MALI_ERROR_NONE; + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_NO_MALI */ + break; + } + + case KBASE_FUNC_GET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + controls->profiling_controls[i] = + kbdev->kbase_profiling_controls[i]; + + break; + } + + /* used only for testing purposes; these controls are to be set by gator through gator API */ + case KBASE_FUNC_SET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + _mali_profiling_control(i, controls->profiling_controls[i]); + + break; + } + + case KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD: + { + struct kbase_uk_debugfs_mem_profile_add *add_data = + (struct kbase_uk_debugfs_mem_profile_add *)args; + char *buf; + char __user *user_buf; + + if (sizeof(*add_data) != args_size) + goto bad_size; + + if (add_data->len > KBASE_MEM_PROFILE_MAX_BUF_SIZE) { + dev_err(kbdev->dev, "buffer too big\n"); + goto out_bad; + } + +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + user_buf = compat_ptr(add_data->buf); + else +#endif + user_buf = u64_to_user_ptr(add_data->buf); + + buf = kmalloc(add_data->len, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) + goto out_bad; + + if (0 != copy_from_user(buf, user_buf, add_data->len)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + kfree(buf); + goto out_bad; + } + + if (kbasep_mem_profile_debugfs_insert(kctx, buf, + add_data->len)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto out_bad; + } + + break; + } + +#ifdef CONFIG_MALI_NO_MALI + case KBASE_FUNC_SET_PRFCNT_VALUES: + { + + struct kbase_uk_prfcnt_values *params = + ((struct kbase_uk_prfcnt_values *)args); + gpu_model_set_dummy_prfcnt_sample(params->data, + params->size); + + break; + } +#endif /* CONFIG_MALI_NO_MALI */ +#ifdef BASE_LEGACY_UK10_4_SUPPORT + case KBASE_FUNC_TLSTREAM_ACQUIRE_V10_4: + { + struct kbase_uk_tlstream_acquire_v10_4 *tlstream_acquire + = args; + int ret; + + if (sizeof(*tlstream_acquire) != args_size) + goto bad_size; + + ret = kbase_tlstream_acquire( + kctx, 0); + if (ret < 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + tlstream_acquire->fd = ret; + break; + } +#endif /* BASE_LEGACY_UK10_4_SUPPORT */ + case KBASE_FUNC_TLSTREAM_ACQUIRE: + { + struct kbase_uk_tlstream_acquire *tlstream_acquire = + args; + int ret; + + if (sizeof(*tlstream_acquire) != args_size) + goto bad_size; + + if (tlstream_acquire->flags & ~BASE_TLSTREAM_FLAGS_MASK) + goto out_bad; + + ret = kbase_tlstream_acquire( + kctx, tlstream_acquire->flags); + if (ret < 0) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + else + tlstream_acquire->fd = ret; + break; + } + case KBASE_FUNC_TLSTREAM_FLUSH: + { + struct kbase_uk_tlstream_flush *tlstream_flush = + args; + + if (sizeof(*tlstream_flush) != args_size) + goto bad_size; + + kbase_tlstream_flush_streams(); + break; + } +#if MALI_UNIT_TEST + case KBASE_FUNC_TLSTREAM_TEST: + { + struct kbase_uk_tlstream_test *tlstream_test = args; + + if (sizeof(*tlstream_test) != args_size) + goto bad_size; + + kbase_tlstream_test( + tlstream_test->tpw_count, + tlstream_test->msg_delay, + tlstream_test->msg_count, + tlstream_test->aux_msg); + break; + } + case KBASE_FUNC_TLSTREAM_STATS: + { + struct kbase_uk_tlstream_stats *tlstream_stats = args; + + if (sizeof(*tlstream_stats) != args_size) + goto bad_size; + + kbase_tlstream_stats( + &tlstream_stats->bytes_collected, + &tlstream_stats->bytes_generated); + break; + } +#endif /* MALI_UNIT_TEST */ + + case KBASE_FUNC_GET_CONTEXT_ID: + { + struct kbase_uk_context_id *info = args; + + info->id = kctx->id; + break; + } + + case KBASE_FUNC_SOFT_EVENT_UPDATE: + { + struct kbase_uk_soft_event_update *update = args; + + if (sizeof(*update) != args_size) + goto bad_size; + + if (((update->new_status != BASE_JD_SOFT_EVENT_SET) && + (update->new_status != BASE_JD_SOFT_EVENT_RESET)) || + (update->flags != 0)) + goto out_bad; + + if (kbase_soft_event_update(kctx, update->evt, + update->new_status)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + + default: + dev_err(kbdev->dev, "unknown ioctl %u\n", id); + goto out_bad; + } + + return ret; + + bad_size: + dev_err(kbdev->dev, "Wrong syscall size (%d) for %08x\n", args_size, id); + out_bad: + return -EINVAL; +} + +static struct kbase_device *to_kbase_device(struct device *dev) +{ + return dev_get_drvdata(dev); +} + +static int assign_irqs(struct platform_device *pdev) +{ + struct kbase_device *kbdev = to_kbase_device(&pdev->dev); + int i; + + if (!kbdev) + return -ENODEV; + + /* 3 IRQ resources */ + for (i = 0; i < 3; i++) { + struct resource *irq_res; + int irqtag; + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!irq_res) { + dev_err(kbdev->dev, "No IRQ resource at index %d\n", i); + return -ENOENT; + } + +#ifdef CONFIG_OF + if (!strncmp(irq_res->name, "JOB", 4)) { + irqtag = JOB_IRQ_TAG; + } else if (!strncmp(irq_res->name, "MMU", 4)) { + irqtag = MMU_IRQ_TAG; + } else if (!strncmp(irq_res->name, "GPU", 4)) { + irqtag = GPU_IRQ_TAG; + } else { + dev_err(&pdev->dev, "Invalid irq res name: '%s'\n", + irq_res->name); + return -EINVAL; + } +#else + irqtag = i; +#endif /* CONFIG_OF */ + kbdev->irqs[irqtag].irq = irq_res->start; + kbdev->irqs[irqtag].flags = irq_res->flags & IRQF_TRIGGER_MASK; + } + + return 0; +} + +/* + * API to acquire device list mutex and + * return pointer to the device list head + */ +const struct list_head *kbase_dev_list_get(void) +{ + mutex_lock(&kbase_dev_list_lock); + return &kbase_dev_list; +} +KBASE_EXPORT_TEST_API(kbase_dev_list_get); + +/* API to release the device list mutex */ +void kbase_dev_list_put(const struct list_head *dev_list) +{ + mutex_unlock(&kbase_dev_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_dev_list_put); + +/* Find a particular kbase device (as specified by minor number), or find the "first" device if -1 is specified */ +struct kbase_device *kbase_find_device(int minor) +{ + struct kbase_device *kbdev = NULL; + struct list_head *entry; + const struct list_head *dev_list = kbase_dev_list_get(); + + list_for_each(entry, dev_list) { + struct kbase_device *tmp; + + tmp = list_entry(entry, struct kbase_device, entry); + if (tmp->mdev.minor == minor || minor == -1) { + kbdev = tmp; + get_device(kbdev->dev); + break; + } + } + kbase_dev_list_put(dev_list); + + return kbdev; +} +EXPORT_SYMBOL(kbase_find_device); + +void kbase_release_device(struct kbase_device *kbdev) +{ + put_device(kbdev->dev); +} +EXPORT_SYMBOL(kbase_release_device); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && \ + !(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 28) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) +/* + * Older versions, before v4.6, of the kernel doesn't have + * kstrtobool_from_user(), except longterm 4.4.y which had it added in 4.4.28 + */ +static int kstrtobool_from_user(const char __user *s, size_t count, bool *res) +{ + char buf[32]; + + count = min(sizeof(buf), count); + + if (copy_from_user(buf, s, count)) + return -EFAULT; + buf[count] = '\0'; + + return strtobool(buf, res); +} +#endif + +static ssize_t write_ctx_infinite_cache(struct file *f, const char __user *ubuf, size_t size, loff_t *off) +{ + struct kbase_context *kctx = f->private_data; + int err; + bool value; + + err = kstrtobool_from_user(ubuf, size, &value); + if (err) + return err; + + if (value) + kbase_ctx_flag_set(kctx, KCTX_INFINITE_CACHE); + else + kbase_ctx_flag_clear(kctx, KCTX_INFINITE_CACHE); + + return size; +} + +static ssize_t read_ctx_infinite_cache(struct file *f, char __user *ubuf, size_t size, loff_t *off) +{ + struct kbase_context *kctx = f->private_data; + char buf[32]; + int count; + bool value; + + value = kbase_ctx_flag(kctx, KCTX_INFINITE_CACHE); + + count = scnprintf(buf, sizeof(buf), "%s\n", value ? "Y" : "N"); + + return simple_read_from_buffer(ubuf, size, off, buf, count); +} + +static const struct file_operations kbase_infinite_cache_fops = { + .open = simple_open, + .write = write_ctx_infinite_cache, + .read = read_ctx_infinite_cache, +}; + +static int kbase_open(struct inode *inode, struct file *filp) +{ + struct kbase_device *kbdev = NULL; + struct kbase_context *kctx; + int ret = 0; +#ifdef CONFIG_DEBUG_FS + char kctx_name[64]; +#endif + + kbdev = kbase_find_device(iminor(inode)); + + if (!kbdev) + return -ENODEV; + + kctx = kbase_create_context(kbdev, is_compat_task()); + if (!kctx) { + ret = -ENOMEM; + goto out; + } + + init_waitqueue_head(&kctx->event_queue); + filp->private_data = kctx; + kctx->filp = filp; + + if (kbdev->infinite_cache_active_default) + kbase_ctx_flag_set(kctx, KCTX_INFINITE_CACHE); + +#ifdef CONFIG_DEBUG_FS + snprintf(kctx_name, 64, "%d_%d", kctx->tgid, kctx->id); + + kctx->kctx_dentry = debugfs_create_dir(kctx_name, + kbdev->debugfs_ctx_directory); + + if (IS_ERR_OR_NULL(kctx->kctx_dentry)) { + ret = -ENOMEM; + goto out; + } + + debugfs_create_file("infinite_cache", 0644, kctx->kctx_dentry, + kctx, &kbase_infinite_cache_fops); + + mutex_init(&kctx->mem_profile_lock); + + kbasep_jd_debugfs_ctx_init(kctx); + kbase_debug_mem_view_init(filp); + + kbase_debug_job_fault_context_init(kctx); + + kbase_mem_pool_debugfs_init(kctx->kctx_dentry, &kctx->mem_pool, &kctx->lp_mem_pool); + + kbase_jit_debugfs_init(kctx); +#endif /* CONFIG_DEBUG_FS */ + + dev_dbg(kbdev->dev, "created base context\n"); + + { + struct kbasep_kctx_list_element *element; + + element = kzalloc(sizeof(*element), GFP_KERNEL); + if (element) { + mutex_lock(&kbdev->kctx_list_lock); + element->kctx = kctx; + list_add(&element->link, &kbdev->kctx_list); + KBASE_TLSTREAM_TL_NEW_CTX( + element->kctx, + element->kctx->id, + (u32)(element->kctx->tgid)); + mutex_unlock(&kbdev->kctx_list_lock); + } else { + /* we don't treat this as a fail - just warn about it */ + dev_warn(kbdev->dev, "couldn't add kctx to kctx_list\n"); + } + } + return 0; + + out: + kbase_release_device(kbdev); + return ret; +} + +static int kbase_release(struct inode *inode, struct file *filp) +{ + struct kbase_context *kctx = filp->private_data; + struct kbase_device *kbdev = kctx->kbdev; + struct kbasep_kctx_list_element *element, *tmp; + bool found_element = false; + + KBASE_TLSTREAM_TL_DEL_CTX(kctx); + +#ifdef CONFIG_DEBUG_FS + kbasep_mem_profile_debugfs_remove(kctx); + kbase_debug_job_fault_context_term(kctx); +#endif + + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry_safe(element, tmp, &kbdev->kctx_list, link) { + if (element->kctx == kctx) { + list_del(&element->link); + kfree(element); + found_element = true; + } + } + mutex_unlock(&kbdev->kctx_list_lock); + if (!found_element) + dev_warn(kbdev->dev, "kctx not in kctx_list\n"); + + filp->private_data = NULL; + + mutex_lock(&kctx->vinstr_cli_lock); + /* If this client was performing hwcnt dumping and did not explicitly + * detach itself, remove it from the vinstr core now */ + if (kctx->vinstr_cli) { + struct kbase_uk_hwcnt_setup setup; + + setup.dump_buffer = 0llu; + kbase_vinstr_legacy_hwc_setup( + kbdev->vinstr_ctx, &kctx->vinstr_cli, &setup); + } + mutex_unlock(&kctx->vinstr_cli_lock); + + kbase_destroy_context(kctx); + + dev_dbg(kbdev->dev, "deleted base context\n"); + kbase_release_device(kbdev); + return 0; +} + +#define CALL_MAX_SIZE 536 + +static long kbase_legacy_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + u64 msg[(CALL_MAX_SIZE + 7) >> 3] = { 0xdeadbeefdeadbeefull }; /* alignment fixup */ + u32 size = _IOC_SIZE(cmd); + struct kbase_context *kctx = filp->private_data; + + if (size > CALL_MAX_SIZE) + return -ENOTTY; + + if (0 != copy_from_user(&msg, (void __user *)arg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy ioctl argument into kernel space\n"); + return -EFAULT; + } + + if (kbase_legacy_dispatch(kctx, &msg, size) != 0) + return -EFAULT; + + if (0 != copy_to_user((void __user *)arg, &msg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy results of UK call back to user space\n"); + return -EFAULT; + } + return 0; +} + +static int kbase_api_set_flags(struct kbase_context *kctx, + struct kbase_ioctl_set_flags *flags) +{ + int err; + + /* setup pending, try to signal that we'll do the setup, + * if setup was already in progress, err this call + */ + if (atomic_cmpxchg(&kctx->setup_in_progress, 0, 1) != 0) + return -EINVAL; + + err = kbase_context_set_create_flags(kctx, flags->create_flags); + /* if bad flags, will stay stuck in setup mode */ + if (err) + return err; + + atomic_set(&kctx->setup_complete, 1); + return 0; +} + +static int kbase_api_job_submit(struct kbase_context *kctx, + struct kbase_ioctl_job_submit *submit) +{ + return kbase_jd_submit(kctx, u64_to_user_ptr(submit->addr), + submit->nr_atoms, + submit->stride, false); +} + +static int kbase_api_get_gpuprops(struct kbase_context *kctx, + struct kbase_ioctl_get_gpuprops *get_props) +{ + struct kbase_gpu_props *kprops = &kctx->kbdev->gpu_props; + int err; + + if (get_props->flags != 0) { + dev_err(kctx->kbdev->dev, "Unsupported flags to get_gpuprops"); + return -EINVAL; + } + + if (get_props->size == 0) + return kprops->prop_buffer_size; + if (get_props->size < kprops->prop_buffer_size) + return -EINVAL; + + err = copy_to_user(u64_to_user_ptr(get_props->buffer), + kprops->prop_buffer, + kprops->prop_buffer_size); + if (err) + return -EFAULT; + return kprops->prop_buffer_size; +} + +static int kbase_api_post_term(struct kbase_context *kctx) +{ + kbase_event_close(kctx); + return 0; +} + +static int kbase_api_mem_alloc(struct kbase_context *kctx, + union kbase_ioctl_mem_alloc *alloc) +{ + struct kbase_va_region *reg; + u64 flags = alloc->in.flags; + u64 gpu_va; + +#if defined(CONFIG_64BIT) + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* force SAME_VA if a 64-bit client */ + flags |= BASE_MEM_SAME_VA; + } +#endif + + reg = kbase_mem_alloc(kctx, alloc->in.va_pages, + alloc->in.commit_pages, + alloc->in.extent, + &flags, &gpu_va); + + if (!reg) + return -ENOMEM; + + alloc->out.flags = flags; + alloc->out.gpu_va = gpu_va; + + return 0; +} + +static int kbase_api_mem_query(struct kbase_context *kctx, + union kbase_ioctl_mem_query *query) +{ + return kbase_mem_query(kctx, query->in.gpu_addr, + query->in.query, &query->out.value); +} + +static int kbase_api_mem_free(struct kbase_context *kctx, + struct kbase_ioctl_mem_free *free) +{ + return kbase_mem_free(kctx, free->gpu_addr); +} + +static int kbase_api_hwcnt_reader_setup(struct kbase_context *kctx, + struct kbase_ioctl_hwcnt_reader_setup *setup) +{ + int ret; + struct kbase_uk_hwcnt_reader_setup args = { + .buffer_count = setup->buffer_count, + .jm_bm = setup->jm_bm, + .shader_bm = setup->shader_bm, + .tiler_bm = setup->tiler_bm, + .mmu_l2_bm = setup->mmu_l2_bm + }; + + mutex_lock(&kctx->vinstr_cli_lock); + ret = kbase_vinstr_hwcnt_reader_setup(kctx->kbdev->vinstr_ctx, &args); + mutex_unlock(&kctx->vinstr_cli_lock); + + if (ret) + return ret; + return args.fd; +} + +static int kbase_api_hwcnt_enable(struct kbase_context *kctx, + struct kbase_ioctl_hwcnt_enable *enable) +{ + int ret; + struct kbase_uk_hwcnt_setup args = { + .dump_buffer = enable->dump_buffer, + .jm_bm = enable->jm_bm, + .shader_bm = enable->shader_bm, + .tiler_bm = enable->tiler_bm, + .mmu_l2_bm = enable->mmu_l2_bm + }; + + mutex_lock(&kctx->vinstr_cli_lock); + ret = kbase_vinstr_legacy_hwc_setup(kctx->kbdev->vinstr_ctx, + &kctx->vinstr_cli, &args); + mutex_unlock(&kctx->vinstr_cli_lock); + + return ret; +} + +static int kbase_api_hwcnt_dump(struct kbase_context *kctx) +{ + int ret; + + mutex_lock(&kctx->vinstr_cli_lock); + ret = kbase_vinstr_hwc_dump(kctx->vinstr_cli, + BASE_HWCNT_READER_EVENT_MANUAL); + mutex_unlock(&kctx->vinstr_cli_lock); + + return ret; +} + +static int kbase_api_hwcnt_clear(struct kbase_context *kctx) +{ + int ret; + + mutex_lock(&kctx->vinstr_cli_lock); + ret = kbase_vinstr_hwc_clear(kctx->vinstr_cli); + mutex_unlock(&kctx->vinstr_cli_lock); + + return ret; +} + +static int kbase_api_disjoint_query(struct kbase_context *kctx, + struct kbase_ioctl_disjoint_query *query) +{ + query->counter = kbase_disjoint_event_get(kctx->kbdev); + + return 0; +} + +static int kbase_api_get_ddk_version(struct kbase_context *kctx, + struct kbase_ioctl_get_ddk_version *version) +{ + int ret; + int len = sizeof(KERNEL_SIDE_DDK_VERSION_STRING); + + if (version->version_buffer == 0) + return len; + + if (version->size < len) + return -EOVERFLOW; + + ret = copy_to_user(u64_to_user_ptr(version->version_buffer), + KERNEL_SIDE_DDK_VERSION_STRING, + sizeof(KERNEL_SIDE_DDK_VERSION_STRING)); + + if (ret) + return -EFAULT; + + return len; +} + +static int kbase_api_mem_jit_init(struct kbase_context *kctx, + struct kbase_ioctl_mem_jit_init *jit_init) +{ + return kbase_region_tracker_init_jit(kctx, jit_init->va_pages); +} + +static int kbase_api_mem_sync(struct kbase_context *kctx, + struct kbase_ioctl_mem_sync *sync) +{ + struct basep_syncset sset = { + .mem_handle.basep.handle = sync->handle, + .user_addr = sync->user_addr, + .size = sync->size, + .type = sync->type + }; + + return kbase_sync_now(kctx, &sset); +} + +static int kbase_api_mem_find_cpu_offset(struct kbase_context *kctx, + union kbase_ioctl_mem_find_cpu_offset *find) +{ + return kbasep_find_enclosing_cpu_mapping_offset( + kctx, + find->in.cpu_addr, + find->in.size, + &find->out.offset); +} + +static int kbase_api_get_context_id(struct kbase_context *kctx, + struct kbase_ioctl_get_context_id *info) +{ + info->id = kctx->id; + + return 0; +} + +static int kbase_api_tlstream_acquire(struct kbase_context *kctx, + struct kbase_ioctl_tlstream_acquire *acquire) +{ + return kbase_tlstream_acquire(kctx, acquire->flags); +} + +static int kbase_api_tlstream_flush(struct kbase_context *kctx) +{ + kbase_tlstream_flush_streams(); + + return 0; +} + +static int kbase_api_mem_commit(struct kbase_context *kctx, + struct kbase_ioctl_mem_commit *commit) +{ + return kbase_mem_commit(kctx, commit->gpu_addr, commit->pages); +} + +static int kbase_api_mem_alias(struct kbase_context *kctx, + union kbase_ioctl_mem_alias *alias) +{ + struct base_mem_aliasing_info *ai; + u64 flags; + int err; + + if (alias->in.nents == 0 || alias->in.nents > 2048) + return -EINVAL; + + ai = vmalloc(sizeof(*ai) * alias->in.nents); + if (!ai) + return -ENOMEM; + + err = copy_from_user(ai, + u64_to_user_ptr(alias->in.aliasing_info), + sizeof(*ai) * alias->in.nents); + if (err) { + vfree(ai); + return -EFAULT; + } + + flags = alias->in.flags; + + alias->out.gpu_va = kbase_mem_alias(kctx, &flags, + alias->in.stride, alias->in.nents, + ai, &alias->out.va_pages); + + alias->out.flags = flags; + + vfree(ai); + + if (alias->out.gpu_va == 0) + return -ENOMEM; + + return 0; +} + +static int kbase_api_mem_import(struct kbase_context *kctx, + union kbase_ioctl_mem_import *import) +{ + int ret; + u64 flags = import->in.flags; + + ret = kbase_mem_import(kctx, + import->in.type, + u64_to_user_ptr(import->in.phandle), + import->in.padding, + &import->out.gpu_va, + &import->out.va_pages, + &flags); + + import->out.flags = flags; + + return ret; +} + +static int kbase_api_mem_flags_change(struct kbase_context *kctx, + struct kbase_ioctl_mem_flags_change *change) +{ + return kbase_mem_flags_change(kctx, change->gpu_va, + change->flags, change->mask); +} + +static int kbase_api_stream_create(struct kbase_context *kctx, + struct kbase_ioctl_stream_create *stream) +{ +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + int fd, ret; + + /* Name must be NULL-terminated and padded with NULLs, so check last + * character is NULL + */ + if (stream->name[sizeof(stream->name)-1] != 0) + return -EINVAL; + + ret = kbase_sync_fence_stream_create(stream->name, &fd); + + if (ret) + return ret; + return fd; +#else + return -ENOENT; +#endif +} + +static int kbase_api_fence_validate(struct kbase_context *kctx, + struct kbase_ioctl_fence_validate *validate) +{ +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + return kbase_sync_fence_validate(validate->fd); +#else + return -ENOENT; +#endif +} + +static int kbase_api_get_profiling_controls(struct kbase_context *kctx, + struct kbase_ioctl_get_profiling_controls *controls) +{ + int ret; + + if (controls->count > (FBDUMP_CONTROL_MAX - FBDUMP_CONTROL_MIN)) + return -EINVAL; + + ret = copy_to_user(u64_to_user_ptr(controls->buffer), + &kctx->kbdev->kbase_profiling_controls[ + FBDUMP_CONTROL_MIN], + controls->count * sizeof(u32)); + + if (ret) + return -EFAULT; + return 0; +} + +static int kbase_api_mem_profile_add(struct kbase_context *kctx, + struct kbase_ioctl_mem_profile_add *data) +{ + char *buf; + int err; + + if (data->len > KBASE_MEM_PROFILE_MAX_BUF_SIZE) { + dev_err(kctx->kbdev->dev, "mem_profile_add: buffer too big\n"); + return -EINVAL; + } + + buf = kmalloc(data->len, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) + return -ENOMEM; + + err = copy_from_user(buf, u64_to_user_ptr(data->buffer), + data->len); + if (err) { + kfree(buf); + return -EFAULT; + } + + return kbasep_mem_profile_debugfs_insert(kctx, buf, data->len); +} + +static int kbase_api_soft_event_update(struct kbase_context *kctx, + struct kbase_ioctl_soft_event_update *update) +{ + if (update->flags != 0) + return -EINVAL; + + return kbase_soft_event_update(kctx, update->event, update->new_status); +} + +#if MALI_UNIT_TEST +static int kbase_api_tlstream_test(struct kbase_context *kctx, + struct kbase_ioctl_tlstream_test *test) +{ + kbase_tlstream_test( + test->tpw_count, + test->msg_delay, + test->msg_count, + test->aux_msg); + + return 0; +} + +static int kbase_api_tlstream_stats(struct kbase_context *kctx, + struct kbase_ioctl_tlstream_stats *stats) +{ + kbase_tlstream_stats( + &stats->bytes_collected, + &stats->bytes_generated); + + return 0; +} +#endif /* MALI_UNIT_TEST */ + +#define KBASE_HANDLE_IOCTL(cmd, function) \ + case cmd: \ + do { \ + BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \ + return function(kctx); \ + } while (0) + +#define KBASE_HANDLE_IOCTL_IN(cmd, function, type) \ + case cmd: \ + do { \ + type param; \ + int err; \ + BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \ + BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \ + err = copy_from_user(¶m, uarg, sizeof(param)); \ + if (err) \ + return -EFAULT; \ + return function(kctx, ¶m); \ + } while (0) + +#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type) \ + case cmd: \ + do { \ + type param; \ + int ret, err; \ + BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \ + BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \ + ret = function(kctx, ¶m); \ + err = copy_to_user(uarg, ¶m, sizeof(param)); \ + if (err) \ + return -EFAULT; \ + return ret; \ + } while (0) + +#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type) \ + case cmd: \ + do { \ + type param; \ + int ret, err; \ + BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE|_IOC_READ)); \ + BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \ + err = copy_from_user(¶m, uarg, sizeof(param)); \ + if (err) \ + return -EFAULT; \ + ret = function(kctx, ¶m); \ + err = copy_to_user(uarg, ¶m, sizeof(param)); \ + if (err) \ + return -EFAULT; \ + return ret; \ + } while (0) + +static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct kbase_context *kctx = filp->private_data; + struct kbase_device *kbdev = kctx->kbdev; + void __user *uarg = (void __user *)arg; + + /* The UK ioctl values overflow the cmd field causing the type to be + * incremented + */ + if (_IOC_TYPE(cmd) == LINUX_UK_BASE_MAGIC+2) + return kbase_legacy_ioctl(filp, cmd, arg); + + /* The UK version check IOCTL doesn't overflow the cmd field, so is + * handled separately here + */ + if (cmd == _IOC(_IOC_READ|_IOC_WRITE, LINUX_UK_BASE_MAGIC, + UKP_FUNC_ID_CHECK_VERSION, + sizeof(struct uku_version_check_args))) + return kbase_legacy_ioctl(filp, cmd, arg); + + /* Only these ioctls are available until setup is complete */ + switch (cmd) { + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_VERSION_CHECK, + kbase_api_handshake, + struct kbase_ioctl_version_check); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SET_FLAGS, + kbase_api_set_flags, + struct kbase_ioctl_set_flags); + } + + /* Block call until version handshake and setup is complete */ + if (kctx->api_version == 0 || !atomic_read(&kctx->setup_complete)) + return -EINVAL; + + /* Normal ioctls */ + switch (cmd) { + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_JOB_SUBMIT, + kbase_api_job_submit, + struct kbase_ioctl_job_submit); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_GET_GPUPROPS, + kbase_api_get_gpuprops, + struct kbase_ioctl_get_gpuprops); + KBASE_HANDLE_IOCTL(KBASE_IOCTL_POST_TERM, + kbase_api_post_term); + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_ALLOC, + kbase_api_mem_alloc, + union kbase_ioctl_mem_alloc); + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_QUERY, + kbase_api_mem_query, + union kbase_ioctl_mem_query); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_FREE, + kbase_api_mem_free, + struct kbase_ioctl_mem_free); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_HWCNT_READER_SETUP, + kbase_api_hwcnt_reader_setup, + struct kbase_ioctl_hwcnt_reader_setup); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_HWCNT_ENABLE, + kbase_api_hwcnt_enable, + struct kbase_ioctl_hwcnt_enable); + KBASE_HANDLE_IOCTL(KBASE_IOCTL_HWCNT_DUMP, + kbase_api_hwcnt_dump); + KBASE_HANDLE_IOCTL(KBASE_IOCTL_HWCNT_CLEAR, + kbase_api_hwcnt_clear); + KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_DISJOINT_QUERY, + kbase_api_disjoint_query, + struct kbase_ioctl_disjoint_query); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_GET_DDK_VERSION, + kbase_api_get_ddk_version, + struct kbase_ioctl_get_ddk_version); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT, + kbase_api_mem_jit_init, + struct kbase_ioctl_mem_jit_init); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_SYNC, + kbase_api_mem_sync, + struct kbase_ioctl_mem_sync); + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_FIND_CPU_OFFSET, + kbase_api_mem_find_cpu_offset, + union kbase_ioctl_mem_find_cpu_offset); + KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_GET_CONTEXT_ID, + kbase_api_get_context_id, + struct kbase_ioctl_get_context_id); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_TLSTREAM_ACQUIRE, + kbase_api_tlstream_acquire, + struct kbase_ioctl_tlstream_acquire); + KBASE_HANDLE_IOCTL(KBASE_IOCTL_TLSTREAM_FLUSH, + kbase_api_tlstream_flush); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_COMMIT, + kbase_api_mem_commit, + struct kbase_ioctl_mem_commit); + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_ALIAS, + kbase_api_mem_alias, + union kbase_ioctl_mem_alias); + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_IMPORT, + kbase_api_mem_import, + union kbase_ioctl_mem_import); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_FLAGS_CHANGE, + kbase_api_mem_flags_change, + struct kbase_ioctl_mem_flags_change); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_STREAM_CREATE, + kbase_api_stream_create, + struct kbase_ioctl_stream_create); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_FENCE_VALIDATE, + kbase_api_fence_validate, + struct kbase_ioctl_fence_validate); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_GET_PROFILING_CONTROLS, + kbase_api_get_profiling_controls, + struct kbase_ioctl_get_profiling_controls); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_PROFILE_ADD, + kbase_api_mem_profile_add, + struct kbase_ioctl_mem_profile_add); + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SOFT_EVENT_UPDATE, + kbase_api_soft_event_update, + struct kbase_ioctl_soft_event_update); + +#if MALI_UNIT_TEST + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_TLSTREAM_TEST, + kbase_api_tlstream_test, + struct kbase_ioctl_tlstream_test); + KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_TLSTREAM_STATS, + kbase_api_tlstream_stats, + struct kbase_ioctl_tlstream_stats); +#endif + } + + dev_warn(kbdev->dev, "Unknown ioctl 0x%x nr:%d", cmd, _IOC_NR(cmd)); + + return -ENOIOCTLCMD; +} + +static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + struct kbase_context *kctx = filp->private_data; + struct base_jd_event_v2 uevent; + int out_count = 0; + + if (count < sizeof(uevent)) + return -ENOBUFS; + + do { + while (kbase_event_dequeue(kctx, &uevent)) { + if (out_count > 0) + goto out; + + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(kctx->event_queue, + kbase_event_pending(kctx)) != 0) + return -ERESTARTSYS; + } + if (uevent.event_code == BASE_JD_EVENT_DRV_TERMINATED) { + if (out_count == 0) + return -EPIPE; + goto out; + } + + if (copy_to_user(buf, &uevent, sizeof(uevent)) != 0) + return -EFAULT; + + buf += sizeof(uevent); + out_count++; + count -= sizeof(uevent); + } while (count >= sizeof(uevent)); + + out: + return out_count * sizeof(uevent); +} + +static unsigned int kbase_poll(struct file *filp, poll_table *wait) +{ + struct kbase_context *kctx = filp->private_data; + + poll_wait(filp, &kctx->event_queue, wait); + if (kbase_event_pending(kctx)) + return POLLIN | POLLRDNORM; + + return 0; +} + +void kbase_event_wakeup(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + wake_up_interruptible(&kctx->event_queue); +} + +KBASE_EXPORT_TEST_API(kbase_event_wakeup); + +static int kbase_check_flags(int flags) +{ + /* Enforce that the driver keeps the O_CLOEXEC flag so that execve() always + * closes the file descriptor in a child process. + */ + if (0 == (flags & O_CLOEXEC)) + return -EINVAL; + + return 0; +} + + +/** + * align_and_check - Align the specified pointer to the provided alignment and + * check that it is still in range. + * @gap_end: Highest possible start address for allocation (end of gap in + * address space) + * @gap_start: Start address of current memory area / gap in address space + * @info: vm_unmapped_area_info structure passed to caller, containing + * alignment, length and limits for the allocation + * @is_shader_code: True if the allocation is for shader code (which has + * additional alignment requirements) + * + * Return: true if gap_end is now aligned correctly and is still in range, + * false otherwise + */ +static bool align_and_check(unsigned long *gap_end, unsigned long gap_start, + struct vm_unmapped_area_info *info, bool is_shader_code) +{ + /* Compute highest gap address at the desired alignment */ + (*gap_end) -= info->length; + (*gap_end) -= (*gap_end - info->align_offset) & info->align_mask; + + if (is_shader_code) { + /* Check for 4GB boundary */ + if (0 == (*gap_end & BASE_MEM_MASK_4GB)) + (*gap_end) -= (info->align_offset ? info->align_offset : + info->length); + if (0 == ((*gap_end + info->length) & BASE_MEM_MASK_4GB)) + (*gap_end) -= (info->align_offset ? info->align_offset : + info->length); + + if (!(*gap_end & BASE_MEM_MASK_4GB) || !((*gap_end + + info->length) & BASE_MEM_MASK_4GB)) + return false; + } + + + if ((*gap_end < info->low_limit) || (*gap_end < gap_start)) + return false; + + + return true; +} + +/* The following function is taken from the kernel and just + * renamed. As it's not exported to modules we must copy-paste it here. + */ + +static unsigned long kbase_unmapped_area_topdown(struct vm_unmapped_area_info + *info, bool is_shader_code) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long length, low_limit, high_limit, gap_start, gap_end; + + /* Adjust search length to account for worst case alignment overhead */ + length = info->length + info->align_mask; + if (length < info->length) + return -ENOMEM; + + /* + * Adjust search limits by the desired length. + * See implementation comment at top of unmapped_area(). + */ + gap_end = info->high_limit; + if (gap_end < length) + return -ENOMEM; + high_limit = gap_end - length; + + if (info->low_limit > high_limit) + return -ENOMEM; + low_limit = info->low_limit + length; + + /* Check highest gap, which does not precede any rbtree node */ + gap_start = mm->highest_vm_end; + if (gap_start <= high_limit) { + if (align_and_check(&gap_end, gap_start, info, is_shader_code)) + return gap_end; + } + + /* Check if rbtree root looks promising */ + if (RB_EMPTY_ROOT(&mm->mm_rb)) + return -ENOMEM; + vma = rb_entry(mm->mm_rb.rb_node, struct vm_area_struct, vm_rb); + if (vma->rb_subtree_gap < length) + return -ENOMEM; + + while (true) { + /* Visit right subtree if it looks promising */ + gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; + if (gap_start <= high_limit && vma->vm_rb.rb_right) { + struct vm_area_struct *right = + rb_entry(vma->vm_rb.rb_right, + struct vm_area_struct, vm_rb); + if (right->rb_subtree_gap >= length) { + vma = right; + continue; + } + } + +check_current: + /* Check if current node has a suitable gap */ + gap_end = vma->vm_start; + if (gap_end < low_limit) + return -ENOMEM; + if (gap_start <= high_limit && gap_end - gap_start >= length) { + /* We found a suitable gap. Clip it with the original + * high_limit. */ + if (gap_end > info->high_limit) + gap_end = info->high_limit; + + if (align_and_check(&gap_end, gap_start, info, + is_shader_code)) + return gap_end; + } + + /* Visit left subtree if it looks promising */ + if (vma->vm_rb.rb_left) { + struct vm_area_struct *left = + rb_entry(vma->vm_rb.rb_left, + struct vm_area_struct, vm_rb); + if (left->rb_subtree_gap >= length) { + vma = left; + continue; + } + } + + /* Go back up the rbtree to find next candidate node */ + while (true) { + struct rb_node *prev = &vma->vm_rb; + if (!rb_parent(prev)) + return -ENOMEM; + vma = rb_entry(rb_parent(prev), + struct vm_area_struct, vm_rb); + if (prev == vma->vm_rb.rb_right) { + gap_start = vma->vm_prev ? + vma->vm_prev->vm_end : 0; + goto check_current; + } + } + } + + return -ENOMEM; +} + +static unsigned long kbase_get_unmapped_area(struct file *filp, + const unsigned long addr, const unsigned long len, + const unsigned long pgoff, const unsigned long flags) +{ + /* based on get_unmapped_area, but simplified slightly due to that some + * values are known in advance */ + struct kbase_context *kctx = filp->private_data; + struct mm_struct *mm = current->mm; + struct vm_unmapped_area_info info; + unsigned long align_offset = 0; + unsigned long align_mask = 0; + unsigned long high_limit = mm->mmap_base; + unsigned long low_limit = PAGE_SIZE; + int cpu_va_bits = BITS_PER_LONG; + int gpu_pc_bits = + kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + bool is_shader_code = false; + unsigned long ret; + + /* err on fixed address */ + if ((flags & MAP_FIXED) || addr) + return -EINVAL; + +#ifdef CONFIG_64BIT + /* too big? */ + if (len > TASK_SIZE - SZ_2M) + return -ENOMEM; + + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + + if (kbase_hw_has_feature(kctx->kbdev, + BASE_HW_FEATURE_33BIT_VA)) { + high_limit = kctx->same_va_end << PAGE_SHIFT; + } else { + high_limit = min_t(unsigned long, mm->mmap_base, + (kctx->same_va_end << PAGE_SHIFT)); + if (len >= SZ_2M) { + align_offset = SZ_2M; + align_mask = SZ_2M - 1; + } + } + + low_limit = SZ_2M; + } else { + cpu_va_bits = 32; + } +#endif /* CONFIG_64BIT */ + if ((PFN_DOWN(BASE_MEM_COOKIE_BASE) <= pgoff) && + (PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) > pgoff)) { + int cookie = pgoff - PFN_DOWN(BASE_MEM_COOKIE_BASE); + + if (!kctx->pending_regions[cookie]) + return -EINVAL; + + if (!(kctx->pending_regions[cookie]->flags & + KBASE_REG_GPU_NX)) { + if (cpu_va_bits > gpu_pc_bits) { + align_offset = 1ULL << gpu_pc_bits; + align_mask = align_offset - 1; + is_shader_code = true; + } + } +#ifndef CONFIG_64BIT + } else { + return current->mm->get_unmapped_area(filp, addr, len, pgoff, + flags); +#endif + } + + info.flags = 0; + info.length = len; + info.low_limit = low_limit; + info.high_limit = high_limit; + info.align_offset = align_offset; + info.align_mask = align_mask; + + ret = kbase_unmapped_area_topdown(&info, is_shader_code); + + if (IS_ERR_VALUE(ret) && high_limit == mm->mmap_base && + high_limit < (kctx->same_va_end << PAGE_SHIFT)) { + /* Retry above mmap_base */ + info.low_limit = mm->mmap_base; + info.high_limit = min_t(u64, TASK_SIZE, + (kctx->same_va_end << PAGE_SHIFT)); + + ret = kbase_unmapped_area_topdown(&info, is_shader_code); + } + + return ret; +} + +static const struct file_operations kbase_fops = { + .owner = THIS_MODULE, + .open = kbase_open, + .release = kbase_release, + .read = kbase_read, + .poll = kbase_poll, + .unlocked_ioctl = kbase_ioctl, + .compat_ioctl = kbase_ioctl, + .mmap = kbase_mmap, + .check_flags = kbase_check_flags, + .get_unmapped_area = kbase_get_unmapped_area, +}; + +#ifndef CONFIG_MALI_NO_MALI +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value) +{ + writel(value, kbdev->reg + offset); +} + +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset) +{ + return readl(kbdev->reg + offset); +} +#endif /* !CONFIG_MALI_NO_MALI */ + +/** + * show_policy - Show callback for the power_policy sysfs file. + * + * This function is called to get the contents of the power_policy sysfs + * file. This is a list of the available policies with the currently active one + * surrounded by square brackets. + * + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_policy(struct device *dev, struct device_attribute *attr, char *const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *current_policy; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_get_policy(kbdev); + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** + * set_policy - Store callback for the power_policy sysfs file. + * + * This function is called when the power_policy sysfs file is written to. + * It matches the requested policy against the available policies and if a + * matching policy is found calls kbase_pm_set_policy() to change the + * policy. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *new_policy = NULL; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "power_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_set_policy(kbdev, new_policy); + + return count; +} + +/* + * The sysfs file power_policy. + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(power_policy, S_IRUGO | S_IWUSR, show_policy, set_policy); + +/** + * show_ca_policy - Show callback for the core_availability_policy sysfs file. + * + * This function is called to get the contents of the core_availability_policy + * sysfs file. This is a list of the available policies with the currently + * active one surrounded by square brackets. + * + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_ca_policy(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *current_policy; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_ca_get_policy(kbdev); + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** + * set_ca_policy - Store callback for the core_availability_policy sysfs file. + * + * This function is called when the core_availability_policy sysfs file is + * written to. It matches the requested policy against the available policies + * and if a matching policy is found calls kbase_pm_set_policy() to change + * the policy. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_ca_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *new_policy = NULL; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "core_availability_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_ca_set_policy(kbdev, new_policy); + + return count; +} + +/* + * The sysfs file core_availability_policy + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(core_availability_policy, S_IRUGO | S_IWUSR, show_ca_policy, set_ca_policy); + +/* + * show_core_mask - Show callback for the core_mask sysfs file. + * + * This function is called to get the contents of the core_mask sysfs file. + * + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "Current core mask (JS0) : 0x%llX\n", + kbdev->pm.debug_core_mask[0]); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "Current core mask (JS1) : 0x%llX\n", + kbdev->pm.debug_core_mask[1]); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "Current core mask (JS2) : 0x%llX\n", + kbdev->pm.debug_core_mask[2]); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "Available core mask : 0x%llX\n", + kbdev->gpu_props.props.raw_props.shader_present); + + return ret; +} + +/** + * set_core_mask - Store callback for the core_mask sysfs file. + * + * This function is called when the core_mask sysfs file is written to. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + u64 new_core_mask[3]; + int items; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%llx %llx %llx", + &new_core_mask[0], &new_core_mask[1], + &new_core_mask[2]); + + if (items == 1) + new_core_mask[1] = new_core_mask[2] = new_core_mask[0]; + + if (items == 1 || items == 3) { + u64 shader_present = + kbdev->gpu_props.props.raw_props.shader_present; + u64 group0_core_mask = + kbdev->gpu_props.props.coherency_info.group[0]. + core_mask; + + if ((new_core_mask[0] & shader_present) != new_core_mask[0] || + !(new_core_mask[0] & group0_core_mask) || + (new_core_mask[1] & shader_present) != + new_core_mask[1] || + !(new_core_mask[1] & group0_core_mask) || + (new_core_mask[2] & shader_present) != + new_core_mask[2] || + !(new_core_mask[2] & group0_core_mask)) { + dev_err(dev, "power_policy: invalid core specification\n"); + return -EINVAL; + } + + if (kbdev->pm.debug_core_mask[0] != new_core_mask[0] || + kbdev->pm.debug_core_mask[1] != + new_core_mask[1] || + kbdev->pm.debug_core_mask[2] != + new_core_mask[2]) { + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbase_pm_set_debug_core_mask(kbdev, new_core_mask[0], + new_core_mask[1], new_core_mask[2]); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } + + return count; + } + + dev_err(kbdev->dev, "Couldn't process set_core_mask write operation.\n" + "Use format \n" + "or \n"); + return -EINVAL; +} + +/* + * The sysfs file core_mask. + * + * This is used to restrict shader core availability for debugging purposes. + * Reading it will show the current core mask and the mask of cores available. + * Writing to it will set the current core mask. + */ +static DEVICE_ATTR(core_mask, S_IRUGO | S_IWUSR, show_core_mask, set_core_mask); + +/** + * set_soft_job_timeout - Store callback for the soft_job_timeout sysfs + * file. + * + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The value written to the sysfs file. + * @count: The number of bytes written to the sysfs file. + * + * This allows setting the timeout for software jobs. Waiting soft event wait + * jobs will be cancelled after this period expires, while soft fence wait jobs + * will print debug information if the fence debug feature is enabled. + * + * This is expressed in milliseconds. + * + * Return: count if the function succeeded. An error code on failure. + */ +static ssize_t set_soft_job_timeout(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int soft_job_timeout_ms; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if ((kstrtoint(buf, 0, &soft_job_timeout_ms) != 0) || + (soft_job_timeout_ms <= 0)) + return -EINVAL; + + atomic_set(&kbdev->js_data.soft_job_timeout_ms, + soft_job_timeout_ms); + + return count; +} + +/** + * show_soft_job_timeout - Show callback for the soft_job_timeout sysfs + * file. + * + * This will return the timeout for the software jobs. + * + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer for the sysfs file contents. + * + * Return: The number of bytes output to buf. + */ +static ssize_t show_soft_job_timeout(struct device *dev, + struct device_attribute *attr, + char * const buf) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%i\n", + atomic_read(&kbdev->js_data.soft_job_timeout_ms)); +} + +static DEVICE_ATTR(soft_job_timeout, S_IRUGO | S_IWUSR, + show_soft_job_timeout, set_soft_job_timeout); + +static u32 timeout_ms_to_ticks(struct kbase_device *kbdev, long timeout_ms, + int default_ticks, u32 old_ticks) +{ + if (timeout_ms > 0) { + u64 ticks = timeout_ms * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_period_ns); + if (!ticks) + return 1; + return ticks; + } else if (timeout_ms < 0) { + return default_ticks; + } else { + return old_ticks; + } +} + +/** + * set_js_timeouts - Store callback for the js_timeouts sysfs file. + * + * This function is called to get the contents of the js_timeouts sysfs + * file. This file contains five values separated by whitespace. The values + * are basically the same as %JS_SOFT_STOP_TICKS, %JS_HARD_STOP_TICKS_SS, + * %JS_HARD_STOP_TICKS_DUMPING, %JS_RESET_TICKS_SS, %JS_RESET_TICKS_DUMPING + * configuration values (in that order), with the difference that the js_timeout + * values are expressed in MILLISECONDS. + * + * The js_timeouts sysfile file allows the current values in + * use by the job scheduler to get override. Note that a value needs to + * be other than 0 for it to override the current job scheduler value. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_js_timeouts(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + long js_soft_stop_ms; + long js_soft_stop_ms_cl; + long js_hard_stop_ms_ss; + long js_hard_stop_ms_cl; + long js_hard_stop_ms_dumping; + long js_reset_ms_ss; + long js_reset_ms_cl; + long js_reset_ms_dumping; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld", + &js_soft_stop_ms, &js_soft_stop_ms_cl, + &js_hard_stop_ms_ss, &js_hard_stop_ms_cl, + &js_hard_stop_ms_dumping, &js_reset_ms_ss, + &js_reset_ms_cl, &js_reset_ms_dumping); + + if (items == 8) { + struct kbasep_js_device_data *js_data = &kbdev->js_data; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + +#define UPDATE_TIMEOUT(ticks_name, ms_name, default) do {\ + js_data->ticks_name = timeout_ms_to_ticks(kbdev, ms_name, \ + default, js_data->ticks_name); \ + dev_dbg(kbdev->dev, "Overriding " #ticks_name \ + " with %lu ticks (%lu ms)\n", \ + (unsigned long)js_data->ticks_name, \ + ms_name); \ + } while (0) + + UPDATE_TIMEOUT(soft_stop_ticks, js_soft_stop_ms, + DEFAULT_JS_SOFT_STOP_TICKS); + UPDATE_TIMEOUT(soft_stop_ticks_cl, js_soft_stop_ms_cl, + DEFAULT_JS_SOFT_STOP_TICKS_CL); + UPDATE_TIMEOUT(hard_stop_ticks_ss, js_hard_stop_ms_ss, + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408) ? + DEFAULT_JS_HARD_STOP_TICKS_SS_8408 : + DEFAULT_JS_HARD_STOP_TICKS_SS); + UPDATE_TIMEOUT(hard_stop_ticks_cl, js_hard_stop_ms_cl, + DEFAULT_JS_HARD_STOP_TICKS_CL); + UPDATE_TIMEOUT(hard_stop_ticks_dumping, + js_hard_stop_ms_dumping, + DEFAULT_JS_HARD_STOP_TICKS_DUMPING); + UPDATE_TIMEOUT(gpu_reset_ticks_ss, js_reset_ms_ss, + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408) ? + DEFAULT_JS_RESET_TICKS_SS_8408 : + DEFAULT_JS_RESET_TICKS_SS); + UPDATE_TIMEOUT(gpu_reset_ticks_cl, js_reset_ms_cl, + DEFAULT_JS_RESET_TICKS_CL); + UPDATE_TIMEOUT(gpu_reset_ticks_dumping, js_reset_ms_dumping, + DEFAULT_JS_RESET_TICKS_DUMPING); + + kbase_js_set_timeouts(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return count; + } + + dev_err(kbdev->dev, "Couldn't process js_timeouts write operation.\n" + "Use format \n" + "Write 0 for no change, -1 to restore default timeout\n"); + return -EINVAL; +} + +static unsigned long get_js_timeout_in_ms( + u32 scheduling_period_ns, + u32 ticks) +{ + u64 ms = (u64)ticks * scheduling_period_ns; + + do_div(ms, 1000000UL); + return ms; +} + +/** + * show_js_timeouts - Show callback for the js_timeouts sysfs file. + * + * This function is called to get the contents of the js_timeouts sysfs + * file. It returns the last set values written to the js_timeouts sysfs file. + * If the file didn't get written yet, the values will be current setting in + * use. + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_js_timeouts(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + unsigned long js_soft_stop_ms; + unsigned long js_soft_stop_ms_cl; + unsigned long js_hard_stop_ms_ss; + unsigned long js_hard_stop_ms_cl; + unsigned long js_hard_stop_ms_dumping; + unsigned long js_reset_ms_ss; + unsigned long js_reset_ms_cl; + unsigned long js_reset_ms_dumping; + u32 scheduling_period_ns; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + scheduling_period_ns = kbdev->js_data.scheduling_period_ns; + +#define GET_TIMEOUT(name) get_js_timeout_in_ms(\ + scheduling_period_ns, \ + kbdev->js_data.name) + + js_soft_stop_ms = GET_TIMEOUT(soft_stop_ticks); + js_soft_stop_ms_cl = GET_TIMEOUT(soft_stop_ticks_cl); + js_hard_stop_ms_ss = GET_TIMEOUT(hard_stop_ticks_ss); + js_hard_stop_ms_cl = GET_TIMEOUT(hard_stop_ticks_cl); + js_hard_stop_ms_dumping = GET_TIMEOUT(hard_stop_ticks_dumping); + js_reset_ms_ss = GET_TIMEOUT(gpu_reset_ticks_ss); + js_reset_ms_cl = GET_TIMEOUT(gpu_reset_ticks_cl); + js_reset_ms_dumping = GET_TIMEOUT(gpu_reset_ticks_dumping); + +#undef GET_TIMEOUT + + ret = scnprintf(buf, PAGE_SIZE, "%lu %lu %lu %lu %lu %lu %lu %lu\n", + js_soft_stop_ms, js_soft_stop_ms_cl, + js_hard_stop_ms_ss, js_hard_stop_ms_cl, + js_hard_stop_ms_dumping, js_reset_ms_ss, + js_reset_ms_cl, js_reset_ms_dumping); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/* + * The sysfs file js_timeouts. + * + * This is used to override the current job scheduler values for + * JS_STOP_STOP_TICKS_SS + * JS_STOP_STOP_TICKS_CL + * JS_HARD_STOP_TICKS_SS + * JS_HARD_STOP_TICKS_CL + * JS_HARD_STOP_TICKS_DUMPING + * JS_RESET_TICKS_SS + * JS_RESET_TICKS_CL + * JS_RESET_TICKS_DUMPING. + */ +static DEVICE_ATTR(js_timeouts, S_IRUGO | S_IWUSR, show_js_timeouts, set_js_timeouts); + +static u32 get_new_js_timeout( + u32 old_period, + u32 old_ticks, + u32 new_scheduling_period_ns) +{ + u64 ticks = (u64)old_period * (u64)old_ticks; + do_div(ticks, new_scheduling_period_ns); + return ticks?ticks:1; +} + +/** + * set_js_scheduling_period - Store callback for the js_scheduling_period sysfs + * file + * @dev: The device the sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * This function is called when the js_scheduling_period sysfs file is written + * to. It checks the data written, and if valid updates the js_scheduling_period + * value + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_js_scheduling_period(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int ret; + unsigned int js_scheduling_period; + u32 new_scheduling_period_ns; + u32 old_period; + struct kbasep_js_device_data *js_data; + unsigned long flags; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + js_data = &kbdev->js_data; + + ret = kstrtouint(buf, 0, &js_scheduling_period); + if (ret || !js_scheduling_period) { + dev_err(kbdev->dev, "Couldn't process js_scheduling_period write operation.\n" + "Use format \n"); + return -EINVAL; + } + + new_scheduling_period_ns = js_scheduling_period * 1000000; + + /* Update scheduling timeouts */ + mutex_lock(&js_data->runpool_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* If no contexts have been scheduled since js_timeouts was last written + * to, the new timeouts might not have been latched yet. So check if an + * update is pending and use the new values if necessary. */ + + /* Use previous 'new' scheduling period as a base if present. */ + old_period = js_data->scheduling_period_ns; + +#define SET_TIMEOUT(name) \ + (js_data->name = get_new_js_timeout(\ + old_period, \ + kbdev->js_data.name, \ + new_scheduling_period_ns)) + + SET_TIMEOUT(soft_stop_ticks); + SET_TIMEOUT(soft_stop_ticks_cl); + SET_TIMEOUT(hard_stop_ticks_ss); + SET_TIMEOUT(hard_stop_ticks_cl); + SET_TIMEOUT(hard_stop_ticks_dumping); + SET_TIMEOUT(gpu_reset_ticks_ss); + SET_TIMEOUT(gpu_reset_ticks_cl); + SET_TIMEOUT(gpu_reset_ticks_dumping); + +#undef SET_TIMEOUT + + js_data->scheduling_period_ns = new_scheduling_period_ns; + + kbase_js_set_timeouts(kbdev); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&js_data->runpool_mutex); + + dev_dbg(kbdev->dev, "JS scheduling period: %dms\n", + js_scheduling_period); + + return count; +} + +/** + * show_js_scheduling_period - Show callback for the js_scheduling_period sysfs + * entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU information. + * + * This function is called to get the current period used for the JS scheduling + * period. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_js_scheduling_period(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + u32 period; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + period = kbdev->js_data.scheduling_period_ns; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", + period / 1000000); + + return ret; +} + +static DEVICE_ATTR(js_scheduling_period, S_IRUGO | S_IWUSR, + show_js_scheduling_period, set_js_scheduling_period); + +#if !MALI_CUSTOMER_RELEASE +/** + * set_force_replay - Store callback for the force_replay sysfs file. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_force_replay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (!strncmp("limit=", buf, MIN(6, count))) { + int force_replay_limit; + int items = sscanf(buf, "limit=%u", &force_replay_limit); + + if (items == 1) { + kbdev->force_replay_random = false; + kbdev->force_replay_limit = force_replay_limit; + kbdev->force_replay_count = 0; + + return count; + } + } else if (!strncmp("random_limit", buf, MIN(12, count))) { + kbdev->force_replay_random = true; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("norandom_limit", buf, MIN(14, count))) { + kbdev->force_replay_random = false; + kbdev->force_replay_limit = KBASEP_FORCE_REPLAY_DISABLED; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("core_req=", buf, MIN(9, count))) { + unsigned int core_req; + int items = sscanf(buf, "core_req=%x", &core_req); + + if (items == 1) { + kbdev->force_replay_core_req = (base_jd_core_req)core_req; + + return count; + } + } + dev_err(kbdev->dev, "Couldn't process force_replay write operation.\nPossible settings: limit=, random_limit, norandom_limit, core_req=\n"); + return -EINVAL; +} + +/** + * show_force_replay - Show callback for the force_replay sysfs file. + * + * This function is called to get the contents of the force_replay sysfs + * file. It returns the last set value written to the force_replay sysfs file. + * If the file didn't get written yet, the values will be 0. + * + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_force_replay(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (kbdev->force_replay_random) + ret = scnprintf(buf, PAGE_SIZE, + "limit=0\nrandom_limit\ncore_req=%x\n", + kbdev->force_replay_core_req); + else + ret = scnprintf(buf, PAGE_SIZE, + "limit=%u\nnorandom_limit\ncore_req=%x\n", + kbdev->force_replay_limit, + kbdev->force_replay_core_req); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/* + * The sysfs file force_replay. + */ +static DEVICE_ATTR(force_replay, S_IRUGO | S_IWUSR, show_force_replay, + set_force_replay); +#endif /* !MALI_CUSTOMER_RELEASE */ + +#ifdef CONFIG_MALI_DEBUG +static ssize_t set_js_softstop_always(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int ret; + int softstop_always; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = kstrtoint(buf, 0, &softstop_always); + if (ret || ((softstop_always != 0) && (softstop_always != 1))) { + dev_err(kbdev->dev, "Couldn't process js_softstop_always write operation.\n" + "Use format \n"); + return -EINVAL; + } + + kbdev->js_data.softstop_always = (bool) softstop_always; + dev_dbg(kbdev->dev, "Support for softstop on a single context: %s\n", + (kbdev->js_data.softstop_always) ? + "Enabled" : "Disabled"); + return count; +} + +static ssize_t show_js_softstop_always(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->js_data.softstop_always); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/* + * By default, soft-stops are disabled when only a single context is present. + * The ability to enable soft-stop when only a single context is present can be + * used for debug and unit-testing purposes. + * (see CL t6xx_stress_1 unit-test as an example whereby this feature is used.) + */ +static DEVICE_ATTR(js_softstop_always, S_IRUGO | S_IWUSR, show_js_softstop_always, set_js_softstop_always); +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_MALI_DEBUG +typedef void (kbasep_debug_command_func) (struct kbase_device *); + +enum kbasep_debug_command_code { + KBASEP_DEBUG_COMMAND_DUMPTRACE, + + /* This must be the last enum */ + KBASEP_DEBUG_COMMAND_COUNT +}; + +struct kbasep_debug_command { + char *str; + kbasep_debug_command_func *func; +}; + +/* Debug commands supported by the driver */ +static const struct kbasep_debug_command debug_commands[] = { + { + .str = "dumptrace", + .func = &kbasep_trace_dump, + } +}; + +/** + * show_debug - Show callback for the debug_command sysfs file. + * + * This function is called to get the contents of the debug_command sysfs + * file. This is a list of the available debug commands, separated by newlines. + * + * @dev: The device this sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The output buffer for the sysfs file contents + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_debug(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT && ret < PAGE_SIZE; i++) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s\n", debug_commands[i].str); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** + * issue_debug - Store callback for the debug_command sysfs file. + * + * This function is called when the debug_command sysfs file is written to. + * It matches the requested command against the available commands, and if + * a matching command is found calls the associated function from + * @debug_commands to issue the command. + * + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t issue_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT; i++) { + if (sysfs_streq(debug_commands[i].str, buf)) { + debug_commands[i].func(kbdev); + return count; + } + } + + /* Debug Command not found */ + dev_err(dev, "debug_command: command not known\n"); + return -EINVAL; +} + +/* The sysfs file debug_command. + * + * This is used to issue general debug commands to the device driver. + * Reading it will produce a list of debug commands, separated by newlines. + * Writing to it with one of those commands will issue said command. + */ +static DEVICE_ATTR(debug_command, S_IRUGO | S_IWUSR, show_debug, issue_debug); +#endif /* CONFIG_MALI_DEBUG */ + +/** + * kbase_show_gpuinfo - Show callback for the gpuinfo sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU information. + * + * This function is called to get a description of the present Mali + * GPU via the gpuinfo sysfs entry. This includes the GPU family, the + * number of cores, the hardware version and the raw product id. For + * example + * + * Mali-T60x MP4 r0p0 0x6956 + * + * Return: The number of bytes output to @buf. + */ +static ssize_t kbase_show_gpuinfo(struct device *dev, + struct device_attribute *attr, char *buf) +{ + static const struct gpu_product_id_name { + unsigned id; + char *name; + } gpu_product_id_names[] = { + { .id = GPU_ID_PI_T60X, .name = "Mali-T60x" }, + { .id = GPU_ID_PI_T62X, .name = "Mali-T62x" }, + { .id = GPU_ID_PI_T72X, .name = "Mali-T72x" }, + { .id = GPU_ID_PI_T76X, .name = "Mali-T76x" }, + { .id = GPU_ID_PI_T82X, .name = "Mali-T82x" }, + { .id = GPU_ID_PI_T83X, .name = "Mali-T83x" }, + { .id = GPU_ID_PI_T86X, .name = "Mali-T86x" }, + { .id = GPU_ID_PI_TFRX, .name = "Mali-T88x" }, + { .id = GPU_ID2_PRODUCT_TMIX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, + .name = "Mali-G71" }, + { .id = GPU_ID2_PRODUCT_THEX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, + .name = "Mali-G72" }, + { .id = GPU_ID2_PRODUCT_TSIX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, + .name = "Mali-G51" }, + }; + const char *product_name = "(Unknown Mali GPU)"; + struct kbase_device *kbdev; + u32 gpu_id; + unsigned product_id, product_id_mask; + unsigned i; + bool is_new_format; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + product_id = gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT; + is_new_format = GPU_ID_IS_NEW_FORMAT(product_id); + product_id_mask = + (is_new_format ? + GPU_ID2_PRODUCT_MODEL : + GPU_ID_VERSION_PRODUCT_ID) >> + GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + for (i = 0; i < ARRAY_SIZE(gpu_product_id_names); ++i) { + const struct gpu_product_id_name *p = &gpu_product_id_names[i]; + + if ((GPU_ID_IS_NEW_FORMAT(p->id) == is_new_format) && + (p->id & product_id_mask) == + (product_id & product_id_mask)) { + product_name = p->name; + break; + } + } + + return scnprintf(buf, PAGE_SIZE, "%s %d cores r%dp%d 0x%04X\n", + product_name, kbdev->gpu_props.num_cores, + (gpu_id & GPU_ID_VERSION_MAJOR) >> GPU_ID_VERSION_MAJOR_SHIFT, + (gpu_id & GPU_ID_VERSION_MINOR) >> GPU_ID_VERSION_MINOR_SHIFT, + product_id); +} +static DEVICE_ATTR(gpuinfo, S_IRUGO, kbase_show_gpuinfo, NULL); + +/** + * set_dvfs_period - Store callback for the dvfs_period sysfs file. + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * This function is called when the dvfs_period sysfs file is written to. It + * checks the data written, and if valid updates the DVFS period variable, + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_dvfs_period(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int ret; + int dvfs_period; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = kstrtoint(buf, 0, &dvfs_period); + if (ret || dvfs_period <= 0) { + dev_err(kbdev->dev, "Couldn't process dvfs_period write operation.\n" + "Use format \n"); + return -EINVAL; + } + + kbdev->pm.dvfs_period = dvfs_period; + dev_dbg(kbdev->dev, "DVFS period: %dms\n", dvfs_period); + + return count; +} + +/** + * show_dvfs_period - Show callback for the dvfs_period sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU information. + * + * This function is called to get the current period used for the DVFS sample + * timer. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_dvfs_period(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->pm.dvfs_period); + + return ret; +} + +static DEVICE_ATTR(dvfs_period, S_IRUGO | S_IWUSR, show_dvfs_period, + set_dvfs_period); + +/** + * set_pm_poweroff - Store callback for the pm_poweroff sysfs file. + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * This function is called when the pm_poweroff sysfs file is written to. + * + * This file contains three values separated by whitespace. The values + * are gpu_poweroff_time (the period of the poweroff timer, in ns), + * poweroff_shader_ticks (the number of poweroff timer ticks before an idle + * shader is powered off), and poweroff_gpu_ticks (the number of poweroff timer + * ticks before the GPU is powered off), in that order. + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_pm_poweroff(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + s64 gpu_poweroff_time; + int poweroff_shader_ticks, poweroff_gpu_ticks; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%llu %u %u", &gpu_poweroff_time, + &poweroff_shader_ticks, + &poweroff_gpu_ticks); + if (items != 3) { + dev_err(kbdev->dev, "Couldn't process pm_poweroff write operation.\n" + "Use format \n"); + return -EINVAL; + } + + kbdev->pm.gpu_poweroff_time = HR_TIMER_DELAY_NSEC(gpu_poweroff_time); + kbdev->pm.poweroff_shader_ticks = poweroff_shader_ticks; + kbdev->pm.poweroff_gpu_ticks = poweroff_gpu_ticks; + + return count; +} + +/** + * show_pm_poweroff - Show callback for the pm_poweroff sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU information. + * + * This function is called to get the current period used for the DVFS sample + * timer. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_pm_poweroff(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%llu %u %u\n", + ktime_to_ns(kbdev->pm.gpu_poweroff_time), + kbdev->pm.poweroff_shader_ticks, + kbdev->pm.poweroff_gpu_ticks); + + return ret; +} + +static DEVICE_ATTR(pm_poweroff, S_IRUGO | S_IWUSR, show_pm_poweroff, + set_pm_poweroff); + +/** + * set_reset_timeout - Store callback for the reset_timeout sysfs file. + * @dev: The device with sysfs file is for + * @attr: The attributes of the sysfs file + * @buf: The value written to the sysfs file + * @count: The number of bytes written to the sysfs file + * + * This function is called when the reset_timeout sysfs file is written to. It + * checks the data written, and if valid updates the reset timeout. + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_reset_timeout(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int ret; + int reset_timeout; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = kstrtoint(buf, 0, &reset_timeout); + if (ret || reset_timeout <= 0) { + dev_err(kbdev->dev, "Couldn't process reset_timeout write operation.\n" + "Use format \n"); + return -EINVAL; + } + + kbdev->reset_timeout_ms = reset_timeout; + dev_dbg(kbdev->dev, "Reset timeout: %dms\n", reset_timeout); + + return count; +} + +/** + * show_reset_timeout - Show callback for the reset_timeout sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU information. + * + * This function is called to get the current reset timeout. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_reset_timeout(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->reset_timeout_ms); + + return ret; +} + +static DEVICE_ATTR(reset_timeout, S_IRUGO | S_IWUSR, show_reset_timeout, + set_reset_timeout); + + + +static ssize_t show_mem_pool_size(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%zu\n", + kbase_mem_pool_size(&kbdev->mem_pool)); + + return ret; +} + +static ssize_t set_mem_pool_size(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + size_t new_size; + int err; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + err = kstrtoul(buf, 0, (unsigned long *)&new_size); + if (err) + return err; + + kbase_mem_pool_trim(&kbdev->mem_pool, new_size); + + return count; +} + +static DEVICE_ATTR(mem_pool_size, S_IRUGO | S_IWUSR, show_mem_pool_size, + set_mem_pool_size); + +static ssize_t show_mem_pool_max_size(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%zu\n", + kbase_mem_pool_max_size(&kbdev->mem_pool)); + + return ret; +} + +static ssize_t set_mem_pool_max_size(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + size_t new_max_size; + int err; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + err = kstrtoul(buf, 0, (unsigned long *)&new_max_size); + if (err) + return -EINVAL; + + kbase_mem_pool_set_max_size(&kbdev->mem_pool, new_max_size); + + return count; +} + +static DEVICE_ATTR(mem_pool_max_size, S_IRUGO | S_IWUSR, show_mem_pool_max_size, + set_mem_pool_max_size); + +/** + * show_lp_mem_pool_size - Show size of the large memory pages pool. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the pool size. + * + * This function is called to get the number of large memory pages which currently populate the kbdev pool. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_lp_mem_pool_size(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kbase_mem_pool_size(&kbdev->lp_mem_pool)); +} + +/** + * set_lp_mem_pool_size - Set size of the large memory pages pool. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The value written to the sysfs file. + * @count: The number of bytes written to the sysfs file. + * + * This function is called to set the number of large memory pages which should populate the kbdev pool. + * This may cause existing pages to be removed from the pool, or new pages to be created and then added to the pool. + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_lp_mem_pool_size(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + unsigned long new_size; + int err; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + err = kstrtoul(buf, 0, &new_size); + if (err) + return err; + + kbase_mem_pool_trim(&kbdev->lp_mem_pool, new_size); + + return count; +} + +static DEVICE_ATTR(lp_mem_pool_size, S_IRUGO | S_IWUSR, show_lp_mem_pool_size, + set_lp_mem_pool_size); + +/** + * show_lp_mem_pool_max_size - Show maximum size of the large memory pages pool. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the pool size. + * + * This function is called to get the maximum number of large memory pages that the kbdev pool can possibly contain. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t show_lp_mem_pool_max_size(struct device *dev, + struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kbase_mem_pool_max_size(&kbdev->lp_mem_pool)); +} + +/** + * set_lp_mem_pool_max_size - Set maximum size of the large memory pages pool. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The value written to the sysfs file. + * @count: The number of bytes written to the sysfs file. + * + * This function is called to set the maximum number of large memory pages that the kbdev pool can possibly contain. + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t set_lp_mem_pool_max_size(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + unsigned long new_max_size; + int err; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + err = kstrtoul(buf, 0, &new_max_size); + if (err) + return -EINVAL; + + kbase_mem_pool_set_max_size(&kbdev->lp_mem_pool, new_max_size); + + return count; +} + +static DEVICE_ATTR(lp_mem_pool_max_size, S_IRUGO | S_IWUSR, show_lp_mem_pool_max_size, + set_lp_mem_pool_max_size); + +#ifdef CONFIG_DEBUG_FS + +/* Number of entries in serialize_jobs_settings[] */ +#define NR_SERIALIZE_JOBS_SETTINGS 5 +/* Maximum string length in serialize_jobs_settings[].name */ +#define MAX_SERIALIZE_JOBS_NAME_LEN 16 + +static struct +{ + char *name; + u8 setting; +} serialize_jobs_settings[NR_SERIALIZE_JOBS_SETTINGS] = { + {"none", 0}, + {"intra-slot", KBASE_SERIALIZE_INTRA_SLOT}, + {"inter-slot", KBASE_SERIALIZE_INTER_SLOT}, + {"full", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT}, + {"full-reset", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT | + KBASE_SERIALIZE_RESET} +}; + +/** + * kbasep_serialize_jobs_seq_show - Show callback for the serialize_jobs debugfs + * file + * @sfile: seq_file pointer + * @data: Private callback data + * + * This function is called to get the contents of the serialize_jobs debugfs + * file. This is a list of the available settings with the currently active one + * surrounded by square brackets. + * + * Return: 0 on success, or an error code on error + */ +static int kbasep_serialize_jobs_seq_show(struct seq_file *sfile, void *data) +{ + struct kbase_device *kbdev = sfile->private; + int i; + + CSTD_UNUSED(data); + + for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) { + if (kbdev->serialize_jobs == serialize_jobs_settings[i].setting) + seq_printf(sfile, "[%s] ", + serialize_jobs_settings[i].name); + else + seq_printf(sfile, "%s ", + serialize_jobs_settings[i].name); + } + + seq_puts(sfile, "\n"); + + return 0; +} + +/** + * kbasep_serialize_jobs_debugfs_write - Store callback for the serialize_jobs + * debugfs file. + * @file: File pointer + * @ubuf: User buffer containing data to store + * @count: Number of bytes in user buffer + * @ppos: File position + * + * This function is called when the serialize_jobs debugfs file is written to. + * It matches the requested setting against the available settings and if a + * matching setting is found updates kbdev->serialize_jobs. + * + * Return: @count if the function succeeded. An error code on failure. + */ +static ssize_t kbasep_serialize_jobs_debugfs_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct kbase_device *kbdev = s->private; + char buf[MAX_SERIALIZE_JOBS_NAME_LEN]; + int i; + bool valid = false; + + CSTD_UNUSED(ppos); + + count = min_t(size_t, sizeof(buf) - 1, count); + if (copy_from_user(buf, ubuf, count)) + return -EFAULT; + + buf[count] = 0; + + for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) { + if (sysfs_streq(serialize_jobs_settings[i].name, buf)) { + kbdev->serialize_jobs = + serialize_jobs_settings[i].setting; + valid = true; + break; + } + } + + if (!valid) { + dev_err(kbdev->dev, "serialize_jobs: invalid setting\n"); + return -EINVAL; + } + + return count; +} + +/** + * kbasep_serialize_jobs_debugfs_open - Open callback for the serialize_jobs + * debugfs file + * @in: inode pointer + * @file: file pointer + * + * Return: Zero on success, error code on failure + */ +static int kbasep_serialize_jobs_debugfs_open(struct inode *in, + struct file *file) +{ + return single_open(file, kbasep_serialize_jobs_seq_show, in->i_private); +} + +static const struct file_operations kbasep_serialize_jobs_debugfs_fops = { + .open = kbasep_serialize_jobs_debugfs_open, + .read = seq_read, + .write = kbasep_serialize_jobs_debugfs_write, + .llseek = seq_lseek, + .release = single_release, +}; + +#endif /* CONFIG_DEBUG_FS */ + +static int kbasep_protected_mode_init(struct kbase_device *kbdev) +{ +#ifdef CONFIG_OF + struct device_node *protected_node; + struct platform_device *pdev; + struct protected_mode_device *protected_dev; +#endif + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE)) { + /* Use native protected ops */ + kbdev->protected_dev = kzalloc(sizeof(*kbdev->protected_dev), + GFP_KERNEL); + if (!kbdev->protected_dev) + return -ENOMEM; + kbdev->protected_dev->data = kbdev; + kbdev->protected_ops = &kbase_native_protected_ops; + kbdev->protected_mode_support = true; + return 0; + } + + kbdev->protected_mode_support = false; + +#ifdef CONFIG_OF + protected_node = of_parse_phandle(kbdev->dev->of_node, + "protected-mode-switcher", 0); + + if (!protected_node) + protected_node = of_parse_phandle(kbdev->dev->of_node, + "secure-mode-switcher", 0); + + if (!protected_node) { + /* If protected_node cannot be looked up then we assume + * protected mode is not supported on this platform. */ + dev_info(kbdev->dev, "Protected mode not available\n"); + return 0; + } + + pdev = of_find_device_by_node(protected_node); + if (!pdev) + return -EINVAL; + + protected_dev = platform_get_drvdata(pdev); + if (!protected_dev) + return -EPROBE_DEFER; + + kbdev->protected_ops = &protected_dev->ops; + kbdev->protected_dev = protected_dev; + + if (kbdev->protected_ops) { + int err; + + /* Make sure protected mode is disabled on startup */ + mutex_lock(&kbdev->pm.lock); + err = kbdev->protected_ops->protected_mode_disable( + kbdev->protected_dev); + mutex_unlock(&kbdev->pm.lock); + + /* protected_mode_disable() returns -EINVAL if not supported */ + kbdev->protected_mode_support = (err != -EINVAL); + } +#endif + return 0; +} + +static void kbasep_protected_mode_term(struct kbase_device *kbdev) +{ + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE)) + kfree(kbdev->protected_dev); +} + +#ifdef CONFIG_MALI_NO_MALI +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + return 0; +} +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ +} +#else /* CONFIG_MALI_NO_MALI */ +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + int err = 0; + + if (!request_mem_region(kbdev->reg_start, kbdev->reg_size, dev_name(kbdev->dev))) { + dev_err(kbdev->dev, "Register window unavailable\n"); + err = -EIO; + goto out_region; + } + + kbdev->reg = ioremap(kbdev->reg_start, kbdev->reg_size); + if (!kbdev->reg) { + dev_err(kbdev->dev, "Can't remap register window\n"); + err = -EINVAL; + goto out_ioremap; + } + + return err; + + out_ioremap: + release_mem_region(kbdev->reg_start, kbdev->reg_size); + out_region: + return err; +} + +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ + if (kbdev->reg) { + iounmap(kbdev->reg); + release_mem_region(kbdev->reg_start, kbdev->reg_size); + kbdev->reg = NULL; + kbdev->reg_start = 0; + kbdev->reg_size = 0; + } +} +#endif /* CONFIG_MALI_NO_MALI */ + +static int registers_map(struct kbase_device * const kbdev) +{ + + /* the first memory resource is the physical address of the GPU + * registers */ + struct platform_device *pdev = to_platform_device(kbdev->dev); + struct resource *reg_res; + int err; + + reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!reg_res) { + dev_err(kbdev->dev, "Invalid register resource\n"); + return -ENOENT; + } + + kbdev->reg_start = reg_res->start; + kbdev->reg_size = resource_size(reg_res); + + err = kbase_common_reg_map(kbdev); + if (err) { + dev_err(kbdev->dev, "Failed to map registers\n"); + return err; + } + + return 0; +} + +static void registers_unmap(struct kbase_device *kbdev) +{ + kbase_common_reg_unmap(kbdev); +} + +static int power_control_init(struct platform_device *pdev) +{ + struct kbase_device *kbdev = to_kbase_device(&pdev->dev); + int err = 0; + + if (!kbdev) + return -ENODEV; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \ + && defined(CONFIG_REGULATOR) + kbdev->regulator = regulator_get_optional(kbdev->dev, "mali"); + if (IS_ERR_OR_NULL(kbdev->regulator)) { + err = PTR_ERR(kbdev->regulator); + kbdev->regulator = NULL; + if (err == -EPROBE_DEFER) { + dev_err(&pdev->dev, "Failed to get regulator\n"); + return err; + } + dev_info(kbdev->dev, + "Continuing without Mali regulator control\n"); + /* Allow probe to continue without regulator */ + } +#endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ + + kbdev->clock = clk_get(kbdev->dev, "clk_mali"); + if (IS_ERR_OR_NULL(kbdev->clock)) { + err = PTR_ERR(kbdev->clock); + kbdev->clock = NULL; + if (err == -EPROBE_DEFER) { + dev_err(&pdev->dev, "Failed to get clock\n"); + goto fail; + } + dev_info(kbdev->dev, "Continuing without Mali clock control\n"); + /* Allow probe to continue without clock. */ + } else { + err = clk_prepare_enable(kbdev->clock); + if (err) { + dev_err(kbdev->dev, + "Failed to prepare and enable clock (%d)\n", + err); + goto fail; + } + } + +#if defined(CONFIG_OF) && defined(CONFIG_PM_OPP) + /* Register the OPPs if they are available in device tree */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) \ + || defined(LSK_OPPV2_BACKPORT) + err = dev_pm_opp_of_add_table(kbdev->dev); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + err = of_init_opp_table(kbdev->dev); +#else + err = 0; +#endif /* LINUX_VERSION_CODE */ + if (err) + dev_dbg(kbdev->dev, "OPP table not found\n"); +#endif /* CONFIG_OF && CONFIG_PM_OPP */ + + return 0; + +fail: + +if (kbdev->clock != NULL) { + clk_put(kbdev->clock); + kbdev->clock = NULL; +} + +#ifdef CONFIG_REGULATOR + if (NULL != kbdev->regulator) { + regulator_put(kbdev->regulator); + kbdev->regulator = NULL; + } +#endif + + return err; +} + +static void power_control_term(struct kbase_device *kbdev) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \ + defined(LSK_OPPV2_BACKPORT) + dev_pm_opp_of_remove_table(kbdev->dev); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) + of_free_opp_table(kbdev->dev); +#endif + + if (kbdev->clock) { + clk_disable_unprepare(kbdev->clock); + clk_put(kbdev->clock); + kbdev->clock = NULL; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \ + && defined(CONFIG_REGULATOR) + if (kbdev->regulator) { + regulator_put(kbdev->regulator); + kbdev->regulator = NULL; + } +#endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ +} + +#ifdef CONFIG_DEBUG_FS + +#if KBASE_GPU_RESET_EN +#include + +static void trigger_quirks_reload(struct kbase_device *kbdev) +{ + kbase_pm_context_active(kbdev); + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); + kbase_pm_context_idle(kbdev); +} + +#define MAKE_QUIRK_ACCESSORS(type) \ +static int type##_quirks_set(void *data, u64 val) \ +{ \ + struct kbase_device *kbdev; \ + kbdev = (struct kbase_device *)data; \ + kbdev->hw_quirks_##type = (u32)val; \ + trigger_quirks_reload(kbdev); \ + return 0;\ +} \ +\ +static int type##_quirks_get(void *data, u64 *val) \ +{ \ + struct kbase_device *kbdev;\ + kbdev = (struct kbase_device *)data;\ + *val = kbdev->hw_quirks_##type;\ + return 0;\ +} \ +DEFINE_SIMPLE_ATTRIBUTE(fops_##type##_quirks, type##_quirks_get,\ + type##_quirks_set, "%llu\n") + +MAKE_QUIRK_ACCESSORS(sc); +MAKE_QUIRK_ACCESSORS(tiler); +MAKE_QUIRK_ACCESSORS(mmu); +MAKE_QUIRK_ACCESSORS(jm); + +#endif /* KBASE_GPU_RESET_EN */ + +/** + * debugfs_protected_debug_mode_read - "protected_debug_mode" debugfs read + * @file: File object to read is for + * @buf: User buffer to populate with data + * @len: Length of user buffer + * @ppos: Offset within file object + * + * Retrieves the current status of protected debug mode + * (0 = disabled, 1 = enabled) + * + * Return: Number of bytes added to user buffer + */ +static ssize_t debugfs_protected_debug_mode_read(struct file *file, + char __user *buf, size_t len, loff_t *ppos) +{ + struct kbase_device *kbdev = (struct kbase_device *)file->private_data; + u32 gpu_status; + ssize_t ret_val; + + kbase_pm_context_active(kbdev); + gpu_status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS), NULL); + kbase_pm_context_idle(kbdev); + + if (gpu_status & GPU_DBGEN) + ret_val = simple_read_from_buffer(buf, len, ppos, "1\n", 2); + else + ret_val = simple_read_from_buffer(buf, len, ppos, "0\n", 2); + + return ret_val; +} + +/* + * struct fops_protected_debug_mode - "protected_debug_mode" debugfs fops + * + * Contains the file operations for the "protected_debug_mode" debugfs file + */ +static const struct file_operations fops_protected_debug_mode = { + .open = simple_open, + .read = debugfs_protected_debug_mode_read, + .llseek = default_llseek, +}; + +static int kbase_device_debugfs_init(struct kbase_device *kbdev) +{ + struct dentry *debugfs_ctx_defaults_directory; + int err; + + kbdev->mali_debugfs_directory = debugfs_create_dir(kbdev->devname, + NULL); + if (!kbdev->mali_debugfs_directory) { + dev_err(kbdev->dev, "Couldn't create mali debugfs directory\n"); + err = -ENOMEM; + goto out; + } + + kbdev->debugfs_ctx_directory = debugfs_create_dir("ctx", + kbdev->mali_debugfs_directory); + if (!kbdev->debugfs_ctx_directory) { + dev_err(kbdev->dev, "Couldn't create mali debugfs ctx directory\n"); + err = -ENOMEM; + goto out; + } + + debugfs_ctx_defaults_directory = debugfs_create_dir("defaults", + kbdev->debugfs_ctx_directory); + if (!debugfs_ctx_defaults_directory) { + dev_err(kbdev->dev, "Couldn't create mali debugfs ctx defaults directory\n"); + err = -ENOMEM; + goto out; + } + +#if !MALI_CUSTOMER_RELEASE + kbasep_regs_dump_debugfs_init(kbdev); +#endif /* !MALI_CUSTOMER_RELEASE */ + kbasep_regs_history_debugfs_init(kbdev); + + kbase_debug_job_fault_debugfs_init(kbdev); + kbasep_gpu_memory_debugfs_init(kbdev); + kbase_as_fault_debugfs_init(kbdev); +#if KBASE_GPU_RESET_EN + /* fops_* variables created by invocations of macro + * MAKE_QUIRK_ACCESSORS() above. */ + debugfs_create_file("quirks_sc", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_sc_quirks); + debugfs_create_file("quirks_tiler", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_tiler_quirks); + debugfs_create_file("quirks_mmu", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_mmu_quirks); + debugfs_create_file("quirks_jm", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_jm_quirks); +#endif /* KBASE_GPU_RESET_EN */ + + debugfs_create_bool("infinite_cache", 0644, + debugfs_ctx_defaults_directory, + &kbdev->infinite_cache_active_default); + + debugfs_create_size_t("mem_pool_max_size", 0644, + debugfs_ctx_defaults_directory, + &kbdev->mem_pool_max_size_default); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) { + debugfs_create_file("protected_debug_mode", S_IRUGO, + kbdev->mali_debugfs_directory, kbdev, + &fops_protected_debug_mode); + } + +#if KBASE_TRACE_ENABLE + kbasep_trace_debugfs_init(kbdev); +#endif /* KBASE_TRACE_ENABLE */ + +#ifdef CONFIG_MALI_TRACE_TIMELINE + kbasep_trace_timeline_debugfs_init(kbdev); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_DEVFREQ_THERMAL + if (kbdev->inited_subsys & inited_devfreq) + kbase_ipa_debugfs_init(kbdev); +#endif /* CONFIG_DEVFREQ_THERMAL */ +#endif /* CONFIG_MALI_DEVFREQ */ + +#ifdef CONFIG_DEBUG_FS + debugfs_create_file("serialize_jobs", S_IRUGO | S_IWUSR, + kbdev->mali_debugfs_directory, kbdev, + &kbasep_serialize_jobs_debugfs_fops); +#endif /* CONFIG_DEBUG_FS */ + + return 0; + +out: + debugfs_remove_recursive(kbdev->mali_debugfs_directory); + return err; +} + +static void kbase_device_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove_recursive(kbdev->mali_debugfs_directory); +} + +#else /* CONFIG_DEBUG_FS */ +static inline int kbase_device_debugfs_init(struct kbase_device *kbdev) +{ + return 0; +} + +static inline void kbase_device_debugfs_term(struct kbase_device *kbdev) { } +#endif /* CONFIG_DEBUG_FS */ + +static void kbase_device_coherency_init(struct kbase_device *kbdev, + unsigned prod_id) +{ +#ifdef CONFIG_OF + u32 supported_coherency_bitmap = + kbdev->gpu_props.props.raw_props.coherency_mode; + const void *coherency_override_dts; + u32 override_coherency; + + /* Only for tMIx : + * (COHERENCY_ACE_LITE | COHERENCY_ACE) was incorrectly + * documented for tMIx so force correct value here. + */ + if (GPU_ID_IS_NEW_FORMAT(prod_id) && + (GPU_ID2_MODEL_MATCH_VALUE(prod_id) == + GPU_ID2_PRODUCT_TMIX)) + if (supported_coherency_bitmap == + COHERENCY_FEATURE_BIT(COHERENCY_ACE)) + supported_coherency_bitmap |= + COHERENCY_FEATURE_BIT(COHERENCY_ACE_LITE); + +#endif /* CONFIG_OF */ + + kbdev->system_coherency = COHERENCY_NONE; + + /* device tree may override the coherency */ +#ifdef CONFIG_OF + coherency_override_dts = of_get_property(kbdev->dev->of_node, + "system-coherency", + NULL); + if (coherency_override_dts) { + + override_coherency = be32_to_cpup(coherency_override_dts); + + if ((override_coherency <= COHERENCY_NONE) && + (supported_coherency_bitmap & + COHERENCY_FEATURE_BIT(override_coherency))) { + + kbdev->system_coherency = override_coherency; + + dev_info(kbdev->dev, + "Using coherency mode %u set from dtb", + override_coherency); + } else + dev_warn(kbdev->dev, + "Ignoring unsupported coherency mode %u set from dtb", + override_coherency); + } + +#endif /* CONFIG_OF */ + + kbdev->gpu_props.props.raw_props.coherency_mode = + kbdev->system_coherency; +} + +#ifdef CONFIG_MALI_FPGA_BUS_LOGGER + +/* Callback used by the kbase bus logger client, to initiate a GPU reset + * when the bus log is restarted. GPU reset is used as reference point + * in HW bus log analyses. + */ +static void kbase_logging_started_cb(void *data) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); + dev_info(kbdev->dev, "KBASE - Bus logger restarted\n"); +} +#endif + +static struct attribute *kbase_attrs[] = { +#ifdef CONFIG_MALI_DEBUG + &dev_attr_debug_command.attr, + &dev_attr_js_softstop_always.attr, +#endif +#if !MALI_CUSTOMER_RELEASE + &dev_attr_force_replay.attr, +#endif + &dev_attr_js_timeouts.attr, + &dev_attr_soft_job_timeout.attr, + &dev_attr_gpuinfo.attr, + &dev_attr_dvfs_period.attr, + &dev_attr_pm_poweroff.attr, + &dev_attr_reset_timeout.attr, + &dev_attr_js_scheduling_period.attr, + &dev_attr_power_policy.attr, + &dev_attr_core_availability_policy.attr, + &dev_attr_core_mask.attr, + &dev_attr_mem_pool_size.attr, + &dev_attr_mem_pool_max_size.attr, + &dev_attr_lp_mem_pool_size.attr, + &dev_attr_lp_mem_pool_max_size.attr, + NULL +}; + +static const struct attribute_group kbase_attr_group = { + .attrs = kbase_attrs, +}; + +static int kbase_platform_device_remove(struct platform_device *pdev) +{ + struct kbase_device *kbdev = to_kbase_device(&pdev->dev); + const struct list_head *dev_list; + + if (!kbdev) + return -ENODEV; + + kfree(kbdev->gpu_props.prop_buffer); + +#ifdef CONFIG_MALI_FPGA_BUS_LOGGER + if (kbdev->inited_subsys & inited_buslogger) { + bl_core_client_unregister(kbdev->buslogger); + kbdev->inited_subsys &= ~inited_buslogger; + } +#endif + + + if (kbdev->inited_subsys & inited_dev_list) { + dev_list = kbase_dev_list_get(); + list_del(&kbdev->entry); + kbase_dev_list_put(dev_list); + kbdev->inited_subsys &= ~inited_dev_list; + } + + if (kbdev->inited_subsys & inited_misc_register) { + misc_deregister(&kbdev->mdev); + kbdev->inited_subsys &= ~inited_misc_register; + } + + if (kbdev->inited_subsys & inited_sysfs_group) { + sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + kbdev->inited_subsys &= ~inited_sysfs_group; + } + + if (kbdev->inited_subsys & inited_get_device) { + put_device(kbdev->dev); + kbdev->inited_subsys &= ~inited_get_device; + } + + if (kbdev->inited_subsys & inited_debugfs) { + kbase_device_debugfs_term(kbdev); + kbdev->inited_subsys &= ~inited_debugfs; + } + + if (kbdev->inited_subsys & inited_job_fault) { + kbase_debug_job_fault_dev_term(kbdev); + kbdev->inited_subsys &= ~inited_job_fault; + } + if (kbdev->inited_subsys & inited_vinstr) { + kbase_vinstr_term(kbdev->vinstr_ctx); + kbdev->inited_subsys &= ~inited_vinstr; + } + +#ifdef CONFIG_MALI_DEVFREQ + if (kbdev->inited_subsys & inited_devfreq) { + kbase_devfreq_term(kbdev); + kbdev->inited_subsys &= ~inited_devfreq; + } +#endif + + if (kbdev->inited_subsys & inited_backend_late) { + kbase_backend_late_term(kbdev); + kbdev->inited_subsys &= ~inited_backend_late; + } + + if (kbdev->inited_subsys & inited_tlstream) { + kbase_tlstream_term(); + kbdev->inited_subsys &= ~inited_tlstream; + } + + /* Bring job and mem sys to a halt before we continue termination */ + + if (kbdev->inited_subsys & inited_js) + kbasep_js_devdata_halt(kbdev); + + if (kbdev->inited_subsys & inited_mem) + kbase_mem_halt(kbdev); + + if (kbdev->inited_subsys & inited_protected) { + kbasep_protected_mode_term(kbdev); + kbdev->inited_subsys &= ~inited_protected; + } + + if (kbdev->inited_subsys & inited_js) { + kbasep_js_devdata_term(kbdev); + kbdev->inited_subsys &= ~inited_js; + } + + if (kbdev->inited_subsys & inited_mem) { + kbase_mem_term(kbdev); + kbdev->inited_subsys &= ~inited_mem; + } + + if (kbdev->inited_subsys & inited_pm_runtime_init) { + kbdev->pm.callback_power_runtime_term(kbdev); + kbdev->inited_subsys &= ~inited_pm_runtime_init; + } + + if (kbdev->inited_subsys & inited_ctx_sched) { + kbase_ctx_sched_term(kbdev); + kbdev->inited_subsys &= ~inited_ctx_sched; + } + + if (kbdev->inited_subsys & inited_device) { + kbase_device_term(kbdev); + kbdev->inited_subsys &= ~inited_device; + } + + if (kbdev->inited_subsys & inited_backend_early) { + kbase_backend_early_term(kbdev); + kbdev->inited_subsys &= ~inited_backend_early; + } + + if (kbdev->inited_subsys & inited_io_history) { + kbase_io_history_term(&kbdev->io_history); + kbdev->inited_subsys &= ~inited_io_history; + } + + if (kbdev->inited_subsys & inited_power_control) { + power_control_term(kbdev); + kbdev->inited_subsys &= ~inited_power_control; + } + + if (kbdev->inited_subsys & inited_registers_map) { + registers_unmap(kbdev); + kbdev->inited_subsys &= ~inited_registers_map; + } + +#ifdef CONFIG_MALI_NO_MALI + if (kbdev->inited_subsys & inited_gpu_device) { + gpu_device_destroy(kbdev); + kbdev->inited_subsys &= ~inited_gpu_device; + } +#endif /* CONFIG_MALI_NO_MALI */ + + if (kbdev->inited_subsys != 0) + dev_err(kbdev->dev, "Missing sub system termination\n"); + + kbase_device_free(kbdev); + + return 0; +} + + +/* Number of register accesses for the buffer that we allocate during + * initialization time. The buffer size can be changed later via debugfs. */ +#define KBASEP_DEFAULT_REGISTER_HISTORY_SIZE ((u16)512) + +static int kbase_platform_device_probe(struct platform_device *pdev) +{ + struct kbase_device *kbdev; + struct mali_base_gpu_core_props *core_props; + u32 gpu_id; + unsigned prod_id; + const struct list_head *dev_list; + int err = 0; + +#ifdef CONFIG_OF + err = kbase_platform_early_init(); + if (err) { + dev_err(&pdev->dev, "Early platform initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } +#endif + kbdev = kbase_device_alloc(); + if (!kbdev) { + dev_err(&pdev->dev, "Allocate device failed\n"); + kbase_platform_device_remove(pdev); + return -ENOMEM; + } + + kbdev->dev = &pdev->dev; + dev_set_drvdata(kbdev->dev, kbdev); + +#ifdef CONFIG_MALI_NO_MALI + err = gpu_device_create(kbdev); + if (err) { + dev_err(&pdev->dev, "Dummy model initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_gpu_device; +#endif /* CONFIG_MALI_NO_MALI */ + + err = assign_irqs(pdev); + if (err) { + dev_err(&pdev->dev, "IRQ search failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + + err = registers_map(kbdev); + if (err) { + dev_err(&pdev->dev, "Register map failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_registers_map; + + err = power_control_init(pdev); + if (err) { + dev_err(&pdev->dev, "Power control initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_power_control; + + err = kbase_io_history_init(&kbdev->io_history, + KBASEP_DEFAULT_REGISTER_HISTORY_SIZE); + if (err) { + dev_err(&pdev->dev, "Register access history initialization failed\n"); + kbase_platform_device_remove(pdev); + return -ENOMEM; + } + kbdev->inited_subsys |= inited_io_history; + + err = kbase_backend_early_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Early backend initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_backend_early; + + scnprintf(kbdev->devname, DEVNAME_SIZE, "%s%d", kbase_drv_name, + kbase_dev_nr); + + kbase_disjoint_init(kbdev); + + /* obtain min/max configured gpu frequencies */ + core_props = &(kbdev->gpu_props.props.core_props); + core_props->gpu_freq_khz_min = GPU_FREQ_KHZ_MIN; + core_props->gpu_freq_khz_max = GPU_FREQ_KHZ_MAX; + + err = kbase_device_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Device initialization failed (%d)\n", err); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_device; + + err = kbase_ctx_sched_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Context scheduler initialization failed (%d)\n", + err); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_ctx_sched; + + if (kbdev->pm.callback_power_runtime_init) { + err = kbdev->pm.callback_power_runtime_init(kbdev); + if (err) { + dev_err(kbdev->dev, + "Runtime PM initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_pm_runtime_init; + } + + err = kbase_mem_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Memory subsystem initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_mem; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + gpu_id &= GPU_ID_VERSION_PRODUCT_ID; + prod_id = gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + kbase_device_coherency_init(kbdev, prod_id); + + err = kbasep_protected_mode_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Protected mode subsystem initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_protected; + + dev_list = kbase_dev_list_get(); + list_add(&kbdev->entry, &kbase_dev_list); + kbase_dev_list_put(dev_list); + kbdev->inited_subsys |= inited_dev_list; + + err = kbasep_js_devdata_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Job JS devdata initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_js; + + err = kbase_tlstream_init(); + if (err) { + dev_err(kbdev->dev, "Timeline stream initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_tlstream; + + err = kbase_backend_late_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Late backend initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_backend_late; + + /* Initialize the kctx list. This is used by vinstr. */ + mutex_init(&kbdev->kctx_list_lock); + INIT_LIST_HEAD(&kbdev->kctx_list); + + kbdev->vinstr_ctx = kbase_vinstr_init(kbdev); + if (!kbdev->vinstr_ctx) { + dev_err(kbdev->dev, + "Virtual instrumentation initialization failed\n"); + kbase_platform_device_remove(pdev); + return -EINVAL; + } + kbdev->inited_subsys |= inited_vinstr; + +#ifdef CONFIG_MALI_DEVFREQ + /* Devfreq uses vinstr, so must be initialized after it. */ + err = kbase_devfreq_init(kbdev); + if (!err) + kbdev->inited_subsys |= inited_devfreq; + else + dev_err(kbdev->dev, "Continuing without devfreq\n"); +#endif /* CONFIG_MALI_DEVFREQ */ + + err = kbase_debug_job_fault_dev_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Job fault debug initialization failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_job_fault; + + err = kbase_device_debugfs_init(kbdev); + if (err) { + dev_err(kbdev->dev, "DebugFS initialization failed"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_debugfs; + + kbdev->mdev.minor = MISC_DYNAMIC_MINOR; + kbdev->mdev.name = kbdev->devname; + kbdev->mdev.fops = &kbase_fops; + kbdev->mdev.parent = get_device(kbdev->dev); + kbdev->inited_subsys |= inited_get_device; + + /* This needs to happen before registering the device with misc_register(), + * otherwise it causes a race condition between registering the device and a + * uevent event being generated for userspace, causing udev rules to run + * which might expect certain sysfs attributes present. As a result of the + * race condition we avoid, some Mali sysfs entries may have appeared to + * udev to not exist. + + * For more information, see + * https://www.kernel.org/doc/Documentation/driver-model/device.txt, the + * paragraph that starts with "Word of warning", currently the second-last + * paragraph. + */ + err = sysfs_create_group(&kbdev->dev->kobj, &kbase_attr_group); + if (err) { + dev_err(&pdev->dev, "SysFS group creation failed\n"); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_sysfs_group; + + err = misc_register(&kbdev->mdev); + if (err) { + dev_err(kbdev->dev, "Misc device registration failed for %s\n", + kbdev->devname); + kbase_platform_device_remove(pdev); + return err; + } + kbdev->inited_subsys |= inited_misc_register; + + +#ifdef CONFIG_MALI_FPGA_BUS_LOGGER + err = bl_core_client_register(kbdev->devname, + kbase_logging_started_cb, + kbdev, &kbdev->buslogger, + THIS_MODULE, NULL); + if (err == 0) { + kbdev->inited_subsys |= inited_buslogger; + bl_core_set_threshold(kbdev->buslogger, 1024*1024*1024); + } else { + dev_warn(kbdev->dev, "Bus log client registration failed\n"); + err = 0; + } +#endif + + err = kbase_gpuprops_populate_user_buffer(kbdev); + if (err) { + dev_err(&pdev->dev, "GPU property population failed"); + kbase_platform_device_remove(pdev); + return err; + } + + dev_info(kbdev->dev, + "Probed as %s\n", dev_name(kbdev->mdev.this_device)); + + kbase_dev_nr++; + + return err; +} + +#undef KBASEP_DEFAULT_REGISTER_HISTORY_SIZE + +/** + * kbase_device_suspend - Suspend callback from the OS. + * + * This is called by Linux when the device should suspend. + * + * @dev: The device to suspend + * + * Return: A standard Linux error code + */ +static int kbase_device_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_MALI_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (kbdev->inited_subsys & inited_devfreq) + devfreq_suspend_device(kbdev->devfreq); +#endif + + kbase_pm_suspend(kbdev); + return 0; +} + +/** + * kbase_device_resume - Resume callback from the OS. + * + * This is called by Linux when the device should resume from suspension. + * + * @dev: The device to resume + * + * Return: A standard Linux error code + */ +static int kbase_device_resume(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + kbase_pm_resume(kbdev); + +#if defined(CONFIG_MALI_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (kbdev->inited_subsys & inited_devfreq) + devfreq_resume_device(kbdev->devfreq); +#endif + return 0; +} + +/** + * kbase_device_runtime_suspend - Runtime suspend callback from the OS. + * + * This is called by Linux when the device should prepare for a condition in + * which it will not be able to communicate with the CPU(s) and RAM due to + * power management. + * + * @dev: The device to suspend + * + * Return: A standard Linux error code + */ +#ifdef KBASE_PM_RUNTIME +static int kbase_device_runtime_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_MALI_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (kbdev->inited_subsys & inited_devfreq) + devfreq_suspend_device(kbdev->devfreq); +#endif + + if (kbdev->pm.backend.callback_power_runtime_off) { + kbdev->pm.backend.callback_power_runtime_off(kbdev); + dev_dbg(dev, "runtime suspend\n"); + } + return 0; +} +#endif /* KBASE_PM_RUNTIME */ + +/** + * kbase_device_runtime_resume - Runtime resume callback from the OS. + * + * This is called by Linux when the device should go into a fully active state. + * + * @dev: The device to suspend + * + * Return: A standard Linux error code + */ + +#ifdef KBASE_PM_RUNTIME +static int kbase_device_runtime_resume(struct device *dev) +{ + int ret = 0; + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + if (kbdev->pm.backend.callback_power_runtime_on) { + ret = kbdev->pm.backend.callback_power_runtime_on(kbdev); + dev_dbg(dev, "runtime resume\n"); + } + +#if defined(CONFIG_MALI_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (kbdev->inited_subsys & inited_devfreq) + devfreq_resume_device(kbdev->devfreq); +#endif + + return ret; +} +#endif /* KBASE_PM_RUNTIME */ + + +#ifdef KBASE_PM_RUNTIME +/** + * kbase_device_runtime_idle - Runtime idle callback from the OS. + * @dev: The device to suspend + * + * This is called by Linux when the device appears to be inactive and it might + * be placed into a low power state. + * + * Return: 0 if device can be suspended, non-zero to avoid runtime autosuspend, + * otherwise a standard Linux error code + */ +static int kbase_device_runtime_idle(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + /* Use platform specific implementation if it exists. */ + if (kbdev->pm.backend.callback_power_runtime_idle) + return kbdev->pm.backend.callback_power_runtime_idle(kbdev); + + return 0; +} +#endif /* KBASE_PM_RUNTIME */ + +/* The power management operations for the platform driver. + */ +static const struct dev_pm_ops kbase_pm_ops = { + .suspend = kbase_device_suspend, + .resume = kbase_device_resume, +#ifdef KBASE_PM_RUNTIME + .runtime_suspend = kbase_device_runtime_suspend, + .runtime_resume = kbase_device_runtime_resume, + .runtime_idle = kbase_device_runtime_idle, +#endif /* KBASE_PM_RUNTIME */ +}; + +#ifdef CONFIG_OF +static const struct of_device_id kbase_dt_ids[] = { + { .compatible = "arm,malit6xx" }, + { .compatible = "arm,mali-midgard" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, kbase_dt_ids); +#endif + +static struct platform_driver kbase_platform_driver = { + .probe = kbase_platform_device_probe, + .remove = kbase_platform_device_remove, + .driver = { + .name = kbase_drv_name, + .owner = THIS_MODULE, + .pm = &kbase_pm_ops, + .of_match_table = of_match_ptr(kbase_dt_ids), + }, +}; + +/* + * The driver will not provide a shortcut to create the Mali platform device + * anymore when using Device Tree. + */ +#ifdef CONFIG_OF +module_platform_driver(kbase_platform_driver); +#else + +static int __init kbase_driver_init(void) +{ + int ret; + + ret = kbase_platform_early_init(); + if (ret) + return ret; + + ret = kbase_platform_register(); + if (ret) + return ret; + + ret = platform_driver_register(&kbase_platform_driver); + + if (ret) + kbase_platform_unregister(); + + return ret; +} + +static void __exit kbase_driver_exit(void) +{ + platform_driver_unregister(&kbase_platform_driver); + kbase_platform_unregister(); +} + +module_init(kbase_driver_init); +module_exit(kbase_driver_exit); + +#endif /* CONFIG_OF */ + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MALI_RELEASE_NAME " (UK version " \ + __stringify(BASE_UK_VERSION_MAJOR) "." \ + __stringify(BASE_UK_VERSION_MINOR) ")"); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) || defined(CONFIG_MALI_SYSTEM_TRACE) +#define CREATE_TRACE_POINTS +#endif + +#ifdef CONFIG_MALI_GATOR_SUPPORT +/* Create the trace points (otherwise we just get code to call a tracepoint) */ +#include "mali_linux_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_job_slots_event); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_pm_status); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_pm_power_on); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_pm_power_off); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_page_fault_insert_pages); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_mmu_as_in_use); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_mmu_as_released); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_total_alloc_pages_change); + +void kbase_trace_mali_pm_status(u32 event, u64 value) +{ + trace_mali_pm_status(event, value); +} + +void kbase_trace_mali_pm_power_off(u32 event, u64 value) +{ + trace_mali_pm_power_off(event, value); +} + +void kbase_trace_mali_pm_power_on(u32 event, u64 value) +{ + trace_mali_pm_power_on(event, value); +} + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id) +{ + trace_mali_job_slots_event(event, (kctx != NULL ? kctx->tgid : 0), (kctx != NULL ? kctx->pid : 0), atom_id); +} + +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value) +{ + trace_mali_page_fault_insert_pages(event, value); +} + +void kbase_trace_mali_mmu_as_in_use(int event) +{ + trace_mali_mmu_as_in_use(event); +} + +void kbase_trace_mali_mmu_as_released(int event) +{ + trace_mali_mmu_as_released(event); +} + +void kbase_trace_mali_total_alloc_pages_change(long long int event) +{ + trace_mali_total_alloc_pages_change(event); +} +#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#ifdef CONFIG_MALI_SYSTEM_TRACE +#include "mali_linux_kbase_trace.h" +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c new file mode 100644 index 000000000000..e2f7baabad43 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c @@ -0,0 +1,203 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include "mali_kbase_ctx_sched.h" + +int kbase_ctx_sched_init(struct kbase_device *kbdev) +{ + int as_present = (1U << kbdev->nr_hw_address_spaces) - 1; + + /* These two must be recalculated if nr_hw_address_spaces changes + * (e.g. for HW workarounds) */ + kbdev->nr_user_address_spaces = kbdev->nr_hw_address_spaces; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + bool use_workaround; + + use_workaround = DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE; + if (use_workaround) { + dev_dbg(kbdev->dev, "GPU has HW ISSUE 8987, and driver configured for security workaround: 1 address space only"); + kbdev->nr_user_address_spaces = 1; + } + } + + kbdev->as_free = as_present; /* All ASs initially free */ + + memset(kbdev->as_to_kctx, 0, sizeof(kbdev->as_to_kctx)); + + return 0; +} + +void kbase_ctx_sched_term(struct kbase_device *kbdev) +{ + s8 i; + + /* Sanity checks */ + for (i = 0; i != kbdev->nr_hw_address_spaces; ++i) { + WARN_ON(kbdev->as_to_kctx[i] != NULL); + WARN_ON(!(kbdev->as_free & (1u << i))); + } +} + +/* kbasep_ctx_sched_find_as_for_ctx - Find a free address space + * + * @kbdev: The context for which to find a free address space + * + * Return: A valid AS if successful, otherwise KBASEP_AS_NR_INVALID + * + * This function returns an address space available for use. It would prefer + * returning an AS that has been previously assigned to the context to + * avoid having to reprogram the MMU. + */ +static int kbasep_ctx_sched_find_as_for_ctx(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + int free_as; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* First check if the previously assigned AS is available */ + if ((kctx->as_nr != KBASEP_AS_NR_INVALID) && + (kbdev->as_free & (1u << kctx->as_nr))) + return kctx->as_nr; + + /* The previously assigned AS was taken, we'll be returning any free + * AS at this point. + */ + free_as = ffs(kbdev->as_free) - 1; + if (free_as >= 0 && free_as < kbdev->nr_hw_address_spaces) + return free_as; + + return KBASEP_AS_NR_INVALID; +} + +int kbase_ctx_sched_retain_ctx(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ON(!kbdev->pm.backend.gpu_powered); + + if (atomic_inc_return(&kctx->refcount) == 1) { + int const free_as = kbasep_ctx_sched_find_as_for_ctx(kctx); + + if (free_as != KBASEP_AS_NR_INVALID) { + kbdev->as_free &= ~(1u << free_as); + /* Only program the MMU if the context has not been + * assigned the same address space before. + */ + if (free_as != kctx->as_nr) { + struct kbase_context *const prev_kctx = + kbdev->as_to_kctx[free_as]; + + if (prev_kctx) { + WARN_ON(atomic_read(&prev_kctx->refcount) != 0); + kbase_mmu_disable(prev_kctx); + prev_kctx->as_nr = KBASEP_AS_NR_INVALID; + } + + kctx->as_nr = free_as; + kbdev->as_to_kctx[free_as] = kctx; + kbase_mmu_update(kctx); + } + } else { + atomic_dec(&kctx->refcount); + + /* Failed to find an available address space, we must + * be returning an error at this point. + */ + WARN_ON(kctx->as_nr != KBASEP_AS_NR_INVALID); + } + } + + return kctx->as_nr; +} + +void kbase_ctx_sched_retain_ctx_refcount(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + + lockdep_assert_held(&kbdev->hwaccess_lock); + WARN_ON(atomic_read(&kctx->refcount) == 0); + WARN_ON(kctx->as_nr == KBASEP_AS_NR_INVALID); + WARN_ON(kbdev->as_to_kctx[kctx->as_nr] != kctx); + + atomic_inc(&kctx->refcount); +} + +void kbase_ctx_sched_release_ctx(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (atomic_dec_return(&kctx->refcount) == 0) + kbdev->as_free |= (1u << kctx->as_nr); +} + +void kbase_ctx_sched_remove_ctx(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ON(atomic_read(&kctx->refcount) != 0); + + if (kctx->as_nr != KBASEP_AS_NR_INVALID) { + if (kbdev->pm.backend.gpu_powered) + kbase_mmu_disable(kctx); + + kbdev->as_to_kctx[kctx->as_nr] = NULL; + kctx->as_nr = KBASEP_AS_NR_INVALID; + } +} + +void kbase_ctx_sched_restore_all_as(struct kbase_device *kbdev) +{ + s8 i; + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ON(!kbdev->pm.backend.gpu_powered); + + for (i = 0; i != kbdev->nr_hw_address_spaces; ++i) { + struct kbase_context *kctx; + + kctx = kbdev->as_to_kctx[i]; + if (kctx) { + if (atomic_read(&kctx->refcount)) { + WARN_ON(kctx->as_nr != i); + + kbase_mmu_update(kctx); + } else { + /* This context might have been assigned an + * AS before, clear it. + */ + kbdev->as_to_kctx[kctx->as_nr] = NULL; + kctx->as_nr = KBASEP_AS_NR_INVALID; + } + } else { + kbase_mmu_disable_as(kbdev, i); + } + } +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.h b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.h new file mode 100644 index 000000000000..2330d48c8e51 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.h @@ -0,0 +1,131 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_CTX_SCHED_H_ +#define _KBASE_CTX_SCHED_H_ + +#include + +/* The Context Scheduler manages address space assignment and reference + * counting to kbase_context. The interface has been designed to minimise + * interactions between the Job Scheduler and Power Management/MMU to support + * the existing Job Scheduler interface. + * + * The initial implementation of the Context Scheduler does not schedule + * contexts. Instead it relies on the Job Scheduler to make decisions of + * when to schedule/evict contexts if address spaces are starved. In the + * future, once an interface between the CS and JS have been devised to + * provide enough information about how each context is consuming GPU resources, + * those decisions can be made in the CS itself, thereby reducing duplicated + * code. + */ + +/* base_ctx_sched_init - Initialise the context scheduler + * + * @kbdev: The device for which the context scheduler needs to be + * initialised + * + * Return: 0 for success, otherwise failure + * + * This must be called during device initilisation. The number of hardware + * address spaces must already be established before calling this function. + */ +int kbase_ctx_sched_init(struct kbase_device *kbdev); + +/* base_ctx_sched_term - Terminate the context scheduler + * + * @kbdev: The device for which the context scheduler needs to be + * terminated + * + * This must be called during device termination after all contexts have been + * destroyed. + */ +void kbase_ctx_sched_term(struct kbase_device *kbdev); + +/* kbase_ctx_sched_retain_ctx - Retain a reference to the @ref kbase_context + * + * @kctx: The context to which to retain a reference + * + * Return: The address space that the context has been assigned to or + * KBASEP_AS_NR_INVALID if no address space was available. + * + * This function should be called whenever an address space should be assigned + * to a context and programmed onto the MMU. It should typically be called + * when jobs are ready to be submitted to the GPU. + * + * It can be called as many times as necessary. The address space will be + * assigned to the context for as long as there is a reference to said context. + * + * The kbase_device::mmu_hw_mutex and kbase_device::hwaccess_lock locks must be + * held whilst calling this function. + */ +int kbase_ctx_sched_retain_ctx(struct kbase_context *kctx); + +/* kbase_ctx_sched_retain_ctx_refcount + * + * @kctx: The context to which to retain a reference + * + * This function only retains a reference to the context. It must be called + * only when the context already has a reference. + * + * This is typically called inside an atomic session where we know the context + * is already scheduled in but want to take an extra reference to ensure that + * it doesn't get descheduled. + * + * The kbase_device::hwaccess_lock must be held whilst calling this function + */ +void kbase_ctx_sched_retain_ctx_refcount(struct kbase_context *kctx); + +/* kbase_ctx_sched_release_ctx - Release a reference to the @ref kbase_context + * + * @kctx: The context from which to release a reference + * + * This function should be called whenever an address space could be unassigned + * from a context. When there are no more references to said context, the + * address space previously assigned to this context shall be reassigned to + * other contexts as needed. + * + * The kbase_device::hwaccess_lock must be held whilst calling this function + */ +void kbase_ctx_sched_release_ctx(struct kbase_context *kctx); + +/* kbase_ctx_sched_remove_ctx - Unassign previously assigned address space + * + * @kctx: The context to be removed + * + * This function should be called when a context is being destroyed. The + * context must no longer have any reference. If it has been assigned an + * address space before then the AS will be unprogrammed. + * + * The kbase_device::mmu_hw_mutex and kbase_device::hwaccess_lock locks must be + * held whilst calling this function. + */ +void kbase_ctx_sched_remove_ctx(struct kbase_context *kctx); + +/* kbase_ctx_sched_restore_all_as - Reprogram all address spaces + * + * @kbdev: The device for which address spaces to be reprogrammed + * + * This function shall reprogram all address spaces previously assigned to + * contexts. It can be used after the GPU is reset. + * + * The kbase_device::mmu_hw_mutex and kbase_device::hwaccess_lock locks must be + * held whilst calling this function. + */ +void kbase_ctx_sched_restore_all_as(struct kbase_device *kbdev); + +#endif /* _KBASE_CTX_SCHED_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug.c b/drivers/gpu/arm/bifrost/mali_kbase_debug.c new file mode 100644 index 000000000000..fb57ac2e31ad --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug.c @@ -0,0 +1,39 @@ +/* + * + * (C) COPYRIGHT 2012-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +static struct kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = { + NULL, + NULL +}; + +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param) +{ + kbasep_debug_assert_registered_cb.func = func; + kbasep_debug_assert_registered_cb.param = param; +} + +void kbasep_debug_assert_call_hook(void) +{ + if (kbasep_debug_assert_registered_cb.func != NULL) + kbasep_debug_assert_registered_cb.func(kbasep_debug_assert_registered_cb.param); +} +KBASE_EXPORT_SYMBOL(kbasep_debug_assert_call_hook); + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug.h b/drivers/gpu/arm/bifrost/mali_kbase_debug.h new file mode 100644 index 000000000000..d7873c5eabf9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug.h @@ -0,0 +1,164 @@ +/* + * + * (C) COPYRIGHT 2012-2015, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_DEBUG_H +#define _KBASE_DEBUG_H + +#include + +/** @brief If equals to 0, a trace containing the file, line, and function will be displayed before each message. */ +#define KBASE_DEBUG_SKIP_TRACE 0 + +/** @brief If different from 0, the trace will only contain the file and line. */ +#define KBASE_DEBUG_SKIP_FUNCTION_NAME 0 + +/** @brief Disable the asserts tests if set to 1. Default is to disable the asserts in release. */ +#ifndef KBASE_DEBUG_DISABLE_ASSERTS +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_DISABLE_ASSERTS 0 +#else +#define KBASE_DEBUG_DISABLE_ASSERTS 1 +#endif +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** Function type that is called on an KBASE_DEBUG_ASSERT() or KBASE_DEBUG_ASSERT_MSG() */ +typedef void (kbase_debug_assert_hook) (void *); + +struct kbasep_debug_assert_cb { + kbase_debug_assert_hook *func; + void *param; +}; + +/** + * @def KBASEP_DEBUG_PRINT_TRACE + * @brief Private macro containing the format of the trace to display before every message + * @sa KBASE_DEBUG_SKIP_TRACE, KBASE_DEBUG_SKIP_FUNCTION_NAME + */ +#if !KBASE_DEBUG_SKIP_TRACE +#define KBASEP_DEBUG_PRINT_TRACE \ + "In file: " __FILE__ " line: " CSTD_STR2(__LINE__) +#if !KBASE_DEBUG_SKIP_FUNCTION_NAME +#define KBASEP_DEBUG_PRINT_FUNCTION __func__ +#else +#define KBASEP_DEBUG_PRINT_FUNCTION "" +#endif +#else +#define KBASEP_DEBUG_PRINT_TRACE "" +#endif + +/** + * @def KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) + * @brief (Private) system printing function associated to the @ref KBASE_DEBUG_ASSERT_MSG event. + * @param trace location in the code from where the message is printed + * @param function function from where the message is printed + * @param ... Format string followed by format arguments. + * @note function parameter cannot be concatenated with other strings + */ +/* Select the correct system output function*/ +#ifdef CONFIG_MALI_DEBUG +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)\ + do { \ + pr_err("Mali: %s function:%s ", trace, function);\ + pr_err(__VA_ARGS__);\ + pr_err("\n");\ + } while (false) +#else +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP() +#endif + +#ifdef CONFIG_MALI_DEBUG +#define KBASE_CALL_ASSERT_HOOK() kbasep_debug_assert_call_hook() +#else +#define KBASE_CALL_ASSERT_HOOK() CSTD_NOP() +#endif + +/** + * @def KBASE_DEBUG_ASSERT(expr) + * @brief Calls @ref KBASE_PRINT_ASSERT and prints the expression @a expr if @a expr is false + * + * @note This macro does nothing if the flag @ref KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + */ +#define KBASE_DEBUG_ASSERT(expr) \ + KBASE_DEBUG_ASSERT_MSG(expr, #expr) + +#if KBASE_DEBUG_DISABLE_ASSERTS +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) CSTD_NOP() +#else + /** + * @def KBASE_DEBUG_ASSERT_MSG(expr, ...) + * @brief Calls @ref KBASEP_DEBUG_ASSERT_OUT and prints the given message if @a expr is false + * + * @note This macro does nothing if the flag @ref KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + * @param ... Message to display when @a expr is false, as a format string followed by format arguments. + */ +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) \ + do { \ + if (!(expr)) { \ + KBASEP_DEBUG_ASSERT_OUT(KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION, __VA_ARGS__);\ + KBASE_CALL_ASSERT_HOOK();\ + BUG();\ + } \ + } while (false) +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** + * @def KBASE_DEBUG_CODE( X ) + * @brief Executes the code inside the macro only in debug mode + * + * @param X Code to compile only in debug mode. + */ +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_CODE(X) X +#else +#define KBASE_DEBUG_CODE(X) CSTD_NOP() +#endif /* CONFIG_MALI_DEBUG */ + +/** @} */ + +/** + * @brief Register a function to call on ASSERT + * + * Such functions will \b only be called during Debug mode, and for debugging + * features \b only. Do not rely on them to be called in general use. + * + * To disable the hook, supply NULL to \a func. + * + * @note This function is not thread-safe, and should only be used to + * register/deregister once in the module's lifetime. + * + * @param[in] func the function to call when an assert is triggered. + * @param[in] param the parameter to pass to \a func when calling it + */ +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param); + +/** + * @brief Call a debug assert hook previously registered with kbase_debug_assert_register_hook() + * + * @note This function is not thread-safe with respect to multiple threads + * registering functions and parameters with + * kbase_debug_assert_register_hook(). Otherwise, thread safety is the + * responsibility of the registered hook. + */ +void kbasep_debug_assert_call_hook(void); + +#endif /* _KBASE_DEBUG_H */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c new file mode 100644 index 000000000000..f29430ddf8f9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c @@ -0,0 +1,499 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include + +#ifdef CONFIG_DEBUG_FS + +static bool kbase_is_job_fault_event_pending(struct kbase_device *kbdev) +{ + struct list_head *event_list = &kbdev->job_fault_event_list; + unsigned long flags; + bool ret; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + ret = !list_empty(event_list); + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + + return ret; +} + +static bool kbase_ctx_has_no_event_pending(struct kbase_context *kctx) +{ + struct kbase_device *kbdev = kctx->kbdev; + struct list_head *event_list = &kctx->kbdev->job_fault_event_list; + struct base_job_fault_event *event; + unsigned long flags; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + if (list_empty(event_list)) { + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + return true; + } + list_for_each_entry(event, event_list, head) { + if (event->katom->kctx == kctx) { + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, + flags); + return false; + } + } + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + return true; +} + +/* wait until the fault happen and copy the event */ +static int kbase_job_fault_event_wait(struct kbase_device *kbdev, + struct base_job_fault_event *event) +{ + struct list_head *event_list = &kbdev->job_fault_event_list; + struct base_job_fault_event *event_in; + unsigned long flags; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + if (list_empty(event_list)) { + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + if (wait_event_interruptible(kbdev->job_fault_wq, + kbase_is_job_fault_event_pending(kbdev))) + return -ERESTARTSYS; + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + } + + event_in = list_entry(event_list->next, + struct base_job_fault_event, head); + event->event_code = event_in->event_code; + event->katom = event_in->katom; + + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + + return 0; + +} + +/* remove the event from the queue */ +static struct base_job_fault_event *kbase_job_fault_event_dequeue( + struct kbase_device *kbdev, struct list_head *event_list) +{ + struct base_job_fault_event *event; + + event = list_entry(event_list->next, + struct base_job_fault_event, head); + list_del(event_list->next); + + return event; + +} + +/* Remove all the following atoms after the failed atom in the same context + * Call the postponed bottom half of job done. + * Then, this context could be rescheduled. + */ +static void kbase_job_fault_resume_event_cleanup(struct kbase_context *kctx) +{ + struct list_head *event_list = &kctx->job_fault_resume_event_list; + + while (!list_empty(event_list)) { + struct base_job_fault_event *event; + + event = kbase_job_fault_event_dequeue(kctx->kbdev, + &kctx->job_fault_resume_event_list); + kbase_jd_done_worker(&event->katom->work); + } + +} + +/* Remove all the failed atoms that belong to different contexts + * Resume all the contexts that were suspend due to failed job + */ +static void kbase_job_fault_event_cleanup(struct kbase_device *kbdev) +{ + struct list_head *event_list = &kbdev->job_fault_event_list; + unsigned long flags; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + while (!list_empty(event_list)) { + kbase_job_fault_event_dequeue(kbdev, event_list); + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + wake_up(&kbdev->job_fault_resume_wq); + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + } + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); +} + +static void kbase_job_fault_resume_worker(struct work_struct *data) +{ + struct base_job_fault_event *event = container_of(data, + struct base_job_fault_event, job_fault_work); + struct kbase_context *kctx; + struct kbase_jd_atom *katom; + + katom = event->katom; + kctx = katom->kctx; + + dev_info(kctx->kbdev->dev, "Job dumping wait\n"); + + /* When it was waked up, it need to check if queue is empty or the + * failed atom belongs to different context. If yes, wake up. Both + * of them mean the failed job has been dumped. Please note, it + * should never happen that the job_fault_event_list has the two + * atoms belong to the same context. + */ + wait_event(kctx->kbdev->job_fault_resume_wq, + kbase_ctx_has_no_event_pending(kctx)); + + atomic_set(&kctx->job_fault_count, 0); + kbase_jd_done_worker(&katom->work); + + /* In case the following atoms were scheduled during failed job dump + * the job_done_worker was held. We need to rerun it after the dump + * was finished + */ + kbase_job_fault_resume_event_cleanup(kctx); + + dev_info(kctx->kbdev->dev, "Job dumping finish, resume scheduler\n"); +} + +static struct base_job_fault_event *kbase_job_fault_event_queue( + struct list_head *event_list, + struct kbase_jd_atom *atom, + u32 completion_code) +{ + struct base_job_fault_event *event; + + event = &atom->fault_event; + + event->katom = atom; + event->event_code = completion_code; + + list_add_tail(&event->head, event_list); + + return event; + +} + +static void kbase_job_fault_event_post(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, u32 completion_code) +{ + struct base_job_fault_event *event; + unsigned long flags; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + event = kbase_job_fault_event_queue(&kbdev->job_fault_event_list, + katom, completion_code); + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + + wake_up_interruptible(&kbdev->job_fault_wq); + + INIT_WORK(&event->job_fault_work, kbase_job_fault_resume_worker); + queue_work(kbdev->job_fault_resume_workq, &event->job_fault_work); + + dev_info(katom->kctx->kbdev->dev, "Job fault happen, start dump: %d_%d", + katom->kctx->tgid, katom->kctx->id); + +} + +/* + * This function will process the job fault + * Get the register copy + * Send the failed job dump event + * Create a Wait queue to wait until the job dump finish + */ + +bool kbase_debug_job_fault_process(struct kbase_jd_atom *katom, + u32 completion_code) +{ + struct kbase_context *kctx = katom->kctx; + + /* Check if dumping is in the process + * only one atom of each context can be dumped at the same time + * If the atom belongs to different context, it can be dumped + */ + if (atomic_read(&kctx->job_fault_count) > 0) { + kbase_job_fault_event_queue( + &kctx->job_fault_resume_event_list, + katom, completion_code); + dev_info(kctx->kbdev->dev, "queue:%d\n", + kbase_jd_atom_id(kctx, katom)); + return true; + } + + if (kctx->kbdev->job_fault_debug == true) { + + if (completion_code != BASE_JD_EVENT_DONE) { + + if (kbase_job_fault_get_reg_snapshot(kctx) == false) { + dev_warn(kctx->kbdev->dev, "get reg dump failed\n"); + return false; + } + + kbase_job_fault_event_post(kctx->kbdev, katom, + completion_code); + atomic_inc(&kctx->job_fault_count); + dev_info(kctx->kbdev->dev, "post:%d\n", + kbase_jd_atom_id(kctx, katom)); + return true; + + } + } + return false; + +} + +static int debug_job_fault_show(struct seq_file *m, void *v) +{ + struct kbase_device *kbdev = m->private; + struct base_job_fault_event *event = (struct base_job_fault_event *)v; + struct kbase_context *kctx = event->katom->kctx; + int i; + + dev_info(kbdev->dev, "debug job fault seq show:%d_%d, %d", + kctx->tgid, kctx->id, event->reg_offset); + + if (kctx->reg_dump == NULL) { + dev_warn(kbdev->dev, "reg dump is NULL"); + return -1; + } + + if (kctx->reg_dump[event->reg_offset] == + REGISTER_DUMP_TERMINATION_FLAG) { + /* Return the error here to stop the read. And the + * following next() will not be called. The stop can + * get the real event resource and release it + */ + return -1; + } + + if (event->reg_offset == 0) + seq_printf(m, "%d_%d\n", kctx->tgid, kctx->id); + + for (i = 0; i < 50; i++) { + if (kctx->reg_dump[event->reg_offset] == + REGISTER_DUMP_TERMINATION_FLAG) { + break; + } + seq_printf(m, "%08x: %08x\n", + kctx->reg_dump[event->reg_offset], + kctx->reg_dump[1+event->reg_offset]); + event->reg_offset += 2; + + } + + + return 0; +} +static void *debug_job_fault_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct kbase_device *kbdev = m->private; + struct base_job_fault_event *event = (struct base_job_fault_event *)v; + + dev_info(kbdev->dev, "debug job fault seq next:%d, %d", + event->reg_offset, (int)*pos); + + return event; +} + +static void *debug_job_fault_start(struct seq_file *m, loff_t *pos) +{ + struct kbase_device *kbdev = m->private; + struct base_job_fault_event *event; + + dev_info(kbdev->dev, "fault job seq start:%d", (int)*pos); + + /* The condition is trick here. It needs make sure the + * fault hasn't happened and the dumping hasn't been started, + * or the dumping has finished + */ + if (*pos == 0) { + event = kmalloc(sizeof(*event), GFP_KERNEL); + if (!event) + return NULL; + event->reg_offset = 0; + if (kbase_job_fault_event_wait(kbdev, event)) { + kfree(event); + return NULL; + } + + /* The cache flush workaround is called in bottom half of + * job done but we delayed it. Now we should clean cache + * earlier. Then the GPU memory dump should be correct. + */ + kbase_backend_cacheclean(kbdev, event->katom); + } else + return NULL; + + return event; +} + +static void debug_job_fault_stop(struct seq_file *m, void *v) +{ + struct kbase_device *kbdev = m->private; + + /* here we wake up the kbase_jd_done_worker after stop, it needs + * get the memory dump before the register dump in debug daemon, + * otherwise, the memory dump may be incorrect. + */ + + if (v != NULL) { + kfree(v); + dev_info(kbdev->dev, "debug job fault seq stop stage 1"); + + } else { + unsigned long flags; + + spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); + if (!list_empty(&kbdev->job_fault_event_list)) { + kbase_job_fault_event_dequeue(kbdev, + &kbdev->job_fault_event_list); + wake_up(&kbdev->job_fault_resume_wq); + } + spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); + dev_info(kbdev->dev, "debug job fault seq stop stage 2"); + } + +} + +static const struct seq_operations ops = { + .start = debug_job_fault_start, + .next = debug_job_fault_next, + .stop = debug_job_fault_stop, + .show = debug_job_fault_show, +}; + +static int debug_job_fault_open(struct inode *in, struct file *file) +{ + struct kbase_device *kbdev = in->i_private; + + seq_open(file, &ops); + + ((struct seq_file *)file->private_data)->private = kbdev; + dev_info(kbdev->dev, "debug job fault seq open"); + + kbdev->job_fault_debug = true; + + return 0; + +} + +static int debug_job_fault_release(struct inode *in, struct file *file) +{ + struct kbase_device *kbdev = in->i_private; + + seq_release(in, file); + + kbdev->job_fault_debug = false; + + /* Clean the unprocessed job fault. After that, all the suspended + * contexts could be rescheduled. + */ + kbase_job_fault_event_cleanup(kbdev); + + dev_info(kbdev->dev, "debug job fault seq close"); + + return 0; +} + +static const struct file_operations kbasep_debug_job_fault_fops = { + .open = debug_job_fault_open, + .read = seq_read, + .llseek = seq_lseek, + .release = debug_job_fault_release, +}; + +/* + * Initialize debugfs entry for job fault dump + */ +void kbase_debug_job_fault_debugfs_init(struct kbase_device *kbdev) +{ + debugfs_create_file("job_fault", S_IRUGO, + kbdev->mali_debugfs_directory, kbdev, + &kbasep_debug_job_fault_fops); +} + + +int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev) +{ + + INIT_LIST_HEAD(&kbdev->job_fault_event_list); + + init_waitqueue_head(&(kbdev->job_fault_wq)); + init_waitqueue_head(&(kbdev->job_fault_resume_wq)); + spin_lock_init(&kbdev->job_fault_event_lock); + + kbdev->job_fault_resume_workq = alloc_workqueue( + "kbase_job_fault_resume_work_queue", WQ_MEM_RECLAIM, 1); + if (!kbdev->job_fault_resume_workq) + return -ENOMEM; + + kbdev->job_fault_debug = false; + + return 0; +} + +/* + * Release the relevant resource per device + */ +void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev) +{ + destroy_workqueue(kbdev->job_fault_resume_workq); +} + + +/* + * Initialize the relevant data structure per context + */ +void kbase_debug_job_fault_context_init(struct kbase_context *kctx) +{ + + /* We need allocate double size register range + * Because this memory will keep the register address and value + */ + kctx->reg_dump = vmalloc(0x4000 * 2); + if (kctx->reg_dump == NULL) + return; + + if (kbase_debug_job_fault_reg_snapshot_init(kctx, 0x4000) == false) { + vfree(kctx->reg_dump); + kctx->reg_dump = NULL; + } + INIT_LIST_HEAD(&kctx->job_fault_resume_event_list); + atomic_set(&kctx->job_fault_count, 0); + +} + +/* + * release the relevant resource per context + */ +void kbase_debug_job_fault_context_term(struct kbase_context *kctx) +{ + vfree(kctx->reg_dump); +} + +#else /* CONFIG_DEBUG_FS */ + +int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev) +{ + kbdev->job_fault_debug = false; + + return 0; +} + +void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev) +{ +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.h b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.h new file mode 100644 index 000000000000..a2bf8983c37c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.h @@ -0,0 +1,96 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_DEBUG_JOB_FAULT_H +#define _KBASE_DEBUG_JOB_FAULT_H + +#include +#include + +#define REGISTER_DUMP_TERMINATION_FLAG 0xFFFFFFFF + +/** + * kbase_debug_job_fault_dev_init - Create the fault event wait queue + * per device and initialize the required lists. + * @kbdev: Device pointer + * + * Return: Zero on success or a negative error code. + */ +int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev); + +/** + * kbase_debug_job_fault_debugfs_init - Initialize job fault debug sysfs + * @kbdev: Device pointer + */ +void kbase_debug_job_fault_debugfs_init(struct kbase_device *kbdev); + +/** + * kbase_debug_job_fault_dev_term - Clean up resources created in + * kbase_debug_job_fault_dev_init. + * @kbdev: Device pointer + */ +void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev); + +/** + * kbase_debug_job_fault_context_init - Initialize the relevant + * data structure per context + * @kctx: KBase context pointer + */ +void kbase_debug_job_fault_context_init(struct kbase_context *kctx); + +/** + * kbase_debug_job_fault_context_term - Release the relevant + * resource per context + * @kctx: KBase context pointer + */ +void kbase_debug_job_fault_context_term(struct kbase_context *kctx); + +/** + * kbase_debug_job_fault_process - Process the failed job. + * It will send a event and wake up the job fault waiting queue + * Then create a work queue to wait for job dump finish + * This function should be called in the interrupt handler and before + * jd_done that make sure the jd_done_worker will be delayed until the + * job dump finish + * @katom: The failed atom pointer + * @completion_code: the job status + * @return true if dump is going on + */ +bool kbase_debug_job_fault_process(struct kbase_jd_atom *katom, + u32 completion_code); + + +/** + * kbase_debug_job_fault_reg_snapshot_init - Set the interested registers + * address during the job fault process, the relevant registers will + * be saved when a job fault happen + * @kctx: KBase context pointer + * @reg_range: Maximum register address space + * @return true if initializing successfully + */ +bool kbase_debug_job_fault_reg_snapshot_init(struct kbase_context *kctx, + int reg_range); + +/** + * kbase_job_fault_get_reg_snapshot - Read the interested registers for + * failed job dump + * @kctx: KBase context pointer + * @return true if getting registers successfully + */ +bool kbase_job_fault_get_reg_snapshot(struct kbase_context *kctx); + +#endif /*_KBASE_DEBUG_JOB_FAULT_H*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.c b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.c new file mode 100644 index 000000000000..aa271566e917 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.c @@ -0,0 +1,306 @@ +/* + * + * (C) COPYRIGHT 2013-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Debugfs interface to dump the memory visible to the GPU + */ + +#include "mali_kbase_debug_mem_view.h" +#include "mali_kbase.h" + +#include +#include + +#ifdef CONFIG_DEBUG_FS + +struct debug_mem_mapping { + struct list_head node; + + struct kbase_mem_phy_alloc *alloc; + unsigned long flags; + + u64 start_pfn; + size_t nr_pages; +}; + +struct debug_mem_data { + struct list_head mapping_list; + struct kbase_context *kctx; +}; + +struct debug_mem_seq_off { + struct list_head *lh; + size_t offset; +}; + +static void *debug_mem_start(struct seq_file *m, loff_t *_pos) +{ + struct debug_mem_data *mem_data = m->private; + struct debug_mem_seq_off *data; + struct debug_mem_mapping *map; + loff_t pos = *_pos; + + list_for_each_entry(map, &mem_data->mapping_list, node) { + if (pos >= map->nr_pages) { + pos -= map->nr_pages; + } else { + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + data->lh = &map->node; + data->offset = pos; + return data; + } + } + + /* Beyond the end */ + return NULL; +} + +static void debug_mem_stop(struct seq_file *m, void *v) +{ + kfree(v); +} + +static void *debug_mem_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct debug_mem_data *mem_data = m->private; + struct debug_mem_seq_off *data = v; + struct debug_mem_mapping *map; + + map = list_entry(data->lh, struct debug_mem_mapping, node); + + if (data->offset < map->nr_pages - 1) { + data->offset++; + ++*pos; + return data; + } + + if (list_is_last(data->lh, &mem_data->mapping_list)) { + kfree(data); + return NULL; + } + + data->lh = data->lh->next; + data->offset = 0; + ++*pos; + + return data; +} + +static int debug_mem_show(struct seq_file *m, void *v) +{ + struct debug_mem_data *mem_data = m->private; + struct debug_mem_seq_off *data = v; + struct debug_mem_mapping *map; + int i, j; + struct page *page; + uint32_t *mapping; + pgprot_t prot = PAGE_KERNEL; + + map = list_entry(data->lh, struct debug_mem_mapping, node); + + kbase_gpu_vm_lock(mem_data->kctx); + + if (data->offset >= map->alloc->nents) { + seq_printf(m, "%016llx: Unbacked page\n\n", (map->start_pfn + + data->offset) << PAGE_SHIFT); + goto out; + } + + if (!(map->flags & KBASE_REG_CPU_CACHED)) + prot = pgprot_writecombine(prot); + + page = phys_to_page(as_phys_addr_t(map->alloc->pages[data->offset])); + mapping = vmap(&page, 1, VM_MAP, prot); + if (!mapping) + goto out; + + for (i = 0; i < PAGE_SIZE; i += 4*sizeof(*mapping)) { + seq_printf(m, "%016llx:", i + ((map->start_pfn + + data->offset) << PAGE_SHIFT)); + + for (j = 0; j < 4*sizeof(*mapping); j += sizeof(*mapping)) + seq_printf(m, " %08x", mapping[(i+j)/sizeof(*mapping)]); + seq_putc(m, '\n'); + } + + vunmap(mapping); + + seq_putc(m, '\n'); + +out: + kbase_gpu_vm_unlock(mem_data->kctx); + return 0; +} + +static const struct seq_operations ops = { + .start = debug_mem_start, + .next = debug_mem_next, + .stop = debug_mem_stop, + .show = debug_mem_show, +}; + +static int debug_mem_zone_open(struct rb_root *rbtree, + struct debug_mem_data *mem_data) +{ + int ret = 0; + struct rb_node *p; + struct kbase_va_region *reg; + struct debug_mem_mapping *mapping; + + for (p = rb_first(rbtree); p; p = rb_next(p)) { + reg = rb_entry(p, struct kbase_va_region, rblink); + + if (reg->gpu_alloc == NULL) + /* Empty region - ignore */ + continue; + + mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + ret = -ENOMEM; + goto out; + } + + mapping->alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + mapping->start_pfn = reg->start_pfn; + mapping->nr_pages = reg->nr_pages; + mapping->flags = reg->flags; + list_add_tail(&mapping->node, &mem_data->mapping_list); + } + +out: + return ret; +} + +static int debug_mem_open(struct inode *i, struct file *file) +{ + struct file *kctx_file = i->i_private; + struct kbase_context *kctx = kctx_file->private_data; + struct debug_mem_data *mem_data; + int ret; + + ret = seq_open(file, &ops); + if (ret) + return ret; + + mem_data = kmalloc(sizeof(*mem_data), GFP_KERNEL); + if (!mem_data) { + ret = -ENOMEM; + goto out; + } + + mem_data->kctx = kctx; + + INIT_LIST_HEAD(&mem_data->mapping_list); + + get_file(kctx_file); + + kbase_gpu_vm_lock(kctx); + + ret = debug_mem_zone_open(&kctx->reg_rbtree_same, mem_data); + if (0 != ret) { + kbase_gpu_vm_unlock(kctx); + goto out; + } + + ret = debug_mem_zone_open(&kctx->reg_rbtree_exec, mem_data); + if (0 != ret) { + kbase_gpu_vm_unlock(kctx); + goto out; + } + + ret = debug_mem_zone_open(&kctx->reg_rbtree_custom, mem_data); + if (0 != ret) { + kbase_gpu_vm_unlock(kctx); + goto out; + } + + kbase_gpu_vm_unlock(kctx); + + ((struct seq_file *)file->private_data)->private = mem_data; + + return 0; + +out: + if (mem_data) { + while (!list_empty(&mem_data->mapping_list)) { + struct debug_mem_mapping *mapping; + + mapping = list_first_entry(&mem_data->mapping_list, + struct debug_mem_mapping, node); + kbase_mem_phy_alloc_put(mapping->alloc); + list_del(&mapping->node); + kfree(mapping); + } + fput(kctx_file); + kfree(mem_data); + } + seq_release(i, file); + return ret; +} + +static int debug_mem_release(struct inode *inode, struct file *file) +{ + struct file *kctx_file = inode->i_private; + struct seq_file *sfile = file->private_data; + struct debug_mem_data *mem_data = sfile->private; + struct debug_mem_mapping *mapping; + + seq_release(inode, file); + + while (!list_empty(&mem_data->mapping_list)) { + mapping = list_first_entry(&mem_data->mapping_list, + struct debug_mem_mapping, node); + kbase_mem_phy_alloc_put(mapping->alloc); + list_del(&mapping->node); + kfree(mapping); + } + + kfree(mem_data); + + fput(kctx_file); + + return 0; +} + +static const struct file_operations kbase_debug_mem_view_fops = { + .open = debug_mem_open, + .release = debug_mem_release, + .read = seq_read, + .llseek = seq_lseek +}; + +/** + * kbase_debug_mem_view_init - Initialise the mem_view sysfs file + * @kctx_file: The /dev/mali0 file instance for the context + * + * This function creates a "mem_view" file which can be used to get a view of + * the context's memory as the GPU sees it (i.e. using the GPU's page tables). + * + * The file is cleaned up by a call to debugfs_remove_recursive() deleting the + * parent directory. + */ +void kbase_debug_mem_view_init(struct file *kctx_file) +{ + struct kbase_context *kctx = kctx_file->private_data; + + debugfs_create_file("mem_view", S_IRUGO, kctx->kctx_dentry, kctx_file, + &kbase_debug_mem_view_fops); +} + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h new file mode 100644 index 000000000000..20ab51a776c6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h @@ -0,0 +1,25 @@ +/* + * + * (C) COPYRIGHT 2013-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_DEBUG_MEM_VIEW_H +#define _KBASE_DEBUG_MEM_VIEW_H + +#include + +void kbase_debug_mem_view_init(struct file *kctx_file); + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h new file mode 100644 index 000000000000..1ab64255d1a2 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -0,0 +1,1639 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_defs.h + * + * Defintions (types, defines, etcs) common to Kbase. They are placed here to + * allow the hierarchy of header files to work. + */ + +#ifndef _KBASE_DEFS_H_ +#define _KBASE_DEFS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_MALI_FPGA_BUS_LOGGER +#include +#endif + + +#ifdef CONFIG_KDS +#include +#endif /* CONFIG_KDS */ + +#if defined(CONFIG_SYNC) +#include +#else +#include "mali_kbase_fence_defs.h" +#endif + +#ifdef CONFIG_DEBUG_FS +#include +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_MALI_DEVFREQ +#include +#endif /* CONFIG_MALI_DEVFREQ */ + +#include +#include + +#if defined(CONFIG_PM_RUNTIME) || \ + (defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) +#define KBASE_PM_RUNTIME 1 +#endif + +/** Enable SW tracing when set */ +#ifdef CONFIG_MALI_MIDGARD_ENABLE_TRACE +#define KBASE_TRACE_ENABLE 1 +#endif + +#ifndef KBASE_TRACE_ENABLE +#ifdef CONFIG_MALI_DEBUG +#define KBASE_TRACE_ENABLE 1 +#else +#define KBASE_TRACE_ENABLE 0 +#endif /* CONFIG_MALI_DEBUG */ +#endif /* KBASE_TRACE_ENABLE */ + +/** Dump Job slot trace on error (only active if KBASE_TRACE_ENABLE != 0) */ +#define KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR 1 + +/** + * Number of milliseconds before resetting the GPU when a job cannot be "zapped" from the hardware. + * Note that the time is actually ZAP_TIMEOUT+SOFT_STOP_RESET_TIMEOUT between the context zap starting and the GPU + * actually being reset to give other contexts time for their jobs to be soft-stopped and removed from the hardware + * before resetting. + */ +#define ZAP_TIMEOUT 1000 + +/** Number of milliseconds before we time out on a GPU soft/hard reset */ +#define RESET_TIMEOUT 500 + +/** + * Prevent soft-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * Therefore, soft stop may still be disabled due to HW issues. + * + * @note Soft stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_SOFT_STOPS 0 + +/** + * Prevent hard-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * @note Hard stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_HARD_STOPS 0 + +/** + * The maximum number of Job Slots to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of job slots. + */ +#define BASE_JM_MAX_NR_SLOTS 3 + +/** + * The maximum number of Address Spaces to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of Address Spaces + */ +#define BASE_MAX_NR_AS 16 + +/* mmu */ +#define MIDGARD_MMU_VA_BITS 48 + +#define MIDGARD_MMU_LEVEL(x) (x) + +#if MIDGARD_MMU_VA_BITS > 39 +#define MIDGARD_MMU_TOPLEVEL MIDGARD_MMU_LEVEL(0) +#else +#define MIDGARD_MMU_TOPLEVEL MIDGARD_MMU_LEVEL(1) +#endif + +#define MIDGARD_MMU_BOTTOMLEVEL MIDGARD_MMU_LEVEL(3) + +#define GROWABLE_FLAGS_REQUIRED (KBASE_REG_PF_GROW | KBASE_REG_GPU_WR) + +/** setting in kbase_context::as_nr that indicates it's invalid */ +#define KBASEP_AS_NR_INVALID (-1) + +#define KBASE_LOCK_REGION_MAX_SIZE (63) +#define KBASE_LOCK_REGION_MIN_SIZE (11) + +#define KBASE_TRACE_SIZE_LOG2 8 /* 256 entries */ +#define KBASE_TRACE_SIZE (1 << KBASE_TRACE_SIZE_LOG2) +#define KBASE_TRACE_MASK ((1 << KBASE_TRACE_SIZE_LOG2)-1) + +#include "mali_kbase_js_defs.h" +#include "mali_kbase_hwaccess_defs.h" + +#define KBASEP_FORCE_REPLAY_DISABLED 0 + +/* Maximum force replay limit when randomization is enabled */ +#define KBASEP_FORCE_REPLAY_RANDOM_LIMIT 16 + +/** Atom has been previously soft-stoppped */ +#define KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED (1<<1) +/** Atom has been previously retried to execute */ +#define KBASE_KATOM_FLAGS_RERUN (1<<2) +#define KBASE_KATOM_FLAGS_JOBCHAIN (1<<3) +/** Atom has been previously hard-stopped. */ +#define KBASE_KATOM_FLAG_BEEN_HARD_STOPPED (1<<4) +/** Atom has caused us to enter disjoint state */ +#define KBASE_KATOM_FLAG_IN_DISJOINT (1<<5) +/* Atom blocked on cross-slot dependency */ +#define KBASE_KATOM_FLAG_X_DEP_BLOCKED (1<<7) +/* Atom has fail dependency on cross-slot dependency */ +#define KBASE_KATOM_FLAG_FAIL_BLOCKER (1<<8) +/* Atom is currently in the list of atoms blocked on cross-slot dependencies */ +#define KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST (1<<9) +/* Atom is currently holding a context reference */ +#define KBASE_KATOM_FLAG_HOLDING_CTX_REF (1<<10) +/* Atom requires GPU to be in protected mode */ +#define KBASE_KATOM_FLAG_PROTECTED (1<<11) +/* Atom has been stored in runnable_tree */ +#define KBASE_KATOM_FLAG_JSCTX_IN_TREE (1<<12) + +/* SW related flags about types of JS_COMMAND action + * NOTE: These must be masked off by JS_COMMAND_MASK */ + +/** This command causes a disjoint event */ +#define JS_COMMAND_SW_CAUSES_DISJOINT 0x100 + +/** Bitmask of all SW related flags */ +#define JS_COMMAND_SW_BITS (JS_COMMAND_SW_CAUSES_DISJOINT) + +#if (JS_COMMAND_SW_BITS & JS_COMMAND_MASK) +#error JS_COMMAND_SW_BITS not masked off by JS_COMMAND_MASK. Must update JS_COMMAND_SW_<..> bitmasks +#endif + +/** Soft-stop command that causes a Disjoint event. This of course isn't + * entirely masked off by JS_COMMAND_MASK */ +#define JS_COMMAND_SOFT_STOP_WITH_SW_DISJOINT \ + (JS_COMMAND_SW_CAUSES_DISJOINT | JS_COMMAND_SOFT_STOP) + +#define KBASEP_ATOM_ID_INVALID BASE_JD_ATOM_COUNT + +/* Serialize atoms within a slot (ie only one atom per job slot) */ +#define KBASE_SERIALIZE_INTRA_SLOT (1 << 0) +/* Serialize atoms between slots (ie only one job slot running at any time) */ +#define KBASE_SERIALIZE_INTER_SLOT (1 << 1) +/* Reset the GPU after each atom completion */ +#define KBASE_SERIALIZE_RESET (1 << 2) + +/* Forward declarations */ +struct kbase_context; +struct kbase_device; +struct kbase_as; +struct kbase_mmu_setup; + +#ifdef CONFIG_DEBUG_FS +struct base_job_fault_event { + + u32 event_code; + struct kbase_jd_atom *katom; + struct work_struct job_fault_work; + struct list_head head; + int reg_offset; +}; + +#endif + +struct kbase_jd_atom_dependency { + struct kbase_jd_atom *atom; + u8 dep_type; +}; + +/** + * struct kbase_io_access - holds information about 1 register access + * + * @addr: first bit indicates r/w (r=0, w=1) + * @value: value written or read + */ +struct kbase_io_access { + uintptr_t addr; + u32 value; +}; + +/** + * struct kbase_io_history - keeps track of all recent register accesses + * + * @enabled: true if register accesses are recorded, false otherwise + * @lock: spinlock protecting kbase_io_access array + * @count: number of registers read/written + * @size: number of elements in kbase_io_access array + * @buf: array of kbase_io_access + */ +struct kbase_io_history { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bool enabled; +#else + u32 enabled; +#endif + + spinlock_t lock; + size_t count; + u16 size; + struct kbase_io_access *buf; +}; + +/** + * @brief The function retrieves a read-only reference to the atom field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return readonly reference to dependent ATOM. + */ +static inline const struct kbase_jd_atom * kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency *dep) +{ + LOCAL_ASSERT(dep != NULL); + + return (const struct kbase_jd_atom *)(dep->atom); +} + +/** + * @brief The function retrieves a read-only reference to the dependency type field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return A dependency type value. + */ +static inline u8 kbase_jd_katom_dep_type(const struct kbase_jd_atom_dependency *dep) +{ + LOCAL_ASSERT(dep != NULL); + + return dep->dep_type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency. + * @param[in] a The ATOM to be set as a dependency. + * @param type The ATOM dependency type to be set. + * + */ +static inline void kbase_jd_katom_dep_set(const struct kbase_jd_atom_dependency *const_dep, + struct kbase_jd_atom *a, u8 type) +{ + struct kbase_jd_atom_dependency *dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (struct kbase_jd_atom_dependency *)const_dep; + + dep->atom = a; + dep->dep_type = type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency to be cleared. + * + */ +static inline void kbase_jd_katom_dep_clear(const struct kbase_jd_atom_dependency *const_dep) +{ + struct kbase_jd_atom_dependency *dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (struct kbase_jd_atom_dependency *)const_dep; + + dep->atom = NULL; + dep->dep_type = BASE_JD_DEP_TYPE_INVALID; +} + +enum kbase_atom_gpu_rb_state { + /* Atom is not currently present in slot ringbuffer */ + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB, + /* Atom is in slot ringbuffer but is blocked on a previous atom */ + KBASE_ATOM_GPU_RB_WAITING_BLOCKED, + /* Atom is in slot ringbuffer but is waiting for a previous protected + * mode transition to complete */ + KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV, + /* Atom is in slot ringbuffer but is waiting for proected mode + * transition */ + KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION, + /* Atom is in slot ringbuffer but is waiting for cores to become + * available */ + KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE, + /* Atom is in slot ringbuffer but is blocked on affinity */ + KBASE_ATOM_GPU_RB_WAITING_AFFINITY, + /* Atom is in slot ringbuffer and ready to run */ + KBASE_ATOM_GPU_RB_READY, + /* Atom is in slot ringbuffer and has been submitted to the GPU */ + KBASE_ATOM_GPU_RB_SUBMITTED, + /* Atom must be returned to JS as soon as it reaches the head of the + * ringbuffer due to a previous failure */ + KBASE_ATOM_GPU_RB_RETURN_TO_JS = -1 +}; + +enum kbase_atom_enter_protected_state { + /* + * Starting state: + * Check if a transition into protected mode is required. + * + * NOTE: The integer value of this must + * match KBASE_ATOM_EXIT_PROTECTED_CHECK. + */ + KBASE_ATOM_ENTER_PROTECTED_CHECK = 0, + /* Wait for vinstr to suspend. */ + KBASE_ATOM_ENTER_PROTECTED_VINSTR, + /* Wait for the L2 to become idle in preparation for + * the coherency change. */ + KBASE_ATOM_ENTER_PROTECTED_IDLE_L2, + /* End state; + * Prepare coherency change. */ + KBASE_ATOM_ENTER_PROTECTED_FINISHED, +}; + +enum kbase_atom_exit_protected_state { + /* + * Starting state: + * Check if a transition out of protected mode is required. + * + * NOTE: The integer value of this must + * match KBASE_ATOM_ENTER_PROTECTED_CHECK. + */ + KBASE_ATOM_EXIT_PROTECTED_CHECK = 0, + /* Wait for the L2 to become idle in preparation + * for the reset. */ + KBASE_ATOM_EXIT_PROTECTED_IDLE_L2, + /* Issue the protected reset. */ + KBASE_ATOM_EXIT_PROTECTED_RESET, + /* End state; + * Wait for the reset to complete. */ + KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT, +}; + +struct kbase_ext_res { + u64 gpu_address; + struct kbase_mem_phy_alloc *alloc; +}; + +struct kbase_jd_atom { + struct work_struct work; + ktime_t start_timestamp; + + struct base_jd_udata udata; + struct kbase_context *kctx; + + struct list_head dep_head[2]; + struct list_head dep_item[2]; + const struct kbase_jd_atom_dependency dep[2]; + /* List head used during job dispatch job_done processing - as + * dependencies may not be entirely resolved at this point, we need to + * use a separate list head. */ + struct list_head jd_item; + /* true if atom's jd_item is currently on a list. Prevents atom being + * processed twice. */ + bool in_jd_list; + + u16 nr_extres; + struct kbase_ext_res *extres; + + u32 device_nr; + u64 affinity; + u64 jc; + enum kbase_atom_coreref_state coreref_state; +#ifdef CONFIG_KDS + struct list_head node; + struct kds_resource_set *kds_rset; + bool kds_dep_satisfied; +#endif /* CONFIG_KDS */ +#if defined(CONFIG_SYNC) + /* Stores either an input or output fence, depending on soft-job type */ + struct sync_fence *fence; + struct sync_fence_waiter sync_waiter; +#endif /* CONFIG_SYNC */ +#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) + struct { + /* Use the functions/API defined in mali_kbase_fence.h to + * when working with this sub struct */ +#if defined(CONFIG_SYNC_FILE) + /* Input fence */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence_in; +#else + struct dma_fence *fence_in; +#endif +#endif + /* This points to the dma-buf output fence for this atom. If + * this is NULL then there is no fence for this atom and the + * following fields related to dma_fence may have invalid data. + * + * The context and seqno fields contain the details for this + * fence. + * + * This fence is signaled when the katom is completed, + * regardless of the event_code of the katom (signal also on + * failure). + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + /* The dma-buf fence context number for this atom. A unique + * context number is allocated to each katom in the context on + * context creation. + */ + unsigned int context; + /* The dma-buf fence sequence number for this atom. This is + * increased every time this katom uses dma-buf fence. + */ + atomic_t seqno; + /* This contains a list of all callbacks set up to wait on + * other fences. This atom must be held back from JS until all + * these callbacks have been called and dep_count have reached + * 0. The initial value of dep_count must be equal to the + * number of callbacks on this list. + * + * This list is protected by jctx.lock. Callbacks are added to + * this list when the atom is built and the wait are set up. + * All the callbacks then stay on the list until all callbacks + * have been called and the atom is queued, or cancelled, and + * then all callbacks are taken off the list and freed. + */ + struct list_head callbacks; + /* Atomic counter of number of outstandind dma-buf fence + * dependencies for this atom. When dep_count reaches 0 the + * atom may be queued. + * + * The special value "-1" may only be set after the count + * reaches 0, while holding jctx.lock. This indicates that the + * atom has been handled, either queued in JS or cancelled. + * + * If anyone but the dma-fence worker sets this to -1 they must + * ensure that any potentially queued worker must have + * completed before allowing the atom to be marked as unused. + * This can be done by flushing the fence work queue: + * kctx->dma_fence.wq. + */ + atomic_t dep_count; + } dma_fence; +#endif /* CONFIG_MALI_DMA_FENCE || CONFIG_SYNC_FILE*/ + + /* Note: refer to kbasep_js_atom_retained_state, which will take a copy of some of the following members */ + enum base_jd_event_code event_code; + base_jd_core_req core_req; /**< core requirements */ + /** Job Slot to retry submitting to if submission from IRQ handler failed + * + * NOTE: see if this can be unified into the another member e.g. the event */ + int retry_submit_on_slot; + + u32 ticks; + /* JS atom priority with respect to other atoms on its kctx. */ + int sched_priority; + + int poking; /* BASE_HW_ISSUE_8316 */ + + wait_queue_head_t completed; + enum kbase_jd_atom_state status; +#ifdef CONFIG_GPU_TRACEPOINTS + int work_id; +#endif + /* Assigned after atom is completed. Used to check whether PRLAM-10676 workaround should be applied */ + int slot_nr; + + u32 atom_flags; + + /* Number of times this atom has been retried. Used by replay soft job. + */ + int retry_count; + + enum kbase_atom_gpu_rb_state gpu_rb_state; + + u64 need_cache_flush_cores_retained; + + atomic_t blocked; + + /* Pointer to atom that this atom has same-slot dependency on */ + struct kbase_jd_atom *pre_dep; + /* Pointer to atom that has same-slot dependency on this atom */ + struct kbase_jd_atom *post_dep; + + /* Pointer to atom that this atom has cross-slot dependency on */ + struct kbase_jd_atom *x_pre_dep; + /* Pointer to atom that has cross-slot dependency on this atom */ + struct kbase_jd_atom *x_post_dep; + + /* The GPU's flush count recorded at the time of submission, used for + * the cache flush optimisation */ + u32 flush_id; + + struct kbase_jd_atom_backend backend; +#ifdef CONFIG_DEBUG_FS + struct base_job_fault_event fault_event; +#endif + + /* List head used for three different purposes: + * 1. Overflow list for JS ring buffers. If an atom is ready to run, + * but there is no room in the JS ring buffer, then the atom is put + * on the ring buffer's overflow list using this list node. + * 2. List of waiting soft jobs. + */ + struct list_head queue; + + /* Used to keep track of all JIT free/alloc jobs in submission order + */ + struct list_head jit_node; + bool jit_blocked; + + /* If non-zero, this indicates that the atom will fail with the set + * event_code when the atom is processed. */ + enum base_jd_event_code will_fail_event_code; + + /* Atoms will only ever be transitioning into, or out of + * protected mode so we do not need two separate fields. + */ + union { + enum kbase_atom_enter_protected_state enter; + enum kbase_atom_exit_protected_state exit; + } protected_state; + + struct rb_node runnable_tree_node; + + /* 'Age' of atom relative to other atoms in the context. */ + u32 age; +}; + +static inline bool kbase_jd_katom_is_protected(const struct kbase_jd_atom *katom) +{ + return (bool)(katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED); +} + +/* + * Theory of operations: + * + * Atom objects are statically allocated within the context structure. + * + * Each atom is the head of two lists, one for the "left" set of dependencies, one for the "right" set. + */ + +#define KBASE_JD_DEP_QUEUE_SIZE 256 + +struct kbase_jd_context { + struct mutex lock; + struct kbasep_js_kctx_info sched_info; + struct kbase_jd_atom atoms[BASE_JD_ATOM_COUNT]; + + /** Tracks all job-dispatch jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + u32 job_nr; + + /** Waitq that reflects whether there are no jobs (including SW-only + * dependency jobs). This is set when no jobs are present on the ctx, + * and clear when there are jobs. + * + * @note: Job Dispatcher knows about more jobs than the Job Scheduler: + * the Job Scheduler is unaware of jobs that are blocked on dependencies, + * and SW-only dependency jobs. + * + * This waitq can be waited upon to find out when the context jobs are all + * done/cancelled (including those that might've been blocked on + * dependencies) - and so, whether it can be terminated. However, it should + * only be terminated once it is not present in the run-pool (see + * kbasep_js_kctx_info::ctx::is_scheduled). + * + * Since the waitq is only set under kbase_jd_context::lock, + * the waiter should also briefly obtain and drop kbase_jd_context::lock to + * guarentee that the setter has completed its work on the kbase_context + * + * This must be updated atomically with: + * - kbase_jd_context::job_nr */ + wait_queue_head_t zero_jobs_wait; + + /** Job Done workqueue. */ + struct workqueue_struct *job_done_wq; + + spinlock_t tb_lock; + u32 *tb; + size_t tb_wrap_offset; + +#ifdef CONFIG_KDS + struct kds_callback kds_cb; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_t work_id; +#endif +}; + +struct kbase_device_info { + u32 features; +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +enum { + KBASE_AS_POKE_STATE_IN_FLIGHT = 1<<0, + KBASE_AS_POKE_STATE_KILLING_POKE = 1<<1 +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +typedef u32 kbase_as_poke_state; + +struct kbase_mmu_setup { + u64 transtab; + u64 memattr; + u64 transcfg; +}; + +/** + * Important: Our code makes assumptions that a struct kbase_as structure is always at + * kbase_device->as[number]. This is used to recover the containing + * struct kbase_device from a struct kbase_as structure. + * + * Therefore, struct kbase_as structures must not be allocated anywhere else. + */ +struct kbase_as { + int number; + + struct workqueue_struct *pf_wq; + struct work_struct work_pagefault; + struct work_struct work_busfault; + enum kbase_mmu_fault_type fault_type; + bool protected_mode; + u32 fault_status; + u64 fault_addr; + u64 fault_extra_addr; + + struct kbase_mmu_setup current_setup; + + /* BASE_HW_ISSUE_8316 */ + struct workqueue_struct *poke_wq; + struct work_struct poke_work; + /** Protected by hwaccess_lock */ + int poke_refcount; + /** Protected by hwaccess_lock */ + kbase_as_poke_state poke_state; + struct hrtimer poke_timer; +}; + +static inline int kbase_as_has_bus_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_BUS; +} + +static inline int kbase_as_has_page_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_PAGE; +} + +struct kbasep_mem_device { + atomic_t used_pages; /* Tracks usage of OS shared memory. Updated + when OS memory is allocated/freed. */ + +}; + +#define KBASE_TRACE_CODE(X) KBASE_TRACE_CODE_ ## X + +enum kbase_trace_code { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ENUM */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) KBASE_TRACE_CODE(X) +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE + /* Comma on its own, to extend the list */ + , + /* Must be the last in the enum */ + KBASE_TRACE_CODE_COUNT +}; + +#define KBASE_TRACE_FLAG_REFCOUNT (((u8)1) << 0) +#define KBASE_TRACE_FLAG_JOBSLOT (((u8)1) << 1) + +struct kbase_trace { + struct timespec timestamp; + u32 thread_id; + u32 cpu; + void *ctx; + bool katom; + int atom_number; + u64 atom_udata[2]; + u64 gpu_addr; + unsigned long info_val; + u8 code; + u8 jobslot; + u8 refcount; + u8 flags; +}; + +/** Event IDs for the power management framework. + * + * Any of these events might be missed, so they should not be relied upon to + * find the precise state of the GPU at a particular time in the + * trace. Overall, we should get a high percentage of these events for + * statisical purposes, and so a few missing should not be a problem */ +enum kbase_timeline_pm_event { + /* helper for tests */ + KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** Event reserved for backwards compatibility with 'init' events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_0 = KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** The power state of the device has changed. + * + * Specifically, the device has reached a desired or available state. + */ + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED, + + /** The GPU is becoming active. + * + * This event is sent when the first context is about to use the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE, + + /** The GPU is becoming idle. + * + * This event is sent when the last context has finished using the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_IDLE, + + /** Event reserved for backwards compatibility with 'policy_change' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_4, + + /** Event reserved for backwards compatibility with 'system_suspend' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_5, + + /** Event reserved for backwards compatibility with 'system_resume' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_6, + + /** The job scheduler is requesting to power up/down cores. + * + * This event is sent when: + * - powered down cores are needed to complete a job + * - powered up cores are not needed anymore + */ + KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, + + KBASEP_TIMELINE_PM_EVENT_LAST = KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, +}; + +#ifdef CONFIG_MALI_TRACE_TIMELINE +struct kbase_trace_kctx_timeline { + atomic_t jd_atoms_in_flight; + u32 owner_tgid; +}; + +struct kbase_trace_kbdev_timeline { + /* Note: strictly speaking, not needed, because it's in sync with + * kbase_device::jm_slots[]::submitted_nr + * + * But it's kept as an example of how to add global timeline tracking + * information + * + * The caller must hold hwaccess_lock when accessing this */ + u8 slot_atoms_submitted[BASE_JM_MAX_NR_SLOTS]; + + /* Last UID for each PM event */ + atomic_t pm_event_uid[KBASEP_TIMELINE_PM_EVENT_LAST+1]; + /* Counter for generating PM event UIDs */ + atomic_t pm_event_uid_counter; + /* + * L2 transition state - true indicates that the transition is ongoing + * Expected to be protected by hwaccess_lock */ + bool l2_transitioning; +}; +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + +struct kbasep_kctx_list_element { + struct list_head link; + struct kbase_context *kctx; +}; + +/** + * Data stored per device for power management. + * + * This structure contains data for the power management framework. There is one + * instance of this structure per device in the system. + */ +struct kbase_pm_device_data { + /** + * The lock protecting Power Management structures accessed outside of + * IRQ. + * + * This lock must also be held whenever the GPU is being powered on or + * off. + */ + struct mutex lock; + + /** The reference count of active contexts on this device. */ + int active_count; + /** Flag indicating suspending/suspended */ + bool suspending; + /* Wait queue set when active_count == 0 */ + wait_queue_head_t zero_active_count_wait; + + /** + * Bit masks identifying the available shader cores that are specified + * via sysfs. One mask per job slot. + */ + u64 debug_core_mask[BASE_JM_MAX_NR_SLOTS]; + u64 debug_core_mask_all; + + /** + * Callback for initializing the runtime power management. + * + * @param kbdev The kbase device + * + * @return 0 on success, else error code + */ + int (*callback_power_runtime_init)(struct kbase_device *kbdev); + + /** + * Callback for terminating the runtime power management. + * + * @param kbdev The kbase device + */ + void (*callback_power_runtime_term)(struct kbase_device *kbdev); + + /* Time in milliseconds between each dvfs sample */ + u32 dvfs_period; + + /* Period of GPU poweroff timer */ + ktime_t gpu_poweroff_time; + + /* Number of ticks of GPU poweroff timer before shader is powered off */ + int poweroff_shader_ticks; + + /* Number of ticks of GPU poweroff timer before GPU is powered off */ + int poweroff_gpu_ticks; + + struct kbase_pm_backend_data backend; +}; + +/** + * struct kbase_mem_pool - Page based memory pool for kctx/kbdev + * @kbdev: Kbase device where memory is used + * @cur_size: Number of free pages currently in the pool (may exceed @max_size + * in some corner cases) + * @max_size: Maximum number of free pages in the pool + * @order: order = 0 refers to a pool of 4 KB pages + * order = 9 refers to a pool of 2 MB pages (2^9 * 4KB = 2 MB) + * @pool_lock: Lock protecting the pool - must be held when modifying @cur_size + * and @page_list + * @page_list: List of free pages in the pool + * @reclaim: Shrinker for kernel reclaim of free pages + * @next_pool: Pointer to next pool where pages can be allocated when this pool + * is empty. Pages will spill over to the next pool when this pool + * is full. Can be NULL if there is no next pool. + */ +struct kbase_mem_pool { + struct kbase_device *kbdev; + size_t cur_size; + size_t max_size; + size_t order; + spinlock_t pool_lock; + struct list_head page_list; + struct shrinker reclaim; + + struct kbase_mem_pool *next_pool; +}; + +/** + * struct kbase_devfreq_opp - Lookup table for converting between nominal OPP + * frequency, and real frequency and core mask + * @opp_freq: Nominal OPP frequency + * @real_freq: Real GPU frequency + * @core_mask: Shader core mask + */ +struct kbase_devfreq_opp { + u64 opp_freq; + u64 real_freq; + u64 core_mask; +}; + +struct kbase_mmu_mode { + void (*update)(struct kbase_context *kctx); + void (*get_as_setup)(struct kbase_context *kctx, + struct kbase_mmu_setup * const setup); + void (*disable_as)(struct kbase_device *kbdev, int as_nr); + phys_addr_t (*pte_to_phy_addr)(u64 entry); + int (*ate_is_valid)(u64 ate, unsigned int level); + int (*pte_is_valid)(u64 pte, unsigned int level); + void (*entry_set_ate)(u64 *entry, struct tagged_addr phy, + unsigned long flags, unsigned int level); + void (*entry_set_pte)(u64 *entry, phys_addr_t phy); + void (*entry_invalidate)(u64 *entry); +}; + +struct kbase_mmu_mode const *kbase_mmu_mode_get_lpae(void); +struct kbase_mmu_mode const *kbase_mmu_mode_get_aarch64(void); + + +#define DEVNAME_SIZE 16 + +struct kbase_device { + s8 slot_submit_count_irq[BASE_JM_MAX_NR_SLOTS]; + + u32 hw_quirks_sc; + u32 hw_quirks_tiler; + u32 hw_quirks_mmu; + u32 hw_quirks_jm; + + struct list_head entry; + struct device *dev; + struct miscdevice mdev; + u64 reg_start; + size_t reg_size; + void __iomem *reg; + + struct { + int irq; + int flags; + } irqs[3]; + + struct clk *clock; +#ifdef CONFIG_REGULATOR + struct regulator *regulator; +#endif + char devname[DEVNAME_SIZE]; + +#ifdef CONFIG_MALI_NO_MALI + void *model; + struct kmem_cache *irq_slab; + struct workqueue_struct *irq_workq; + atomic_t serving_job_irq; + atomic_t serving_gpu_irq; + atomic_t serving_mmu_irq; + spinlock_t reg_op_lock; +#endif /* CONFIG_MALI_NO_MALI */ + + struct kbase_pm_device_data pm; + struct kbasep_js_device_data js_data; + struct kbase_mem_pool mem_pool; + struct kbase_mem_pool lp_mem_pool; + struct kbasep_mem_device memdev; + struct kbase_mmu_mode const *mmu_mode; + + struct kbase_as as[BASE_MAX_NR_AS]; + /* The below variables (as_free and as_to_kctx) are managed by the + * Context Scheduler. The kbasep_js_device_data::runpool_irq::lock must + * be held whilst accessing these. + */ + u16 as_free; /* Bitpattern of free Address Spaces */ + /* Mapping from active Address Spaces to kbase_context */ + struct kbase_context *as_to_kctx[BASE_MAX_NR_AS]; + + + spinlock_t mmu_mask_change; + + struct kbase_gpu_props gpu_props; + + /** List of SW workarounds for HW issues */ + unsigned long hw_issues_mask[(BASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + /** List of features available */ + unsigned long hw_features_mask[(BASE_HW_FEATURE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + + /* Bitmaps of cores that are currently in use (running jobs). + * These should be kept up to date by the job scheduler. + * + * pm.power_change_lock should be held when accessing these members. + * + * kbase_pm_check_transitions_nolock() should be called when bits are + * cleared to update the power management system and allow transitions to + * occur. */ + u64 shader_inuse_bitmap; + + /* Refcount for cores in use */ + u32 shader_inuse_cnt[64]; + + /* Bitmaps of cores the JS needs for jobs ready to run */ + u64 shader_needed_bitmap; + + /* Refcount for cores needed */ + u32 shader_needed_cnt[64]; + + u32 tiler_inuse_cnt; + + u32 tiler_needed_cnt; + + /* struct for keeping track of the disjoint information + * + * The state is > 0 if the GPU is in a disjoint state. Otherwise 0 + * The count is the number of disjoint events that have occurred on the GPU + */ + struct { + atomic_t count; + atomic_t state; + } disjoint_event; + + /* Refcount for tracking users of the l2 cache, e.g. when using hardware counter instrumentation. */ + u32 l2_users_count; + + /* Bitmaps of cores that are currently available (powered up and the power policy is happy for jobs to be + * submitted to these cores. These are updated by the power management code. The job scheduler should avoid + * submitting new jobs to any cores that are not marked as available. + * + * pm.power_change_lock should be held when accessing these members. + */ + u64 shader_available_bitmap; + u64 tiler_available_bitmap; + u64 l2_available_bitmap; + u64 stack_available_bitmap; + + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + + s8 nr_hw_address_spaces; /**< Number of address spaces in the GPU (constant after driver initialisation) */ + s8 nr_user_address_spaces; /**< Number of address spaces available to user contexts */ + + /* Structure used for instrumentation and HW counters dumping */ + struct kbase_hwcnt { + /* The lock should be used when accessing any of the following members */ + spinlock_t lock; + + struct kbase_context *kctx; + u64 addr; + + struct kbase_instr_backend backend; + } hwcnt; + + struct kbase_vinstr_context *vinstr_ctx; + +#if KBASE_TRACE_ENABLE + spinlock_t trace_lock; + u16 trace_first_out; + u16 trace_next_in; + struct kbase_trace *trace_rbuf; +#endif + + u32 reset_timeout_ms; + + struct mutex cacheclean_lock; + + /* Platform specific private data to be accessed by mali_kbase_config_xxx.c only */ + void *platform_context; + + /* List of kbase_contexts created */ + struct list_head kctx_list; + struct mutex kctx_list_lock; + +#ifdef CONFIG_MALI_DEVFREQ + struct devfreq_dev_profile devfreq_profile; + struct devfreq *devfreq; + unsigned long current_freq; + unsigned long current_nominal_freq; + unsigned long current_voltage; + u64 current_core_mask; + struct kbase_devfreq_opp *opp_table; + int num_opps; +#ifdef CONFIG_DEVFREQ_THERMAL +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) + struct devfreq_cooling_device *devfreq_cooling; +#else + struct thermal_cooling_device *devfreq_cooling; +#endif + /* Current IPA model - true for configured model, false for fallback */ + atomic_t ipa_use_configured_model; + struct { + /* Access to this struct must be with ipa.lock held */ + struct mutex lock; + struct kbase_ipa_model *configured_model; + struct kbase_ipa_model *fallback_model; + } ipa; +#endif /* CONFIG_DEVFREQ_THERMAL */ +#endif /* CONFIG_MALI_DEVFREQ */ + + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kbdev_timeline timeline; +#endif + + /* + * Control for enabling job dump on failure, set when control debugfs + * is opened. + */ + bool job_fault_debug; + +#ifdef CONFIG_DEBUG_FS + /* directory for debugfs entries */ + struct dentry *mali_debugfs_directory; + /* Root directory for per context entry */ + struct dentry *debugfs_ctx_directory; + +#ifdef CONFIG_MALI_DEBUG + /* bit for each as, set if there is new data to report */ + u64 debugfs_as_read_bitmap; +#endif /* CONFIG_MALI_DEBUG */ + + /* failed job dump, used for separate debug process */ + wait_queue_head_t job_fault_wq; + wait_queue_head_t job_fault_resume_wq; + struct workqueue_struct *job_fault_resume_workq; + struct list_head job_fault_event_list; + spinlock_t job_fault_event_lock; + struct kbase_context *kctx_fault; + +#if !MALI_CUSTOMER_RELEASE + /* Per-device data for register dumping interface */ + struct { + u16 reg_offset; /* Offset of a GPU_CONTROL register to be + dumped upon request */ + } regs_dump_debugfs_data; +#endif /* !MALI_CUSTOMER_RELEASE */ +#endif /* CONFIG_DEBUG_FS */ + + /* fbdump profiling controls set by gator */ + u32 kbase_profiling_controls[FBDUMP_CONTROL_MAX]; + + +#if MALI_CUSTOMER_RELEASE == 0 + /* Number of jobs that are run before a job is forced to fail and + * replay. May be KBASEP_FORCE_REPLAY_DISABLED, to disable forced + * failures. */ + int force_replay_limit; + /* Count of jobs between forced failures. Incremented on each job. A + * job is forced to fail once this is greater than or equal to + * force_replay_limit. */ + int force_replay_count; + /* Core requirement for jobs to be failed and replayed. May be zero. */ + base_jd_core_req force_replay_core_req; + /* true if force_replay_limit should be randomized. The random + * value will be in the range of 1 - KBASEP_FORCE_REPLAY_RANDOM_LIMIT. + */ + bool force_replay_random; +#endif + + /* Total number of created contexts */ + atomic_t ctx_num; + +#ifdef CONFIG_DEBUG_FS + /* Holds the most recent register accesses */ + struct kbase_io_history io_history; +#endif /* CONFIG_DEBUG_FS */ + + struct kbase_hwaccess_data hwaccess; + + /* Count of page/bus faults waiting for workqueues to process */ + atomic_t faults_pending; + + /* true if GPU is powered off or power off operation is in progress */ + bool poweroff_pending; + + + /* defaults for new context created for this device */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bool infinite_cache_active_default; +#else + u32 infinite_cache_active_default; +#endif + size_t mem_pool_max_size_default; + + /* current gpu coherency mode */ + u32 current_gpu_coherency_mode; + /* system coherency mode */ + u32 system_coherency; + /* Flag to track when cci snoops have been enabled on the interface */ + bool cci_snoop_enabled; + + /* SMC function IDs to call into Trusted firmware to enable/disable + * cache snooping. Value of 0 indicates that they are not used + */ + u32 snoop_enable_smc; + u32 snoop_disable_smc; + + /* Protected mode operations */ + struct protected_mode_ops *protected_ops; + + /* Protected device attached to this kbase device */ + struct protected_mode_device *protected_dev; + + /* + * true when GPU is put into protected mode + */ + bool protected_mode; + + /* + * true when GPU is transitioning into or out of protected mode + */ + bool protected_mode_transition; + + /* + * true if protected mode is supported + */ + bool protected_mode_support; + + +#ifdef CONFIG_MALI_DEBUG + wait_queue_head_t driver_inactive_wait; + bool driver_inactive; +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_MALI_FPGA_BUS_LOGGER + /* + * Bus logger integration. + */ + struct bus_logger_client *buslogger; +#endif + /* Boolean indicating if an IRQ flush during reset is in progress. */ + bool irq_reset_flush; + + /* list of inited sub systems. Used during terminate/error recovery */ + u32 inited_subsys; + + spinlock_t hwaccess_lock; + + /* Protects access to MMU operations */ + struct mutex mmu_hw_mutex; + + /* Current serialization mode. See KBASE_SERIALIZE_* for details */ + u8 serialize_jobs; +}; + +/** + * struct jsctx_queue - JS context atom queue + * @runnable_tree: Root of RB-tree containing currently runnable atoms on this + * job slot. + * @x_dep_head: Head item of the linked list of atoms blocked on cross-slot + * dependencies. Atoms on this list will be moved to the + * runnable_tree when the blocking atom completes. + * + * hwaccess_lock must be held when accessing this structure. + */ +struct jsctx_queue { + struct rb_root runnable_tree; + struct list_head x_dep_head; +}; + + +#define KBASE_API_VERSION(major, minor) ((((major) & 0xFFF) << 20) | \ + (((minor) & 0xFFF) << 8) | \ + ((0 & 0xFF) << 0)) + +/** + * enum kbase_context_flags - Flags for kbase contexts + * + * @KCTX_COMPAT: Set when the context process is a compat process, 32-bit + * process on a 64-bit kernel. + * + * @KCTX_RUNNABLE_REF: Set when context is counted in + * kbdev->js_data.nr_contexts_runnable. Must hold queue_mutex when accessing. + * + * @KCTX_ACTIVE: Set when the context is active. + * + * @KCTX_PULLED: Set when last kick() caused atoms to be pulled from this + * context. + * + * @KCTX_MEM_PROFILE_INITIALIZED: Set when the context's memory profile has been + * initialized. + * + * @KCTX_INFINITE_CACHE: Set when infinite cache is to be enabled for new + * allocations. Existing allocations will not change. + * + * @KCTX_SUBMIT_DISABLED: Set to prevent context from submitting any jobs. + * + * @KCTX_PRIVILEGED:Set if the context uses an address space and should be kept + * scheduled in. + * + * @KCTX_SCHEDULED: Set when the context is scheduled on the Run Pool. + * This is only ever updated whilst the jsctx_mutex is held. + * + * @KCTX_DYING: Set when the context process is in the process of being evicted. + * + * @KCTX_NO_IMPLICIT_SYNC: Set when explicit Android fences are in use on this + * context, to disable use of implicit dma-buf fences. This is used to avoid + * potential synchronization deadlocks. + * + * All members need to be separate bits. This enum is intended for use in a + * bitmask where multiple values get OR-ed together. + */ +enum kbase_context_flags { + KCTX_COMPAT = 1U << 0, + KCTX_RUNNABLE_REF = 1U << 1, + KCTX_ACTIVE = 1U << 2, + KCTX_PULLED = 1U << 3, + KCTX_MEM_PROFILE_INITIALIZED = 1U << 4, + KCTX_INFINITE_CACHE = 1U << 5, + KCTX_SUBMIT_DISABLED = 1U << 6, + KCTX_PRIVILEGED = 1U << 7, + KCTX_SCHEDULED = 1U << 8, + KCTX_DYING = 1U << 9, + KCTX_NO_IMPLICIT_SYNC = 1U << 10, +}; + +struct kbase_sub_alloc { + struct list_head link; + struct page *page; + DECLARE_BITMAP(sub_pages, SZ_2M / SZ_4K); +}; + +struct kbase_context { + struct file *filp; + struct kbase_device *kbdev; + u32 id; /* System wide unique id */ + unsigned long api_version; + phys_addr_t pgd; + struct list_head event_list; + struct list_head event_coalesce_list; + struct mutex event_mutex; + atomic_t event_closed; + struct workqueue_struct *event_workq; + atomic_t event_count; + int event_coalesce_count; + + atomic_t flags; + + atomic_t setup_complete; + atomic_t setup_in_progress; + + u64 *mmu_teardown_pages; + + struct tagged_addr aliasing_sink_page; + + struct mutex mem_partials_lock; + struct list_head mem_partials; + + struct mutex mmu_lock; + struct mutex reg_lock; /* To be converted to a rwlock? */ + struct rb_root reg_rbtree_same; /* RB tree of GPU (live) regions, + * SAME_VA zone */ + struct rb_root reg_rbtree_exec; /* RB tree of GPU (live) regions, + * EXEC zone */ + struct rb_root reg_rbtree_custom; /* RB tree of GPU (live) regions, + * CUSTOM_VA zone */ + + unsigned long cookies; + struct kbase_va_region *pending_regions[BITS_PER_LONG]; + + wait_queue_head_t event_queue; + pid_t tgid; + pid_t pid; + + struct kbase_jd_context jctx; + atomic_t used_pages; + atomic_t nonmapped_pages; + + struct kbase_mem_pool mem_pool; + struct kbase_mem_pool lp_mem_pool; + + struct shrinker reclaim; + struct list_head evict_list; + + struct list_head waiting_soft_jobs; + spinlock_t waiting_soft_jobs_lock; +#ifdef CONFIG_KDS + struct list_head waiting_kds_resource; +#endif +#ifdef CONFIG_MALI_DMA_FENCE + struct { + struct list_head waiting_resource; + struct workqueue_struct *wq; + } dma_fence; +#endif /* CONFIG_MALI_DMA_FENCE */ + /** This is effectively part of the Run Pool, because it only has a valid + * setting (!=KBASEP_AS_NR_INVALID) whilst the context is scheduled in + * + * The hwaccess_lock must be held whilst accessing this. + * + * If the context relating to this as_nr is required, you must use + * kbasep_js_runpool_retain_ctx() to ensure that the context doesn't disappear + * whilst you're using it. Alternatively, just hold the hwaccess_lock + * to ensure the context doesn't disappear (but this has restrictions on what other locks + * you can take whilst doing this) */ + int as_nr; + + /* Keeps track of the number of users of this context. A user can be a + * job that is available for execution, instrumentation needing to 'pin' + * a context for counter collection, etc. If the refcount reaches 0 then + * this context is considered inactive and the previously programmed + * AS might be cleared at any point. + */ + atomic_t refcount; + + /* NOTE: + * + * Flags are in jctx.sched_info.ctx.flags + * Mutable flags *must* be accessed under jctx.sched_info.ctx.jsctx_mutex + * + * All other flags must be added there */ + spinlock_t mm_update_lock; + struct mm_struct *process_mm; + /* End of the SAME_VA zone */ + u64 same_va_end; + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kctx_timeline timeline; +#endif +#ifdef CONFIG_DEBUG_FS + /* Content of mem_profile file */ + char *mem_profile_data; + /* Size of @c mem_profile_data */ + size_t mem_profile_size; + /* Mutex guarding memory profile state */ + struct mutex mem_profile_lock; + /* Memory profile directory under debugfs */ + struct dentry *kctx_dentry; + + /* for job fault debug */ + unsigned int *reg_dump; + atomic_t job_fault_count; + /* This list will keep the following atoms during the dump + * in the same context + */ + struct list_head job_fault_resume_event_list; + +#endif /* CONFIG_DEBUG_FS */ + + struct jsctx_queue jsctx_queue + [KBASE_JS_ATOM_SCHED_PRIO_COUNT][BASE_JM_MAX_NR_SLOTS]; + + /* Number of atoms currently pulled from this context */ + atomic_t atoms_pulled; + /* Number of atoms currently pulled from this context, per slot */ + atomic_t atoms_pulled_slot[BASE_JM_MAX_NR_SLOTS]; + /* Number of atoms currently pulled from this context, per slot and + * priority. Hold hwaccess_lock when accessing */ + int atoms_pulled_slot_pri[BASE_JM_MAX_NR_SLOTS][ + KBASE_JS_ATOM_SCHED_PRIO_COUNT]; + + /* true if slot is blocked on the given priority. This will be set on a + * soft-stop */ + bool blocked_js[BASE_JM_MAX_NR_SLOTS][KBASE_JS_ATOM_SCHED_PRIO_COUNT]; + + /* Bitmask of slots that can be pulled from */ + u32 slots_pullable; + + /* Backend specific data */ + struct kbase_context_backend backend; + + /* Work structure used for deferred ASID assignment */ + struct work_struct work; + + /* Only one userspace vinstr client per kbase context */ + struct kbase_vinstr_client *vinstr_cli; + struct mutex vinstr_cli_lock; + + /* List of completed jobs waiting for events to be posted */ + struct list_head completed_jobs; + /* Number of work items currently pending on job_done_wq */ + atomic_t work_count; + + /* Waiting soft-jobs will fail when this timer expires */ + struct timer_list soft_job_timeout; + + /* JIT allocation management */ + struct kbase_va_region *jit_alloc[256]; + struct list_head jit_active_head; + struct list_head jit_pool_head; + struct list_head jit_destroy_head; + struct mutex jit_evict_lock; + struct work_struct jit_work; + + /* A list of the JIT soft-jobs in submission order + * (protected by kbase_jd_context.lock) + */ + struct list_head jit_atoms_head; + /* A list of pending JIT alloc soft-jobs (using the 'queue' list_head) + * (protected by kbase_jd_context.lock) + */ + struct list_head jit_pending_alloc; + + /* External sticky resource management */ + struct list_head ext_res_meta_head; + + /* Used to record that a drain was requested from atomic context */ + atomic_t drain_pending; + + /* Current age count, used to determine age for newly submitted atoms */ + u32 age_count; +}; + +/** + * struct kbase_ctx_ext_res_meta - Structure which binds an external resource + * to a @kbase_context. + * @ext_res_node: List head for adding the metadata to a + * @kbase_context. + * @alloc: The physical memory allocation structure + * which is mapped. + * @gpu_addr: The GPU virtual address the resource is + * mapped to. + * + * External resources can be mapped into multiple contexts as well as the same + * context multiple times. + * As kbase_va_region itself isn't refcounted we can't attach our extra + * information to it as it could be removed under our feet leaving external + * resources pinned. + * This metadata structure binds a single external resource to a single + * context, ensuring that per context mapping is tracked separately so it can + * be overridden when needed and abuses by the application (freeing the resource + * multiple times) don't effect the refcount of the physical allocation. + */ +struct kbase_ctx_ext_res_meta { + struct list_head ext_res_node; + struct kbase_mem_phy_alloc *alloc; + u64 gpu_addr; +}; + +enum kbase_reg_access_type { + REG_READ, + REG_WRITE +}; + +enum kbase_share_attr_bits { + /* (1ULL << 8) bit is reserved */ + SHARE_BOTH_BITS = (2ULL << 8), /* inner and outer shareable coherency */ + SHARE_INNER_BITS = (3ULL << 8) /* inner shareable coherency */ +}; + +/** + * kbase_device_is_cpu_coherent - Returns if the device is CPU coherent. + * @kbdev: kbase device + * + * Return: true if the device access are coherent, false if not. + */ +static inline bool kbase_device_is_cpu_coherent(struct kbase_device *kbdev) +{ + if ((kbdev->system_coherency == COHERENCY_ACE_LITE) || + (kbdev->system_coherency == COHERENCY_ACE)) + return true; + + return false; +} + +/* Conversion helpers for setting up high resolution timers */ +#define HR_TIMER_DELAY_MSEC(x) (ns_to_ktime(((u64)(x))*1000000U)) +#define HR_TIMER_DELAY_NSEC(x) (ns_to_ktime(x)) + +/* Maximum number of loops polling the GPU for a cache flush before we assume it must have completed */ +#define KBASE_CLEAN_CACHE_MAX_LOOPS 100000 +/* Maximum number of loops polling the GPU for an AS command to complete before we assume the GPU has hung */ +#define KBASE_AS_INACTIVE_MAX_LOOPS 100000 + +/* Maximum number of times a job can be replayed */ +#define BASEP_JD_REPLAY_LIMIT 15 + +/* JobDescriptorHeader - taken from the architecture specifications, the layout + * is currently identical for all GPU archs. */ +struct job_descriptor_header { + u32 exception_status; + u32 first_incomplete_task; + u64 fault_pointer; + u8 job_descriptor_size : 1; + u8 job_type : 7; + u8 job_barrier : 1; + u8 _reserved_01 : 1; + u8 _reserved_1 : 1; + u8 _reserved_02 : 1; + u8 _reserved_03 : 1; + u8 _reserved_2 : 1; + u8 _reserved_04 : 1; + u8 _reserved_05 : 1; + u16 job_index; + u16 job_dependency_index_1; + u16 job_dependency_index_2; + union { + u64 _64; + u32 _32; + } next_job; +}; + +#endif /* _KBASE_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_device.c b/drivers/gpu/arm/bifrost/mali_kbase_device.c new file mode 100644 index 000000000000..d635fccaea14 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_device.c @@ -0,0 +1,674 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel device APIs + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* NOTE: Magic - 0x45435254 (TRCE in ASCII). + * Supports tracing feature provided in the base module. + * Please keep it in sync with the value of base module. + */ +#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254 + +#if KBASE_TRACE_ENABLE +static const char *kbasep_trace_code_string[] = { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ARRAY */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) # X +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE +}; +#endif + +#define DEBUG_MESSAGE_SIZE 256 + +static int kbasep_trace_init(struct kbase_device *kbdev); +static void kbasep_trace_term(struct kbase_device *kbdev); +static void kbasep_trace_hook_wrapper(void *param); + +struct kbase_device *kbase_device_alloc(void) +{ + return kzalloc(sizeof(struct kbase_device), GFP_KERNEL); +} + +static int kbase_device_as_init(struct kbase_device *kbdev, int i) +{ + const char format[] = "mali_mmu%d"; + char name[sizeof(format)]; + const char poke_format[] = "mali_mmu%d_poker"; + char poke_name[sizeof(poke_format)]; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + snprintf(poke_name, sizeof(poke_name), poke_format, i); + + snprintf(name, sizeof(name), format, i); + + kbdev->as[i].number = i; + kbdev->as[i].fault_addr = 0ULL; + + kbdev->as[i].pf_wq = alloc_workqueue(name, 0, 1); + if (!kbdev->as[i].pf_wq) + return -EINVAL; + + INIT_WORK(&kbdev->as[i].work_pagefault, page_fault_worker); + INIT_WORK(&kbdev->as[i].work_busfault, bus_fault_worker); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + struct hrtimer *poke_timer = &kbdev->as[i].poke_timer; + struct work_struct *poke_work = &kbdev->as[i].poke_work; + + kbdev->as[i].poke_wq = alloc_workqueue(poke_name, 0, 1); + if (!kbdev->as[i].poke_wq) { + destroy_workqueue(kbdev->as[i].pf_wq); + return -EINVAL; + } + KBASE_DEBUG_ASSERT(!object_is_on_stack(poke_work)); + INIT_WORK(poke_work, kbasep_as_do_poke); + + hrtimer_init(poke_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + + poke_timer->function = kbasep_as_poke_timer_callback; + + kbdev->as[i].poke_refcount = 0; + kbdev->as[i].poke_state = 0u; + } + + return 0; +} + +static void kbase_device_as_term(struct kbase_device *kbdev, int i) +{ + destroy_workqueue(kbdev->as[i].pf_wq); + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + destroy_workqueue(kbdev->as[i].poke_wq); +} + +static int kbase_device_all_as_init(struct kbase_device *kbdev) +{ + int i, err; + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + err = kbase_device_as_init(kbdev, i); + if (err) + goto free_workqs; + } + + return 0; + +free_workqs: + for (; i > 0; i--) + kbase_device_as_term(kbdev, i); + + return err; +} + +static void kbase_device_all_as_term(struct kbase_device *kbdev) +{ + int i; + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) + kbase_device_as_term(kbdev, i); +} + +int kbase_device_init(struct kbase_device * const kbdev) +{ + int i, err; +#ifdef CONFIG_ARM64 + struct device_node *np = NULL; +#endif /* CONFIG_ARM64 */ + + spin_lock_init(&kbdev->mmu_mask_change); + mutex_init(&kbdev->mmu_hw_mutex); +#ifdef CONFIG_ARM64 + kbdev->cci_snoop_enabled = false; + np = kbdev->dev->of_node; + if (np != NULL) { + if (of_property_read_u32(np, "snoop_enable_smc", + &kbdev->snoop_enable_smc)) + kbdev->snoop_enable_smc = 0; + if (of_property_read_u32(np, "snoop_disable_smc", + &kbdev->snoop_disable_smc)) + kbdev->snoop_disable_smc = 0; + /* Either both or none of the calls should be provided. */ + if (!((kbdev->snoop_disable_smc == 0 + && kbdev->snoop_enable_smc == 0) + || (kbdev->snoop_disable_smc != 0 + && kbdev->snoop_enable_smc != 0))) { + WARN_ON(1); + err = -EINVAL; + goto fail; + } + } +#endif /* CONFIG_ARM64 */ + /* Get the list of workarounds for issues on the current HW + * (identified by the GPU_ID register) + */ + err = kbase_hw_set_issues_mask(kbdev); + if (err) + goto fail; + + /* Set the list of features available on the current HW + * (identified by the GPU_ID register) + */ + kbase_hw_set_features_mask(kbdev); + + kbase_gpuprops_set_features(kbdev); + + /* On Linux 4.0+, dma coherency is determined from device tree */ +#if defined(CONFIG_ARM64) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) + set_dma_ops(kbdev->dev, &noncoherent_swiotlb_dma_ops); +#endif + + /* Workaround a pre-3.13 Linux issue, where dma_mask is NULL when our + * device structure was created by device-tree + */ + if (!kbdev->dev->dma_mask) + kbdev->dev->dma_mask = &kbdev->dev->coherent_dma_mask; + + err = dma_set_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits)); + if (err) + goto dma_set_mask_failed; + + err = dma_set_coherent_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits)); + if (err) + goto dma_set_mask_failed; + + kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces; + + err = kbase_device_all_as_init(kbdev); + if (err) + goto as_init_failed; + + spin_lock_init(&kbdev->hwcnt.lock); + + err = kbasep_trace_init(kbdev); + if (err) + goto term_as; + + mutex_init(&kbdev->cacheclean_lock); + +#ifdef CONFIG_MALI_TRACE_TIMELINE + for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) + kbdev->timeline.slot_atoms_submitted[i] = 0; + + for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i) + atomic_set(&kbdev->timeline.pm_event_uid[i], 0); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + /* fbdump profiling controls set to 0 - fbdump not enabled until changed by gator */ + for (i = 0; i < FBDUMP_CONTROL_MAX; i++) + kbdev->kbase_profiling_controls[i] = 0; + + kbase_debug_assert_register_hook(&kbasep_trace_hook_wrapper, kbdev); + + atomic_set(&kbdev->ctx_num, 0); + + err = kbase_instr_backend_init(kbdev); + if (err) + goto term_trace; + + kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD; + + kbdev->reset_timeout_ms = DEFAULT_RESET_TIMEOUT_MS; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + kbdev->mmu_mode = kbase_mmu_mode_get_aarch64(); + else + kbdev->mmu_mode = kbase_mmu_mode_get_lpae(); + +#ifdef CONFIG_MALI_DEBUG + init_waitqueue_head(&kbdev->driver_inactive_wait); +#endif /* CONFIG_MALI_DEBUG */ + + return 0; +term_trace: + kbasep_trace_term(kbdev); +term_as: + kbase_device_all_as_term(kbdev); +as_init_failed: +dma_set_mask_failed: +fail: + return err; +} + +void kbase_device_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); + +#if KBASE_TRACE_ENABLE + kbase_debug_assert_register_hook(NULL, NULL); +#endif + + kbase_instr_backend_term(kbdev); + + kbasep_trace_term(kbdev); + + kbase_device_all_as_term(kbdev); +} + +void kbase_device_free(struct kbase_device *kbdev) +{ + kfree(kbdev); +} + +int kbase_device_trace_buffer_install( + struct kbase_context *kctx, u32 *tb, size_t size) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(tb); + + /* Interface uses 16-bit value to track last accessed entry. Each entry + * is composed of two 32-bit words. + * This limits the size that can be handled without an overflow. */ + if (0xFFFF * (2 * sizeof(u32)) < size) + return -EINVAL; + + /* set up the header */ + /* magic number in the first 4 bytes */ + tb[0] = TRACE_BUFFER_HEADER_SPECIAL; + /* Store (write offset = 0, wrap counter = 0, transaction active = no) + * write offset 0 means never written. + * Offsets 1 to (wrap_offset - 1) used to store values when trace started + */ + tb[1] = 0; + + /* install trace buffer */ + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb_wrap_offset = size / 8; + kctx->jctx.tb = tb; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); + + return 0; +} + +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kctx); + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb = NULL; + kctx->jctx.tb_wrap_offset = 0; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value) +{ + unsigned long flags; + + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + if (kctx->jctx.tb) { + u16 wrap_count; + u16 write_offset; + u32 *tb = kctx->jctx.tb; + u32 header_word; + + header_word = tb[1]; + KBASE_DEBUG_ASSERT(0 == (header_word & 0x1)); + + wrap_count = (header_word >> 1) & 0x7FFF; + write_offset = (header_word >> 16) & 0xFFFF; + + /* mark as transaction in progress */ + tb[1] |= 0x1; + mb(); + + /* calculate new offset */ + write_offset++; + if (write_offset == kctx->jctx.tb_wrap_offset) { + /* wrap */ + write_offset = 1; + wrap_count++; + wrap_count &= 0x7FFF; /* 15bit wrap counter */ + } + + /* store the trace entry at the selected offset */ + tb[write_offset * 2 + 0] = (reg_offset & ~0x3) | ((type == REG_WRITE) ? 0x1 : 0x0); + tb[write_offset * 2 + 1] = reg_value; + mb(); + + /* new header word */ + header_word = (write_offset << 16) | (wrap_count << 1) | 0x0; /* transaction complete */ + tb[1] = header_word; + } + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +/* + * Device trace functions + */ +#if KBASE_TRACE_ENABLE + +static int kbasep_trace_init(struct kbase_device *kbdev) +{ + struct kbase_trace *rbuf; + + rbuf = kmalloc_array(KBASE_TRACE_SIZE, sizeof(*rbuf), GFP_KERNEL); + + if (!rbuf) + return -EINVAL; + + kbdev->trace_rbuf = rbuf; + spin_lock_init(&kbdev->trace_lock); + return 0; +} + +static void kbasep_trace_term(struct kbase_device *kbdev) +{ + kfree(kbdev->trace_rbuf); +} + +static void kbasep_trace_format_msg(struct kbase_trace *trace_msg, char *buffer, int len) +{ + s32 written = 0; + + /* Initial part of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d.%.6d,%d,%d,%s,%p,", (int)trace_msg->timestamp.tv_sec, (int)(trace_msg->timestamp.tv_nsec / 1000), trace_msg->thread_id, trace_msg->cpu, kbasep_trace_code_string[trace_msg->code], trace_msg->ctx), 0); + + if (trace_msg->katom) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "atom %d (ud: 0x%llx 0x%llx)", trace_msg->atom_number, trace_msg->atom_udata[0], trace_msg->atom_udata[1]), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ",%.8llx,", trace_msg->gpu_addr), 0); + + /* NOTE: Could add function callbacks to handle different message types */ + /* Jobslot present */ + if (trace_msg->flags & KBASE_TRACE_FLAG_JOBSLOT) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->jobslot), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Refcount present */ + if (trace_msg->flags & KBASE_TRACE_FLAG_REFCOUNT) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->refcount), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Rest of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "0x%.8lx", trace_msg->info_val), 0); +} + +static void kbasep_trace_dump_msg(struct kbase_device *kbdev, struct kbase_trace *trace_msg) +{ + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + dev_dbg(kbdev->dev, "%s", buffer); +} + +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val) +{ + unsigned long irqflags; + struct kbase_trace *trace_msg; + + spin_lock_irqsave(&kbdev->trace_lock, irqflags); + + trace_msg = &kbdev->trace_rbuf[kbdev->trace_next_in]; + + /* Fill the message */ + trace_msg->thread_id = task_pid_nr(current); + trace_msg->cpu = task_cpu(current); + + getnstimeofday(&trace_msg->timestamp); + + trace_msg->code = code; + trace_msg->ctx = ctx; + + if (NULL == katom) { + trace_msg->katom = false; + } else { + trace_msg->katom = true; + trace_msg->atom_number = kbase_jd_atom_id(katom->kctx, katom); + trace_msg->atom_udata[0] = katom->udata.blob[0]; + trace_msg->atom_udata[1] = katom->udata.blob[1]; + } + + trace_msg->gpu_addr = gpu_addr; + trace_msg->jobslot = jobslot; + trace_msg->refcount = MIN((unsigned int)refcount, 0xFF); + trace_msg->info_val = info_val; + trace_msg->flags = flags; + + /* Update the ringbuffer indices */ + kbdev->trace_next_in = (kbdev->trace_next_in + 1) & KBASE_TRACE_MASK; + if (kbdev->trace_next_in == kbdev->trace_first_out) + kbdev->trace_first_out = (kbdev->trace_first_out + 1) & KBASE_TRACE_MASK; + + /* Done */ + + spin_unlock_irqrestore(&kbdev->trace_lock, irqflags); +} + +void kbasep_trace_clear(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->trace_lock, flags); + kbdev->trace_first_out = kbdev->trace_next_in; + spin_unlock_irqrestore(&kbdev->trace_lock, flags); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 start; + u32 end; + + dev_dbg(kbdev->dev, "Dumping trace:\nsecs,nthread,cpu,code,ctx,katom,gpu_addr,jobslot,refcount,info_val"); + spin_lock_irqsave(&kbdev->trace_lock, flags); + start = kbdev->trace_first_out; + end = kbdev->trace_next_in; + + while (start != end) { + struct kbase_trace *trace_msg = &kbdev->trace_rbuf[start]; + + kbasep_trace_dump_msg(kbdev, trace_msg); + + start = (start + 1) & KBASE_TRACE_MASK; + } + dev_dbg(kbdev->dev, "TRACE_END"); + + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + KBASE_TRACE_CLEAR(kbdev); +} + +static void kbasep_trace_hook_wrapper(void *param) +{ + struct kbase_device *kbdev = (struct kbase_device *)param; + + kbasep_trace_dump(kbdev); +} + +#ifdef CONFIG_DEBUG_FS +struct trace_seq_state { + struct kbase_trace trace_buf[KBASE_TRACE_SIZE]; + u32 start; + u32 end; +}; + +static void *kbasep_trace_seq_start(struct seq_file *s, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + if (*pos > KBASE_TRACE_SIZE) + return NULL; + i = state->start + *pos; + if ((state->end >= state->start && i >= state->end) || + i >= state->end + KBASE_TRACE_SIZE) + return NULL; + + i &= KBASE_TRACE_MASK; + + return &state->trace_buf[i]; +} + +static void kbasep_trace_seq_stop(struct seq_file *s, void *data) +{ +} + +static void *kbasep_trace_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + (*pos)++; + + i = (state->start + *pos) & KBASE_TRACE_MASK; + if (i == state->end) + return NULL; + + return &state->trace_buf[i]; +} + +static int kbasep_trace_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace *trace_msg = data; + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + seq_printf(s, "%s\n", buffer); + return 0; +} + +static const struct seq_operations kbasep_trace_seq_ops = { + .start = kbasep_trace_seq_start, + .next = kbasep_trace_seq_next, + .stop = kbasep_trace_seq_stop, + .show = kbasep_trace_seq_show, +}; + +static int kbasep_trace_debugfs_open(struct inode *inode, struct file *file) +{ + struct kbase_device *kbdev = inode->i_private; + unsigned long flags; + + struct trace_seq_state *state; + + state = __seq_open_private(file, &kbasep_trace_seq_ops, sizeof(*state)); + if (!state) + return -ENOMEM; + + spin_lock_irqsave(&kbdev->trace_lock, flags); + state->start = kbdev->trace_first_out; + state->end = kbdev->trace_next_in; + memcpy(state->trace_buf, kbdev->trace_rbuf, sizeof(state->trace_buf)); + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + return 0; +} + +static const struct file_operations kbasep_trace_debugfs_fops = { + .open = kbasep_trace_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ + debugfs_create_file("mali_trace", S_IRUGO, + kbdev->mali_debugfs_directory, kbdev, + &kbasep_trace_debugfs_fops); +} + +#else +void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#else /* KBASE_TRACE_ENABLE */ +static int kbasep_trace_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); + return 0; +} + +static void kbasep_trace_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void kbasep_trace_hook_wrapper(void *param) +{ + CSTD_UNUSED(param); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} +#endif /* KBASE_TRACE_ENABLE */ + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value) +{ + switch (control) { + case FBDUMP_CONTROL_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RATE: + /* fall through */ + case SW_COUNTER_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RESIZE_FACTOR: + kbdev->kbase_profiling_controls[control] = value; + break; + default: + dev_err(kbdev->dev, "Profiling control %d not found\n", control); + break; + } +} + +/* + * Called by gator to control the production of + * profiling information at runtime + * */ + +void _mali_profiling_control(u32 action, u32 value) +{ + struct kbase_device *kbdev = NULL; + + /* find the first i.e. call with -1 */ + kbdev = kbase_find_device(-1); + + if (NULL != kbdev) + kbase_set_profiling_control(kbdev, action, value); +} +KBASE_EXPORT_SYMBOL(_mali_profiling_control); + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_disjoint_events.c b/drivers/gpu/arm/bifrost/mali_kbase_disjoint_events.c new file mode 100644 index 000000000000..f70bcccf4050 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_disjoint_events.c @@ -0,0 +1,76 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Base kernel disjoint events helper functions + */ + +#include + +void kbase_disjoint_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_set(&kbdev->disjoint_event.count, 0); + atomic_set(&kbdev->disjoint_event.state, 0); +} + +/* increment the disjoint event count */ +void kbase_disjoint_event(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.count); +} + +/* increment the state and the event counter */ +void kbase_disjoint_state_up(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.state); + + kbase_disjoint_event(kbdev); +} + +/* decrement the state */ +void kbase_disjoint_state_down(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->disjoint_event.state) > 0); + + kbase_disjoint_event(kbdev); + + atomic_dec(&kbdev->disjoint_event.state); +} + +/* increments the count only if the state is > 0 */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + if (atomic_read(&kbdev->disjoint_event.state)) + kbase_disjoint_event(kbdev); +} + +u32 kbase_disjoint_event_get(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return atomic_read(&kbdev->disjoint_event.count); +} +KBASE_EXPORT_TEST_API(kbase_disjoint_event_get); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c new file mode 100644 index 000000000000..9197743c81d4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c @@ -0,0 +1,449 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* Include mali_kbase_dma_fence.h before checking for CONFIG_MALI_DMA_FENCE as + * it will be set there. + */ +#include "mali_kbase_dma_fence.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void +kbase_dma_fence_work(struct work_struct *pwork); + +static void +kbase_dma_fence_waiters_add(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + list_add_tail(&katom->queue, &kctx->dma_fence.waiting_resource); +} + +static void +kbase_dma_fence_waiters_remove(struct kbase_jd_atom *katom) +{ + list_del(&katom->queue); +} + +static int +kbase_dma_fence_lock_reservations(struct kbase_dma_fence_resv_info *info, + struct ww_acquire_ctx *ctx) +{ + struct reservation_object *content_res = NULL; + unsigned int content_res_idx = 0; + unsigned int r; + int err = 0; + + ww_acquire_init(ctx, &reservation_ww_class); + +retry: + for (r = 0; r < info->dma_fence_resv_count; r++) { + if (info->resv_objs[r] == content_res) { + content_res = NULL; + continue; + } + + err = ww_mutex_lock(&info->resv_objs[r]->lock, ctx); + if (err) + goto error; + } + + ww_acquire_done(ctx); + return err; + +error: + content_res_idx = r; + + /* Unlock the locked one ones */ + while (r--) + ww_mutex_unlock(&info->resv_objs[r]->lock); + + if (content_res) + ww_mutex_unlock(&content_res->lock); + + /* If we deadlock try with lock_slow and retry */ + if (err == -EDEADLK) { + content_res = info->resv_objs[content_res_idx]; + ww_mutex_lock_slow(&content_res->lock, ctx); + goto retry; + } + + /* If we are here the function failed */ + ww_acquire_fini(ctx); + return err; +} + +static void +kbase_dma_fence_unlock_reservations(struct kbase_dma_fence_resv_info *info, + struct ww_acquire_ctx *ctx) +{ + unsigned int r; + + for (r = 0; r < info->dma_fence_resv_count; r++) + ww_mutex_unlock(&info->resv_objs[r]->lock); + ww_acquire_fini(ctx); +} + +/** + * kbase_dma_fence_queue_work() - Queue work to handle @katom + * @katom: Pointer to atom for which to queue work + * + * Queue kbase_dma_fence_work() for @katom to clean up the fence callbacks and + * submit the atom. + */ +static void +kbase_dma_fence_queue_work(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + bool ret; + + INIT_WORK(&katom->work, kbase_dma_fence_work); + ret = queue_work(kctx->dma_fence.wq, &katom->work); + /* Warn if work was already queued, that should not happen. */ + WARN_ON(!ret); +} + +/** + * kbase_dma_fence_cancel_atom() - Cancels waiting on an atom + * @katom: Katom to cancel + * + * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. + */ +static void +kbase_dma_fence_cancel_atom(struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&katom->kctx->jctx.lock); + + /* Cancel callbacks and clean up. */ + kbase_fence_free_callbacks(katom); + + /* Mark the atom as handled in case all fences signaled just before + * canceling the callbacks and the worker was queued. + */ + kbase_fence_dep_count_set(katom, -1); + + /* Prevent job_done_nolock from being called twice on an atom when + * there is a race between job completion and cancellation. + */ + + if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { + /* Wait was cancelled - zap the atom */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(katom->kctx->kbdev); + } +} + +/** + * kbase_dma_fence_work() - Worker thread called when a fence is signaled + * @pwork: work_struct containing a pointer to a katom + * + * This function will clean and mark all dependencies as satisfied + */ +static void +kbase_dma_fence_work(struct work_struct *pwork) +{ + struct kbase_jd_atom *katom; + struct kbase_jd_context *ctx; + + katom = container_of(pwork, struct kbase_jd_atom, work); + ctx = &katom->kctx->jctx; + + mutex_lock(&ctx->lock); + if (kbase_fence_dep_count_read(katom) != 0) + goto out; + + kbase_fence_dep_count_set(katom, -1); + + /* Remove atom from list of dma-fence waiting atoms. */ + kbase_dma_fence_waiters_remove(katom); + /* Cleanup callbacks. */ + kbase_fence_free_callbacks(katom); + /* + * Queue atom on GPU, unless it has already completed due to a failing + * dependency. Run jd_done_nolock() on the katom if it is completed. + */ + if (unlikely(katom->status == KBASE_JD_ATOM_STATE_COMPLETED)) + jd_done_nolock(katom, NULL); + else + kbase_jd_dep_clear_locked(katom); + +out: + mutex_unlock(&ctx->lock); +} + +static void +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +kbase_dma_fence_cb(struct fence *fence, struct fence_cb *cb) +#else +kbase_dma_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb) +#endif +{ + struct kbase_fence_cb *kcb = container_of(cb, + struct kbase_fence_cb, + fence_cb); + struct kbase_jd_atom *katom = kcb->katom; + + /* If the atom is zapped dep_count will be forced to a negative number + * preventing this callback from ever scheduling work. Which in turn + * would reschedule the atom. + */ + + if (kbase_fence_dep_count_dec_and_test(katom)) + kbase_dma_fence_queue_work(katom); +} + +static int +kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom, + struct reservation_object *resv, + bool exclusive) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *excl_fence = NULL; + struct fence **shared_fences = NULL; +#else + struct dma_fence *excl_fence = NULL; + struct dma_fence **shared_fences = NULL; +#endif + unsigned int shared_count = 0; + int err, i; + + err = reservation_object_get_fences_rcu(resv, + &excl_fence, + &shared_count, + &shared_fences); + if (err) + return err; + + if (excl_fence) { + err = kbase_fence_add_callback(katom, + excl_fence, + kbase_dma_fence_cb); + + /* Release our reference, taken by reservation_object_get_fences_rcu(), + * to the fence. We have set up our callback (if that was possible), + * and it's the fence's owner is responsible for singling the fence + * before allowing it to disappear. + */ + dma_fence_put(excl_fence); + + if (err) + goto out; + } + + if (exclusive) { + for (i = 0; i < shared_count; i++) { + err = kbase_fence_add_callback(katom, + shared_fences[i], + kbase_dma_fence_cb); + if (err) + goto out; + } + } + + /* Release all our references to the shared fences, taken by + * reservation_object_get_fences_rcu(). We have set up our callback (if + * that was possible), and it's the fence's owner is responsible for + * signaling the fence before allowing it to disappear. + */ +out: + for (i = 0; i < shared_count; i++) + dma_fence_put(shared_fences[i]); + kfree(shared_fences); + + if (err) { + /* + * On error, cancel and clean up all callbacks that was set up + * before the error. + */ + kbase_fence_free_callbacks(katom); + } + + return err; +} + +void kbase_dma_fence_add_reservation(struct reservation_object *resv, + struct kbase_dma_fence_resv_info *info, + bool exclusive) +{ + unsigned int i; + + for (i = 0; i < info->dma_fence_resv_count; i++) { + /* Duplicate resource, ignore */ + if (info->resv_objs[i] == resv) + return; + } + + info->resv_objs[info->dma_fence_resv_count] = resv; + if (exclusive) + set_bit(info->dma_fence_resv_count, + info->dma_fence_excl_bitmap); + (info->dma_fence_resv_count)++; +} + +int kbase_dma_fence_wait(struct kbase_jd_atom *katom, + struct kbase_dma_fence_resv_info *info) +{ + int err, i; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + struct ww_acquire_ctx ww_ctx; + + lockdep_assert_held(&katom->kctx->jctx.lock); + + fence = kbase_fence_out_new(katom); + if (!fence) { + err = -ENOMEM; + dev_err(katom->kctx->kbdev->dev, + "Error %d creating fence.\n", err); + return err; + } + + kbase_fence_dep_count_set(katom, 1); + + err = kbase_dma_fence_lock_reservations(info, &ww_ctx); + if (err) { + dev_err(katom->kctx->kbdev->dev, + "Error %d locking reservations.\n", err); + kbase_fence_dep_count_set(katom, -1); + kbase_fence_out_remove(katom); + return err; + } + + for (i = 0; i < info->dma_fence_resv_count; i++) { + struct reservation_object *obj = info->resv_objs[i]; + + if (!test_bit(i, info->dma_fence_excl_bitmap)) { + err = reservation_object_reserve_shared(obj); + if (err) { + dev_err(katom->kctx->kbdev->dev, + "Error %d reserving space for shared fence.\n", err); + goto end; + } + + err = kbase_dma_fence_add_reservation_callback(katom, obj, false); + if (err) { + dev_err(katom->kctx->kbdev->dev, + "Error %d adding reservation to callback.\n", err); + goto end; + } + + reservation_object_add_shared_fence(obj, fence); + } else { + err = kbase_dma_fence_add_reservation_callback(katom, obj, true); + if (err) { + dev_err(katom->kctx->kbdev->dev, + "Error %d adding reservation to callback.\n", err); + goto end; + } + + reservation_object_add_excl_fence(obj, fence); + } + } + +end: + kbase_dma_fence_unlock_reservations(info, &ww_ctx); + + if (likely(!err)) { + /* Test if the callbacks are already triggered */ + if (kbase_fence_dep_count_dec_and_test(katom)) { + kbase_fence_dep_count_set(katom, -1); + kbase_fence_free_callbacks(katom); + } else { + /* Add katom to the list of dma-buf fence waiting atoms + * only if it is still waiting. + */ + kbase_dma_fence_waiters_add(katom); + } + } else { + /* There was an error, cancel callbacks, set dep_count to -1 to + * indicate that the atom has been handled (the caller will + * kill it for us), signal the fence, free callbacks and the + * fence. + */ + kbase_fence_free_callbacks(katom); + kbase_fence_dep_count_set(katom, -1); + kbase_dma_fence_signal(katom); + } + + return err; +} + +void kbase_dma_fence_cancel_all_atoms(struct kbase_context *kctx) +{ + struct list_head *list = &kctx->dma_fence.waiting_resource; + + while (!list_empty(list)) { + struct kbase_jd_atom *katom; + + katom = list_first_entry(list, struct kbase_jd_atom, queue); + kbase_dma_fence_waiters_remove(katom); + kbase_dma_fence_cancel_atom(katom); + } +} + +void kbase_dma_fence_cancel_callbacks(struct kbase_jd_atom *katom) +{ + /* Cancel callbacks and clean up. */ + if (kbase_fence_free_callbacks(katom)) + kbase_dma_fence_queue_work(katom); +} + +void kbase_dma_fence_signal(struct kbase_jd_atom *katom) +{ + if (!katom->dma_fence.fence) + return; + + /* Signal the atom's fence. */ + dma_fence_signal(katom->dma_fence.fence); + + kbase_fence_out_remove(katom); + + kbase_fence_free_callbacks(katom); +} + +void kbase_dma_fence_term(struct kbase_context *kctx) +{ + destroy_workqueue(kctx->dma_fence.wq); + kctx->dma_fence.wq = NULL; +} + +int kbase_dma_fence_init(struct kbase_context *kctx) +{ + INIT_LIST_HEAD(&kctx->dma_fence.waiting_resource); + + kctx->dma_fence.wq = alloc_workqueue("mali-fence-%d", + WQ_UNBOUND, 1, kctx->pid); + if (!kctx->dma_fence.wq) + return -ENOMEM; + + return 0; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h new file mode 100644 index 000000000000..c9ab40350422 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h @@ -0,0 +1,131 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_DMA_FENCE_H_ +#define _KBASE_DMA_FENCE_H_ + +#ifdef CONFIG_MALI_DMA_FENCE + +#include +#include +#include + + +/* Forward declaration from mali_kbase_defs.h */ +struct kbase_jd_atom; +struct kbase_context; + +/** + * struct kbase_dma_fence_resv_info - Structure with list of reservation objects + * @resv_objs: Array of reservation objects to attach the + * new fence to. + * @dma_fence_resv_count: Number of reservation objects in the array. + * @dma_fence_excl_bitmap: Specifies which resv_obj are exclusive. + * + * This is used by some functions to pass around a collection of data about + * reservation objects. + */ +struct kbase_dma_fence_resv_info { + struct reservation_object **resv_objs; + unsigned int dma_fence_resv_count; + unsigned long *dma_fence_excl_bitmap; +}; + +/** + * kbase_dma_fence_add_reservation() - Adds a resv to the array of resv_objs + * @resv: Reservation object to add to the array. + * @info: Pointer to struct with current reservation info + * @exclusive: Boolean indicating if exclusive access is needed + * + * The function adds a new reservation_object to an existing array of + * reservation_objects. At the same time keeps track of which objects require + * exclusive access in dma_fence_excl_bitmap. + */ +void kbase_dma_fence_add_reservation(struct reservation_object *resv, + struct kbase_dma_fence_resv_info *info, + bool exclusive); + +/** + * kbase_dma_fence_wait() - Creates a new fence and attaches it to the resv_objs + * @katom: Katom with the external dependency. + * @info: Pointer to struct with current reservation info + * + * Return: An error code or 0 if succeeds + */ +int kbase_dma_fence_wait(struct kbase_jd_atom *katom, + struct kbase_dma_fence_resv_info *info); + +/** + * kbase_dma_fence_cancel_ctx() - Cancel all dma-fences blocked atoms on kctx + * @kctx: Pointer to kbase context + * + * This function will cancel and clean up all katoms on @kctx that is waiting + * on dma-buf fences. + * + * Locking: jctx.lock needs to be held when calling this function. + */ +void kbase_dma_fence_cancel_all_atoms(struct kbase_context *kctx); + +/** + * kbase_dma_fence_cancel_callbacks() - Cancel only callbacks on katom + * @katom: Pointer to katom whose callbacks are to be canceled + * + * This function cancels all dma-buf fence callbacks on @katom, but does not + * cancel the katom itself. + * + * The caller is responsible for ensuring that jd_done_nolock is called on + * @katom. + * + * Locking: jctx.lock must be held when calling this function. + */ +void kbase_dma_fence_cancel_callbacks(struct kbase_jd_atom *katom); + +/** + * kbase_dma_fence_signal() - Signal katom's fence and clean up after wait + * @katom: Pointer to katom to signal and clean up + * + * This function will signal the @katom's fence, if it has one, and clean up + * the callback data from the katom's wait on earlier fences. + * + * Locking: jctx.lock must be held while calling this function. + */ +void kbase_dma_fence_signal(struct kbase_jd_atom *katom); + +/** + * kbase_dma_fence_term() - Terminate Mali dma-fence context + * @kctx: kbase context to terminate + */ +void kbase_dma_fence_term(struct kbase_context *kctx); + +/** + * kbase_dma_fence_init() - Initialize Mali dma-fence context + * @kctx: kbase context to initialize + */ +int kbase_dma_fence_init(struct kbase_context *kctx); + + +#else /* CONFIG_MALI_DMA_FENCE */ +/* Dummy functions for when dma-buf fence isn't enabled. */ + +static inline int kbase_dma_fence_init(struct kbase_context *kctx) +{ + return 0; +} + +static inline void kbase_dma_fence_term(struct kbase_context *kctx) {} +#endif /* CONFIG_MALI_DMA_FENCE */ +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_event.c b/drivers/gpu/arm/bifrost/mali_kbase_event.c new file mode 100644 index 000000000000..188148645f37 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_event.c @@ -0,0 +1,259 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +static struct base_jd_udata kbase_event_process(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct base_jd_udata data; + + lockdep_assert_held(&kctx->jctx.lock); + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + data = katom->udata; + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(1, &kctx->timeline.jd_atoms_in_flight)); + + KBASE_TLSTREAM_TL_NRET_ATOM_CTX(katom, kctx); + KBASE_TLSTREAM_TL_DEL_ATOM(katom); + + katom->status = KBASE_JD_ATOM_STATE_UNUSED; + + wake_up(&katom->completed); + + return data; +} + +int kbase_event_pending(struct kbase_context *ctx) +{ + KBASE_DEBUG_ASSERT(ctx); + + return (atomic_read(&ctx->event_count) != 0) || + (atomic_read(&ctx->event_closed) != 0); +} + +KBASE_EXPORT_TEST_API(kbase_event_pending); + +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent) +{ + struct kbase_jd_atom *atom; + + KBASE_DEBUG_ASSERT(ctx); + + mutex_lock(&ctx->event_mutex); + + if (list_empty(&ctx->event_list)) { + if (!atomic_read(&ctx->event_closed)) { + mutex_unlock(&ctx->event_mutex); + return -1; + } + + /* generate the BASE_JD_EVENT_DRV_TERMINATED message on the fly */ + mutex_unlock(&ctx->event_mutex); + uevent->event_code = BASE_JD_EVENT_DRV_TERMINATED; + memset(&uevent->udata, 0, sizeof(uevent->udata)); + dev_dbg(ctx->kbdev->dev, + "event system closed, returning BASE_JD_EVENT_DRV_TERMINATED(0x%X)\n", + BASE_JD_EVENT_DRV_TERMINATED); + return 0; + } + + /* normal event processing */ + atomic_dec(&ctx->event_count); + atom = list_entry(ctx->event_list.next, struct kbase_jd_atom, dep_item[0]); + list_del(ctx->event_list.next); + + mutex_unlock(&ctx->event_mutex); + + dev_dbg(ctx->kbdev->dev, "event dequeuing %p\n", (void *)atom); + uevent->event_code = atom->event_code; + uevent->atom_number = (atom - ctx->jctx.atoms); + + if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_free_external_resources(atom); + + mutex_lock(&ctx->jctx.lock); + uevent->udata = kbase_event_process(ctx, atom); + mutex_unlock(&ctx->jctx.lock); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_event_dequeue); + +/** + * kbase_event_process_noreport_worker - Worker for processing atoms that do not + * return an event but do have external + * resources + * @data: Work structure + */ +static void kbase_event_process_noreport_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, + work); + struct kbase_context *kctx = katom->kctx; + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_free_external_resources(katom); + + mutex_lock(&kctx->jctx.lock); + kbase_event_process(kctx, katom); + mutex_unlock(&kctx->jctx.lock); +} + +/** + * kbase_event_process_noreport - Process atoms that do not return an event + * @kctx: Context pointer + * @katom: Atom to be processed + * + * Atoms that do not have external resources will be processed immediately. + * Atoms that do have external resources will be processed on a workqueue, in + * order to avoid locking issues. + */ +static void kbase_event_process_noreport(struct kbase_context *kctx, + struct kbase_jd_atom *katom) +{ + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + INIT_WORK(&katom->work, kbase_event_process_noreport_worker); + queue_work(kctx->event_workq, &katom->work); + } else { + kbase_event_process(kctx, katom); + } +} + +/** + * kbase_event_coalesce - Move pending events to the main event list + * @kctx: Context pointer + * + * kctx->event_list and kctx->event_coalesce_count must be protected + * by a lock unless this is the last thread using them + * (and we're about to terminate the lock). + * + * Return: The number of pending events moved to the main event list + */ +static int kbase_event_coalesce(struct kbase_context *kctx) +{ + const int event_count = kctx->event_coalesce_count; + + /* Join the list of pending events onto the tail of the main list + and reset it */ + list_splice_tail_init(&kctx->event_coalesce_list, &kctx->event_list); + kctx->event_coalesce_count = 0; + + /* Return the number of events moved */ + return event_count; +} + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *atom) +{ + if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) { + if (atom->event_code == BASE_JD_EVENT_DONE) { + /* Don't report the event */ + kbase_event_process_noreport(ctx, atom); + return; + } + } + + if (atom->core_req & BASEP_JD_REQ_EVENT_NEVER) { + /* Don't report the event */ + kbase_event_process_noreport(ctx, atom); + return; + } + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(atom, TL_ATOM_STATE_POSTED); + if (atom->core_req & BASE_JD_REQ_EVENT_COALESCE) { + /* Don't report the event until other event(s) have completed */ + mutex_lock(&ctx->event_mutex); + list_add_tail(&atom->dep_item[0], &ctx->event_coalesce_list); + ++ctx->event_coalesce_count; + mutex_unlock(&ctx->event_mutex); + } else { + /* Report the event and any pending events now */ + int event_count = 1; + + mutex_lock(&ctx->event_mutex); + event_count += kbase_event_coalesce(ctx); + list_add_tail(&atom->dep_item[0], &ctx->event_list); + atomic_add(event_count, &ctx->event_count); + mutex_unlock(&ctx->event_mutex); + + kbase_event_wakeup(ctx); + } +} +KBASE_EXPORT_TEST_API(kbase_event_post); + +void kbase_event_close(struct kbase_context *kctx) +{ + mutex_lock(&kctx->event_mutex); + atomic_set(&kctx->event_closed, true); + mutex_unlock(&kctx->event_mutex); + kbase_event_wakeup(kctx); +} + +int kbase_event_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + INIT_LIST_HEAD(&kctx->event_list); + INIT_LIST_HEAD(&kctx->event_coalesce_list); + mutex_init(&kctx->event_mutex); + atomic_set(&kctx->event_count, 0); + kctx->event_coalesce_count = 0; + atomic_set(&kctx->event_closed, false); + kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1); + + if (NULL == kctx->event_workq) + return -EINVAL; + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_event_init); + +void kbase_event_cleanup(struct kbase_context *kctx) +{ + int event_count; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(kctx->event_workq); + + flush_workqueue(kctx->event_workq); + destroy_workqueue(kctx->event_workq); + + /* We use kbase_event_dequeue to remove the remaining events as that + * deals with all the cleanup needed for the atoms. + * + * Note: use of kctx->event_list without a lock is safe because this must be the last + * thread using it (because we're about to terminate the lock) + */ + event_count = kbase_event_coalesce(kctx); + atomic_add(event_count, &kctx->event_count); + + while (!list_empty(&kctx->event_list)) { + struct base_jd_event_v2 event; + + kbase_event_dequeue(kctx, &event); + } +} + +KBASE_EXPORT_TEST_API(kbase_event_cleanup); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_fence.c new file mode 100644 index 000000000000..fcb373372596 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.c @@ -0,0 +1,196 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include + +/* Spin lock protecting all Mali fences as fence->lock. */ +static DEFINE_SPINLOCK(kbase_fence_lock); + +static const char * +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +kbase_fence_get_driver_name(struct fence *fence) +#else +kbase_fence_get_driver_name(struct dma_fence *fence) +#endif +{ + return kbase_drv_name; +} + +static const char * +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +kbase_fence_get_timeline_name(struct fence *fence) +#else +kbase_fence_get_timeline_name(struct dma_fence *fence) +#endif +{ + return kbase_timeline_name; +} + +static bool +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +kbase_fence_enable_signaling(struct fence *fence) +#else +kbase_fence_enable_signaling(struct dma_fence *fence) +#endif +{ + return true; +} + +static void +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +kbase_fence_fence_value_str(struct fence *fence, char *str, int size) +#else +kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int size) +#endif +{ + snprintf(str, size, "%u", fence->seqno); +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +const struct fence_ops kbase_fence_ops = { + .wait = fence_default_wait, +#else +const struct dma_fence_ops kbase_fence_ops = { + .wait = dma_fence_default_wait, +#endif + .get_driver_name = kbase_fence_get_driver_name, + .get_timeline_name = kbase_fence_get_timeline_name, + .enable_signaling = kbase_fence_enable_signaling, + .fence_value_str = kbase_fence_fence_value_str +}; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +struct fence * +kbase_fence_out_new(struct kbase_jd_atom *katom) +#else +struct dma_fence * +kbase_fence_out_new(struct kbase_jd_atom *katom) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + + WARN_ON(katom->dma_fence.fence); + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + dma_fence_init(fence, + &kbase_fence_ops, + &kbase_fence_lock, + katom->dma_fence.context, + atomic_inc_return(&katom->dma_fence.seqno)); + + katom->dma_fence.fence = fence; + + return fence; +} + +bool +kbase_fence_free_callbacks(struct kbase_jd_atom *katom) +{ + struct kbase_fence_cb *cb, *tmp; + bool res = false; + + lockdep_assert_held(&katom->kctx->jctx.lock); + + /* Clean up and free callbacks. */ + list_for_each_entry_safe(cb, tmp, &katom->dma_fence.callbacks, node) { + bool ret; + + /* Cancel callbacks that hasn't been called yet. */ + ret = dma_fence_remove_callback(cb->fence, &cb->fence_cb); + if (ret) { + int ret; + + /* Fence had not signaled, clean up after + * canceling. + */ + ret = atomic_dec_return(&katom->dma_fence.dep_count); + + if (unlikely(ret == 0)) + res = true; + } + + /* + * Release the reference taken in + * kbase_fence_add_callback(). + */ + dma_fence_put(cb->fence); + list_del(&cb->node); + kfree(cb); + } + + return res; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +int +kbase_fence_add_callback(struct kbase_jd_atom *katom, + struct fence *fence, + fence_func_t callback) +#else +int +kbase_fence_add_callback(struct kbase_jd_atom *katom, + struct dma_fence *fence, + dma_fence_func_t callback) +#endif +{ + int err = 0; + struct kbase_fence_cb *kbase_fence_cb; + + if (!fence) + return -EINVAL; + + kbase_fence_cb = kmalloc(sizeof(*kbase_fence_cb), GFP_KERNEL); + if (!kbase_fence_cb) + return -ENOMEM; + + kbase_fence_cb->fence = fence; + kbase_fence_cb->katom = katom; + INIT_LIST_HEAD(&kbase_fence_cb->node); + + err = dma_fence_add_callback(fence, &kbase_fence_cb->fence_cb, + callback); + if (err == -ENOENT) { + /* Fence signaled, clear the error and return */ + err = 0; + kfree(kbase_fence_cb); + } else if (err) { + kfree(kbase_fence_cb); + } else { + /* + * Get reference to fence that will be kept until callback gets + * cleaned up in kbase_fence_free_callbacks(). + */ + dma_fence_get(fence); + atomic_inc(&katom->dma_fence.dep_count); + /* Add callback to katom's list of callbacks */ + list_add(&kbase_fence_cb->node, &katom->dma_fence.callbacks); + } + + return err; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_fence.h new file mode 100644 index 000000000000..f3ed025f7f6c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.h @@ -0,0 +1,270 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_FENCE_H_ +#define _KBASE_FENCE_H_ + +/* + * mali_kbase_fence.[hc] has common fence code used by both + * - CONFIG_MALI_DMA_FENCE - implicit DMA fences + * - CONFIG_SYNC_FILE - explicit fences beginning with 4.9 kernel + */ + +#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) + +#include +#include "mali_kbase_fence_defs.h" +#include "mali_kbase.h" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +extern const struct fence_ops kbase_fence_ops; +#else +extern const struct dma_fence_ops kbase_fence_ops; +#endif + +/** +* struct kbase_fence_cb - Mali dma-fence callback data struct +* @fence_cb: Callback function +* @katom: Pointer to katom that is waiting on this callback +* @fence: Pointer to the fence object on which this callback is waiting +* @node: List head for linking this callback to the katom +*/ +struct kbase_fence_cb { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence_cb fence_cb; + struct fence *fence; +#else + struct dma_fence_cb fence_cb; + struct dma_fence *fence; +#endif + struct kbase_jd_atom *katom; + struct list_head node; +}; + +/** + * kbase_fence_out_new() - Creates a new output fence and puts it on the atom + * @katom: Atom to create an output fence for + * + * return: A new fence object on success, NULL on failure. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom); +#else +struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom); +#endif + +#if defined(CONFIG_SYNC_FILE) +/** + * kbase_fence_fence_in_set() - Assign input fence to atom + * @katom: Atom to assign input fence to + * @fence: Input fence to assign to atom + * + * This function will take ownership of one fence reference! + */ +#define kbase_fence_fence_in_set(katom, fence) \ + do { \ + WARN_ON((katom)->dma_fence.fence_in); \ + (katom)->dma_fence.fence_in = fence; \ + } while (0) +#endif + +/** + * kbase_fence_out_remove() - Removes the output fence from atom + * @katom: Atom to remove output fence for + * + * This will also release the reference to this fence which the atom keeps + */ +static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom) +{ + if (katom->dma_fence.fence) { + dma_fence_put(katom->dma_fence.fence); + katom->dma_fence.fence = NULL; + } +} + +#if defined(CONFIG_SYNC_FILE) +/** + * kbase_fence_out_remove() - Removes the input fence from atom + * @katom: Atom to remove input fence for + * + * This will also release the reference to this fence which the atom keeps + */ +static inline void kbase_fence_in_remove(struct kbase_jd_atom *katom) +{ + if (katom->dma_fence.fence_in) { + dma_fence_put(katom->dma_fence.fence_in); + katom->dma_fence.fence_in = NULL; + } +} +#endif + +/** + * kbase_fence_out_is_ours() - Check if atom has a valid fence created by us + * @katom: Atom to check output fence for + * + * Return: true if fence exists and is valid, otherwise false + */ +static inline bool kbase_fence_out_is_ours(struct kbase_jd_atom *katom) +{ + return katom->dma_fence.fence && + katom->dma_fence.fence->ops == &kbase_fence_ops; +} + +/** + * kbase_fence_out_signal() - Signal output fence of atom + * @katom: Atom to signal output fence for + * @status: Status to signal with (0 for success, < 0 for error) + * + * Return: 0 on success, < 0 on error + */ +static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom, + int status) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) + katom->dma_fence.fence->error = status; +#else + katom->dma_fence.fence->status = status; +#endif + return dma_fence_signal(katom->dma_fence.fence); +} + +/** + * kbase_fence_add_callback() - Add callback on @fence to block @katom + * @katom: Pointer to katom that will be blocked by @fence + * @fence: Pointer to fence on which to set up the callback + * @callback: Pointer to function to be called when fence is signaled + * + * Caller needs to hold a reference to @fence when calling this function, and + * the caller is responsible for releasing that reference. An additional + * reference to @fence will be taken when the callback was successfully set up + * and @fence needs to be kept valid until the callback has been called and + * cleanup have been done. + * + * Return: 0 on success: fence was either already signaled, or callback was + * set up. Negative error code is returned on error. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +int kbase_fence_add_callback(struct kbase_jd_atom *katom, + struct fence *fence, + fence_func_t callback); +#else +int kbase_fence_add_callback(struct kbase_jd_atom *katom, + struct dma_fence *fence, + dma_fence_func_t callback); +#endif + +/** + * kbase_fence_dep_count_set() - Set dep_count value on atom to specified value + * @katom: Atom to set dep_count for + * @val: value to set dep_count to + * + * The dep_count is available to the users of this module so that they can + * synchronize completion of the wait with cancellation and adding of more + * callbacks. For instance, a user could do the following: + * + * dep_count set to 1 + * callback #1 added, dep_count is increased to 2 + * callback #1 happens, dep_count decremented to 1 + * since dep_count > 0, no completion is done + * callback #2 is added, dep_count is increased to 2 + * dep_count decremented to 1 + * callback #2 happens, dep_count decremented to 0 + * since dep_count now is zero, completion executes + * + * The dep_count can also be used to make sure that the completion only + * executes once. This is typically done by setting dep_count to -1 for the + * thread that takes on this responsibility. + */ +static inline void +kbase_fence_dep_count_set(struct kbase_jd_atom *katom, int val) +{ + atomic_set(&katom->dma_fence.dep_count, val); +} + +/** + * kbase_fence_dep_count_dec_and_test() - Decrements dep_count + * @katom: Atom to decrement dep_count for + * + * See @kbase_fence_dep_count_set for general description about dep_count + * + * Return: true if value was decremented to zero, otherwise false + */ +static inline bool +kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom *katom) +{ + return atomic_dec_and_test(&katom->dma_fence.dep_count); +} + +/** + * kbase_fence_dep_count_read() - Returns the current dep_count value + * @katom: Pointer to katom + * + * See @kbase_fence_dep_count_set for general description about dep_count + * + * Return: The current dep_count value + */ +static inline int kbase_fence_dep_count_read(struct kbase_jd_atom *katom) +{ + return atomic_read(&katom->dma_fence.dep_count); +} + +/** + * kbase_fence_free_callbacks() - Free dma-fence callbacks on a katom + * @katom: Pointer to katom + * + * This function will free all fence callbacks on the katom's list of + * callbacks. Callbacks that have not yet been called, because their fence + * hasn't yet signaled, will first be removed from the fence. + * + * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. + * + * Return: true if dep_count reached 0, otherwise false. + */ +bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); + +#if defined(CONFIG_SYNC_FILE) +/** + * kbase_fence_in_get() - Retrieve input fence for atom. + * @katom: Atom to get input fence from + * + * A ref will be taken for the fence, so use @kbase_fence_put() to release it + * + * Return: The fence, or NULL if there is no input fence for atom + */ +#define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in) +#endif + +/** + * kbase_fence_out_get() - Retrieve output fence for atom. + * @katom: Atom to get output fence from + * + * A ref will be taken for the fence, so use @kbase_fence_put() to release it + * + * Return: The fence, or NULL if there is no output fence for atom + */ +#define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence) + +/** + * kbase_fence_put() - Releases a reference to a fence + * @fence: Fence to release reference for. + */ +#define kbase_fence_put(fence) dma_fence_put(fence) + + +#endif /* CONFIG_MALI_DMA_FENCE || defined(CONFIG_SYNC_FILE */ + +#endif /* _KBASE_FENCE_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h new file mode 100644 index 000000000000..fa2c6dfe999e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h @@ -0,0 +1,51 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_FENCE_DEFS_H_ +#define _KBASE_FENCE_DEFS_H_ + +/* + * There was a big rename in the 4.10 kernel (fence* -> dma_fence*) + * This file hides the compatibility issues with this for the rest the driver + */ + +#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) + +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + +#include + +#define dma_fence_context_alloc(a) fence_context_alloc(a) +#define dma_fence_init(a, b, c, d, e) fence_init(a, b, c, d, e) +#define dma_fence_get(a) fence_get(a) +#define dma_fence_put(a) fence_put(a) +#define dma_fence_signal(a) fence_signal(a) +#define dma_fence_is_signaled(a) fence_is_signaled(a) +#define dma_fence_add_callback(a, b, c) fence_add_callback(a, b, c) +#define dma_fence_remove_callback(a, b) fence_remove_callback(a, b) + +#else + +#include + +#endif /* < 4.10.0 */ + +#endif /* CONFIG_MALI_DMA_FENCE || CONFIG_SYNC_FILE */ + +#endif /* _KBASE_FENCE_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator.h b/drivers/gpu/arm/bifrost/mali_kbase_gator.h new file mode 100644 index 000000000000..ce65b5562a2b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator.h @@ -0,0 +1,45 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* NB taken from gator */ +/* + * List of possible actions to be controlled by DS-5 Streamline. + * The following numbers are used by gator to control the frame buffer dumping + * and s/w counter reporting. We cannot use the enums in mali_uk_types.h because + * they are unknown inside gator. + */ +#ifndef _KBASE_GATOR_H_ +#define _KBASE_GATOR_H_ + +#ifdef CONFIG_MALI_GATOR_SUPPORT +#define GATOR_MAKE_EVENT(type, number) (((type) << 24) | ((number) << 16)) +#define GATOR_JOB_SLOT_START 1 +#define GATOR_JOB_SLOT_STOP 2 +#define GATOR_JOB_SLOT_SOFT_STOPPED 3 + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id); +void kbase_trace_mali_pm_status(u32 event, u64 value); +void kbase_trace_mali_pm_power_off(u32 event, u64 value); +void kbase_trace_mali_pm_power_on(u32 event, u64 value); +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value); +void kbase_trace_mali_mmu_as_in_use(int event); +void kbase_trace_mali_mmu_as_released(int event); +void kbase_trace_mali_total_alloc_pages_change(long long int event); + +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + +#endif /* _KBASE_GATOR_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_api.c b/drivers/gpu/arm/bifrost/mali_kbase_gator_api.c new file mode 100644 index 000000000000..860e10159fb3 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_api.c @@ -0,0 +1,334 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" +#include "mali_kbase_hw.h" +#include "mali_kbase_mem_linux.h" +#include "mali_kbase_gator_api.h" +#include "mali_kbase_gator_hwcnt_names.h" + +#define MALI_MAX_CORES_PER_GROUP 4 +#define MALI_MAX_NUM_BLOCKS_PER_GROUP 8 +#define MALI_COUNTERS_PER_BLOCK 64 +#define MALI_BYTES_PER_COUNTER 4 + +struct kbase_gator_hwcnt_handles { + struct kbase_device *kbdev; + struct kbase_vinstr_client *vinstr_cli; + void *vinstr_buffer; + struct work_struct dump_work; + int dump_complete; + spinlock_t dump_lock; +}; + +static void dump_worker(struct work_struct *work); + +const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters) +{ + const char * const *hardware_counters; + struct kbase_device *kbdev; + uint32_t product_id; + uint32_t count; + + if (!total_counters) + return NULL; + + /* Get the first device - it doesn't matter in this case */ + kbdev = kbase_find_device(-1); + if (!kbdev) + return NULL; + + product_id = kbdev->gpu_props.props.core_props.product_id; + + if (GPU_ID_IS_NEW_FORMAT(product_id)) { + switch (GPU_ID2_MODEL_MATCH_VALUE(product_id)) { + case GPU_ID2_PRODUCT_TMIX: + hardware_counters = hardware_counters_mali_tMIx; + count = ARRAY_SIZE(hardware_counters_mali_tMIx); + break; + case GPU_ID2_PRODUCT_THEX: + hardware_counters = hardware_counters_mali_tHEx; + count = ARRAY_SIZE(hardware_counters_mali_tHEx); + break; + case GPU_ID2_PRODUCT_TSIX: + hardware_counters = hardware_counters_mali_tSIx; + count = ARRAY_SIZE(hardware_counters_mali_tSIx); + break; + default: + hardware_counters = NULL; + count = 0; + dev_err(kbdev->dev, "Unrecognized product ID: %u\n", + product_id); + break; + } + } else { + switch (product_id) { + /* If we are using a Mali-T60x device */ + case GPU_ID_PI_T60X: + hardware_counters = hardware_counters_mali_t60x; + count = ARRAY_SIZE(hardware_counters_mali_t60x); + break; + /* If we are using a Mali-T62x device */ + case GPU_ID_PI_T62X: + hardware_counters = hardware_counters_mali_t62x; + count = ARRAY_SIZE(hardware_counters_mali_t62x); + break; + /* If we are using a Mali-T72x device */ + case GPU_ID_PI_T72X: + hardware_counters = hardware_counters_mali_t72x; + count = ARRAY_SIZE(hardware_counters_mali_t72x); + break; + /* If we are using a Mali-T76x device */ + case GPU_ID_PI_T76X: + hardware_counters = hardware_counters_mali_t76x; + count = ARRAY_SIZE(hardware_counters_mali_t76x); + break; + /* If we are using a Mali-T82x device */ + case GPU_ID_PI_T82X: + hardware_counters = hardware_counters_mali_t82x; + count = ARRAY_SIZE(hardware_counters_mali_t82x); + break; + /* If we are using a Mali-T83x device */ + case GPU_ID_PI_T83X: + hardware_counters = hardware_counters_mali_t83x; + count = ARRAY_SIZE(hardware_counters_mali_t83x); + break; + /* If we are using a Mali-T86x device */ + case GPU_ID_PI_T86X: + hardware_counters = hardware_counters_mali_t86x; + count = ARRAY_SIZE(hardware_counters_mali_t86x); + break; + /* If we are using a Mali-T88x device */ + case GPU_ID_PI_TFRX: + hardware_counters = hardware_counters_mali_t88x; + count = ARRAY_SIZE(hardware_counters_mali_t88x); + break; + default: + hardware_counters = NULL; + count = 0; + dev_err(kbdev->dev, "Unrecognized product ID: %u\n", + product_id); + break; + } + } + + /* Release the kbdev reference. */ + kbase_release_device(kbdev); + + *total_counters = count; + + /* If we return a string array take a reference on the module (or fail). */ + if (hardware_counters && !try_module_get(THIS_MODULE)) + return NULL; + + return hardware_counters; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names); + +void kbase_gator_hwcnt_term_names(void) +{ + /* Release the module reference. */ + module_put(THIS_MODULE); +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names); + +struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info) +{ + struct kbase_gator_hwcnt_handles *hand; + struct kbase_uk_hwcnt_reader_setup setup; + uint32_t dump_size = 0, i = 0; + + if (!in_out_info) + return NULL; + + hand = kzalloc(sizeof(*hand), GFP_KERNEL); + if (!hand) + return NULL; + + INIT_WORK(&hand->dump_work, dump_worker); + spin_lock_init(&hand->dump_lock); + + /* Get the first device */ + hand->kbdev = kbase_find_device(-1); + if (!hand->kbdev) + goto free_hand; + + dump_size = kbase_vinstr_dump_size(hand->kbdev); + hand->vinstr_buffer = kzalloc(dump_size, GFP_KERNEL); + if (!hand->vinstr_buffer) + goto release_device; + in_out_info->kernel_dump_buffer = hand->vinstr_buffer; + + in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores; + in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups; + in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id; + + /* If we are using a v4 device (Mali-T6xx or Mali-T72x) */ + if (kbase_hw_has_feature(hand->kbdev, BASE_HW_FEATURE_V4)) { + uint32_t cg, j; + uint64_t core_mask; + + /* There are 8 hardware counters blocks per core group */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + in_out_info->nr_core_groups, GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto free_vinstr_buffer; + + dump_size = in_out_info->nr_core_groups * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + MALI_COUNTERS_PER_BLOCK * + MALI_BYTES_PER_COUNTER; + + for (cg = 0; cg < in_out_info->nr_core_groups; cg++) { + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask; + + for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) { + if (core_mask & (1u << j)) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + + in_out_info->hwc_layout[i++] = TILER_BLOCK; + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + + if (0 == cg) + in_out_info->hwc_layout[i++] = JM_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + /* If we are using any other device */ + } else { + uint32_t nr_l2, nr_sc_bits, j; + uint64_t core_mask; + + nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices; + + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask; + + nr_sc_bits = fls64(core_mask); + + /* The job manager and tiler sets of counters + * are always present */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto free_vinstr_buffer; + + dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER; + + in_out_info->hwc_layout[i++] = JM_BLOCK; + in_out_info->hwc_layout[i++] = TILER_BLOCK; + + for (j = 0; j < nr_l2; j++) + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + while (core_mask != 0ull) { + if ((core_mask & 1ull) != 0ull) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + core_mask >>= 1; + } + } + + in_out_info->nr_hwc_blocks = i; + in_out_info->size = dump_size; + + setup.jm_bm = in_out_info->bitmask[0]; + setup.tiler_bm = in_out_info->bitmask[1]; + setup.shader_bm = in_out_info->bitmask[2]; + setup.mmu_l2_bm = in_out_info->bitmask[3]; + hand->vinstr_cli = kbase_vinstr_hwcnt_kernel_setup(hand->kbdev->vinstr_ctx, + &setup, hand->vinstr_buffer); + if (!hand->vinstr_cli) { + dev_err(hand->kbdev->dev, "Failed to register gator with vinstr core"); + goto free_layout; + } + + return hand; + +free_layout: + kfree(in_out_info->hwc_layout); + +free_vinstr_buffer: + kfree(hand->vinstr_buffer); + +release_device: + kbase_release_device(hand->kbdev); + +free_hand: + kfree(hand); + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init); + +void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (in_out_info) + kfree(in_out_info->hwc_layout); + + if (opaque_handles) { + cancel_work_sync(&opaque_handles->dump_work); + kbase_vinstr_detach_client(opaque_handles->vinstr_cli); + kfree(opaque_handles->vinstr_buffer); + kbase_release_device(opaque_handles->kbdev); + kfree(opaque_handles); + } +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term); + +static void dump_worker(struct work_struct *work) +{ + struct kbase_gator_hwcnt_handles *hand; + + hand = container_of(work, struct kbase_gator_hwcnt_handles, dump_work); + if (!kbase_vinstr_hwc_dump(hand->vinstr_cli, + BASE_HWCNT_READER_EVENT_MANUAL)) { + spin_lock_bh(&hand->dump_lock); + hand->dump_complete = 1; + spin_unlock_bh(&hand->dump_lock); + } else { + schedule_work(&hand->dump_work); + } +} + +uint32_t kbase_gator_instr_hwcnt_dump_complete( + struct kbase_gator_hwcnt_handles *opaque_handles, + uint32_t * const success) +{ + + if (opaque_handles && success) { + *success = opaque_handles->dump_complete; + opaque_handles->dump_complete = 0; + return *success; + } + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete); + +uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (opaque_handles) + schedule_work(&opaque_handles->dump_work); + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_api.h b/drivers/gpu/arm/bifrost/mali_kbase_gator_api.h new file mode 100644 index 000000000000..ef9ac0f7b633 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_api.h @@ -0,0 +1,219 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_API_H_ +#define _KBASE_GATOR_API_H_ + +/** + * @brief This file describes the API used by Gator to fetch hardware counters. + */ + +/* This define is used by the gator kernel module compile to select which DDK + * API calling convention to use. If not defined (legacy DDK) gator assumes + * version 1. The version to DDK release mapping is: + * Version 1 API: DDK versions r1px, r2px + * Version 2 API: DDK versions r3px, r4px + * Version 3 API: DDK version r5p0 and newer + * + * API Usage + * ========= + * + * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter + * names for the GPU present in this device. + * + * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for + * the counters you want enabled. The enables can all be set for simplicity in + * most use cases, but disabling some will let you minimize bandwidth impact. + * + * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a + * counter context. On successful return the DDK will have populated the + * structure with a variety of useful information. + * + * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a + * counter dump. If this returns a non-zero value the request has been queued, + * otherwise the driver has been unable to do so (typically because of another + * user of the instrumentation exists concurrently). + * + * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously + * requested dump has been succesful. If this returns non-zero the counter dump + * has resolved, but the value of *success must also be tested as the dump + * may have not been successful. If it returns zero the counter dump was + * abandoned due to the device being busy (typically because of another + * user of the instrumentation exists concurrently). + * + * 6] Process the counters stored in the buffer pointed to by ... + * + * kbase_gator_hwcnt_info->kernel_dump_buffer + * + * In pseudo code you can find all of the counters via this approach: + * + * + * hwcnt_info # pointer to kbase_gator_hwcnt_info structure + * hwcnt_name # pointer to name list + * + * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer + * + * # Iterate over each 64-counter block in this GPU configuration + * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { + * hwc_type type = hwcnt_info->hwc_layout[i]; + * + * # Skip reserved type blocks - they contain no counters at all + * if( type == RESERVED_BLOCK ) { + * continue; + * } + * + * size_t name_offset = type * 64; + * size_t data_offset = i * 64; + * + * # Iterate over the names of the counters in this block type + * for( j = 0; j < 64; j++) { + * const char * name = hwcnt_name[name_offset+j]; + * + * # Skip empty name strings - there is no counter here + * if( name[0] == '\0' ) { + * continue; + * } + * + * u32 data = hwcnt_data[data_offset+j]; + * + * printk( "COUNTER: %s DATA: %u\n", name, data ); + * } + * } + * + * + * Note that in most implementations you typically want to either SUM or + * AVERAGE multiple instances of the same counter if, for example, you have + * multiple shader cores or multiple L2 caches. The most sensible view for + * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU + * counters. + * + * 7] Goto 4, repeating until you want to stop collecting counters. + * + * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). + * + * 9] Release the name table resources by calling + * kbase_gator_hwcnt_term_names(). This function must only be called if + * init_names() returned a non-NULL value. + **/ + +#define MALI_DDK_GATOR_API_VERSION 3 + +enum hwc_type { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_L2_BLOCK, + RESERVED_BLOCK +}; + +struct kbase_gator_hwcnt_info { + /* Passed from Gator to kbase */ + + /* the bitmask of enabled hardware counters for each counter block */ + uint16_t bitmask[4]; + + /* Passed from kbase to Gator */ + + /* ptr to counter dump memory */ + void *kernel_dump_buffer; + + /* size of counter dump memory */ + uint32_t size; + + /* the ID of the Mali device */ + uint32_t gpu_id; + + /* the number of shader cores in the GPU */ + uint32_t nr_cores; + + /* the number of core groups */ + uint32_t nr_core_groups; + + /* the memory layout of the performance counters */ + enum hwc_type *hwc_layout; + + /* the total number of hardware couter blocks */ + uint32_t nr_hwc_blocks; +}; + +/** + * @brief Opaque block of Mali data which Gator needs to return to the API later. + */ +struct kbase_gator_hwcnt_handles; + +/** + * @brief Initialize the resources Gator needs for performance profiling. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali + * specific information that will be returned to Gator. On entry Gator must have populated the + * 'bitmask' field with the counters it wishes to enable for each class of counter block. + * Each entry in the array corresponds to a single counter class based on the "hwc_type" + * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables + * the first 4 counters in the block, and so on). See the GPU counter array as returned by + * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. + * + * @return Pointer to an opaque handle block on success, NULL on error. + */ +extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); + +/** + * @brief Free all resources once Gator has finished using performance counters. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the + * Mali specific information that will be returned to Gator. + * @param opaque_handles A wrapper structure for kbase structures. + */ +extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief Poll whether a counter dump is successful. + * + * @param opaque_handles A wrapper structure for kbase structures. + * @param[out] success Non-zero on success, zero on failure. + * + * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a + * completed dump may not have dumped succesfully, so the caller must test for both + * a completed and successful dump before processing counters. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); + +/** + * @brief Request the generation of a new counter dump. + * + * @param opaque_handles A wrapper structure for kbase structures. + * + * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief This function is used to fetch the names table based on the Mali device in use. + * + * @param[out] total_counters The total number of counters short names in the Mali devices' list. + * + * @return Pointer to an array of strings of length *total_counters. + */ +extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters); + +/** + * @brief This function is used to terminate the use of the names table. + * + * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. + */ +extern void kbase_gator_hwcnt_term_names(void); + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names.h b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names.h new file mode 100644 index 000000000000..24103e292453 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names.h @@ -0,0 +1,2167 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_HWCNT_NAMES_H_ +#define _KBASE_GATOR_HWCNT_NAMES_H_ + +/* + * "Short names" for hardware counters used by Streamline. Counters names are + * stored in accordance with their memory layout in the binary counter block + * emitted by the Mali GPU. Each "master" in the GPU emits a fixed-size block + * of 64 counters, and each GPU implements the same set of "masters" although + * the counters each master exposes within its block of 64 may vary. + * + * Counters which are an empty string are simply "holes" in the counter memory + * where no counter exists. + */ + +static const char * const hardware_counters_mali_t60x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T60x_MESSAGES_SENT", + "T60x_MESSAGES_RECEIVED", + "T60x_GPU_ACTIVE", + "T60x_IRQ_ACTIVE", + "T60x_JS0_JOBS", + "T60x_JS0_TASKS", + "T60x_JS0_ACTIVE", + "", + "T60x_JS0_WAIT_READ", + "T60x_JS0_WAIT_ISSUE", + "T60x_JS0_WAIT_DEPEND", + "T60x_JS0_WAIT_FINISH", + "T60x_JS1_JOBS", + "T60x_JS1_TASKS", + "T60x_JS1_ACTIVE", + "", + "T60x_JS1_WAIT_READ", + "T60x_JS1_WAIT_ISSUE", + "T60x_JS1_WAIT_DEPEND", + "T60x_JS1_WAIT_FINISH", + "T60x_JS2_JOBS", + "T60x_JS2_TASKS", + "T60x_JS2_ACTIVE", + "", + "T60x_JS2_WAIT_READ", + "T60x_JS2_WAIT_ISSUE", + "T60x_JS2_WAIT_DEPEND", + "T60x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T60x_TI_JOBS_PROCESSED", + "T60x_TI_TRIANGLES", + "T60x_TI_QUADS", + "T60x_TI_POLYGONS", + "T60x_TI_POINTS", + "T60x_TI_LINES", + "T60x_TI_VCACHE_HIT", + "T60x_TI_VCACHE_MISS", + "T60x_TI_FRONT_FACING", + "T60x_TI_BACK_FACING", + "T60x_TI_PRIM_VISIBLE", + "T60x_TI_PRIM_CULLED", + "T60x_TI_PRIM_CLIPPED", + "T60x_TI_LEVEL0", + "T60x_TI_LEVEL1", + "T60x_TI_LEVEL2", + "T60x_TI_LEVEL3", + "T60x_TI_LEVEL4", + "T60x_TI_LEVEL5", + "T60x_TI_LEVEL6", + "T60x_TI_LEVEL7", + "T60x_TI_COMMAND_1", + "T60x_TI_COMMAND_2", + "T60x_TI_COMMAND_3", + "T60x_TI_COMMAND_4", + "T60x_TI_COMMAND_4_7", + "T60x_TI_COMMAND_8_15", + "T60x_TI_COMMAND_16_63", + "T60x_TI_COMMAND_64", + "T60x_TI_COMPRESS_IN", + "T60x_TI_COMPRESS_OUT", + "T60x_TI_COMPRESS_FLUSH", + "T60x_TI_TIMESTAMPS", + "T60x_TI_PCACHE_HIT", + "T60x_TI_PCACHE_MISS", + "T60x_TI_PCACHE_LINE", + "T60x_TI_PCACHE_STALL", + "T60x_TI_WRBUF_HIT", + "T60x_TI_WRBUF_MISS", + "T60x_TI_WRBUF_LINE", + "T60x_TI_WRBUF_PARTIAL", + "T60x_TI_WRBUF_STALL", + "T60x_TI_ACTIVE", + "T60x_TI_LOADING_DESC", + "T60x_TI_INDEX_WAIT", + "T60x_TI_INDEX_RANGE_WAIT", + "T60x_TI_VERTEX_WAIT", + "T60x_TI_PCACHE_WAIT", + "T60x_TI_WRBUF_WAIT", + "T60x_TI_BUS_READ", + "T60x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T60x_TI_UTLB_STALL", + "T60x_TI_UTLB_REPLAY_MISS", + "T60x_TI_UTLB_REPLAY_FULL", + "T60x_TI_UTLB_NEW_MISS", + "T60x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "", + "T60x_FRAG_ACTIVE", + "T60x_FRAG_PRIMITIVES", + "T60x_FRAG_PRIMITIVES_DROPPED", + "T60x_FRAG_CYCLES_DESC", + "T60x_FRAG_CYCLES_PLR", + "T60x_FRAG_CYCLES_VERT", + "T60x_FRAG_CYCLES_TRISETUP", + "T60x_FRAG_CYCLES_RAST", + "T60x_FRAG_THREADS", + "T60x_FRAG_DUMMY_THREADS", + "T60x_FRAG_QUADS_RAST", + "T60x_FRAG_QUADS_EZS_TEST", + "T60x_FRAG_QUADS_EZS_KILLED", + "T60x_FRAG_THREADS_LZS_TEST", + "T60x_FRAG_THREADS_LZS_KILLED", + "T60x_FRAG_CYCLES_NO_TILE", + "T60x_FRAG_NUM_TILES", + "T60x_FRAG_TRANS_ELIM", + "T60x_COMPUTE_ACTIVE", + "T60x_COMPUTE_TASKS", + "T60x_COMPUTE_THREADS", + "T60x_COMPUTE_CYCLES_DESC", + "T60x_TRIPIPE_ACTIVE", + "T60x_ARITH_WORDS", + "T60x_ARITH_CYCLES_REG", + "T60x_ARITH_CYCLES_L0", + "T60x_ARITH_FRAG_DEPEND", + "T60x_LS_WORDS", + "T60x_LS_ISSUES", + "T60x_LS_RESTARTS", + "T60x_LS_REISSUES_MISS", + "T60x_LS_REISSUES_VD", + "T60x_LS_REISSUE_ATTRIB_MISS", + "T60x_LS_NO_WB", + "T60x_TEX_WORDS", + "T60x_TEX_BUBBLES", + "T60x_TEX_WORDS_L0", + "T60x_TEX_WORDS_DESC", + "T60x_TEX_ISSUES", + "T60x_TEX_RECIRC_FMISS", + "T60x_TEX_RECIRC_DESC", + "T60x_TEX_RECIRC_MULTI", + "T60x_TEX_RECIRC_PMISS", + "T60x_TEX_RECIRC_CONF", + "T60x_LSC_READ_HITS", + "T60x_LSC_READ_MISSES", + "T60x_LSC_WRITE_HITS", + "T60x_LSC_WRITE_MISSES", + "T60x_LSC_ATOMIC_HITS", + "T60x_LSC_ATOMIC_MISSES", + "T60x_LSC_LINE_FETCHES", + "T60x_LSC_DIRTY_LINE", + "T60x_LSC_SNOOPS", + "T60x_AXI_TLB_STALL", + "T60x_AXI_TLB_MISS", + "T60x_AXI_TLB_TRANSACTION", + "T60x_LS_TLB_MISS", + "T60x_LS_TLB_HIT", + "T60x_AXI_BEATS_READ", + "T60x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T60x_MMU_HIT", + "T60x_MMU_NEW_MISS", + "T60x_MMU_REPLAY_FULL", + "T60x_MMU_REPLAY_MISS", + "T60x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T60x_UTLB_HIT", + "T60x_UTLB_NEW_MISS", + "T60x_UTLB_REPLAY_FULL", + "T60x_UTLB_REPLAY_MISS", + "T60x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T60x_L2_EXT_WRITE_BEATS", + "T60x_L2_EXT_READ_BEATS", + "T60x_L2_ANY_LOOKUP", + "T60x_L2_READ_LOOKUP", + "T60x_L2_SREAD_LOOKUP", + "T60x_L2_READ_REPLAY", + "T60x_L2_READ_SNOOP", + "T60x_L2_READ_HIT", + "T60x_L2_CLEAN_MISS", + "T60x_L2_WRITE_LOOKUP", + "T60x_L2_SWRITE_LOOKUP", + "T60x_L2_WRITE_REPLAY", + "T60x_L2_WRITE_SNOOP", + "T60x_L2_WRITE_HIT", + "T60x_L2_EXT_READ_FULL", + "T60x_L2_EXT_READ_HALF", + "T60x_L2_EXT_WRITE_FULL", + "T60x_L2_EXT_WRITE_HALF", + "T60x_L2_EXT_READ", + "T60x_L2_EXT_READ_LINE", + "T60x_L2_EXT_WRITE", + "T60x_L2_EXT_WRITE_LINE", + "T60x_L2_EXT_WRITE_SMALL", + "T60x_L2_EXT_BARRIER", + "T60x_L2_EXT_AR_STALL", + "T60x_L2_EXT_R_BUF_FULL", + "T60x_L2_EXT_RD_BUF_FULL", + "T60x_L2_EXT_R_RAW", + "T60x_L2_EXT_W_STALL", + "T60x_L2_EXT_W_BUF_FULL", + "T60x_L2_EXT_R_W_HAZARD", + "T60x_L2_TAG_HAZARD", + "T60x_L2_SNOOP_FULL", + "T60x_L2_REPLAY_FULL" +}; +static const char * const hardware_counters_mali_t62x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T62x_MESSAGES_SENT", + "T62x_MESSAGES_RECEIVED", + "T62x_GPU_ACTIVE", + "T62x_IRQ_ACTIVE", + "T62x_JS0_JOBS", + "T62x_JS0_TASKS", + "T62x_JS0_ACTIVE", + "", + "T62x_JS0_WAIT_READ", + "T62x_JS0_WAIT_ISSUE", + "T62x_JS0_WAIT_DEPEND", + "T62x_JS0_WAIT_FINISH", + "T62x_JS1_JOBS", + "T62x_JS1_TASKS", + "T62x_JS1_ACTIVE", + "", + "T62x_JS1_WAIT_READ", + "T62x_JS1_WAIT_ISSUE", + "T62x_JS1_WAIT_DEPEND", + "T62x_JS1_WAIT_FINISH", + "T62x_JS2_JOBS", + "T62x_JS2_TASKS", + "T62x_JS2_ACTIVE", + "", + "T62x_JS2_WAIT_READ", + "T62x_JS2_WAIT_ISSUE", + "T62x_JS2_WAIT_DEPEND", + "T62x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T62x_TI_JOBS_PROCESSED", + "T62x_TI_TRIANGLES", + "T62x_TI_QUADS", + "T62x_TI_POLYGONS", + "T62x_TI_POINTS", + "T62x_TI_LINES", + "T62x_TI_VCACHE_HIT", + "T62x_TI_VCACHE_MISS", + "T62x_TI_FRONT_FACING", + "T62x_TI_BACK_FACING", + "T62x_TI_PRIM_VISIBLE", + "T62x_TI_PRIM_CULLED", + "T62x_TI_PRIM_CLIPPED", + "T62x_TI_LEVEL0", + "T62x_TI_LEVEL1", + "T62x_TI_LEVEL2", + "T62x_TI_LEVEL3", + "T62x_TI_LEVEL4", + "T62x_TI_LEVEL5", + "T62x_TI_LEVEL6", + "T62x_TI_LEVEL7", + "T62x_TI_COMMAND_1", + "T62x_TI_COMMAND_2", + "T62x_TI_COMMAND_3", + "T62x_TI_COMMAND_4", + "T62x_TI_COMMAND_5_7", + "T62x_TI_COMMAND_8_15", + "T62x_TI_COMMAND_16_63", + "T62x_TI_COMMAND_64", + "T62x_TI_COMPRESS_IN", + "T62x_TI_COMPRESS_OUT", + "T62x_TI_COMPRESS_FLUSH", + "T62x_TI_TIMESTAMPS", + "T62x_TI_PCACHE_HIT", + "T62x_TI_PCACHE_MISS", + "T62x_TI_PCACHE_LINE", + "T62x_TI_PCACHE_STALL", + "T62x_TI_WRBUF_HIT", + "T62x_TI_WRBUF_MISS", + "T62x_TI_WRBUF_LINE", + "T62x_TI_WRBUF_PARTIAL", + "T62x_TI_WRBUF_STALL", + "T62x_TI_ACTIVE", + "T62x_TI_LOADING_DESC", + "T62x_TI_INDEX_WAIT", + "T62x_TI_INDEX_RANGE_WAIT", + "T62x_TI_VERTEX_WAIT", + "T62x_TI_PCACHE_WAIT", + "T62x_TI_WRBUF_WAIT", + "T62x_TI_BUS_READ", + "T62x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T62x_TI_UTLB_STALL", + "T62x_TI_UTLB_REPLAY_MISS", + "T62x_TI_UTLB_REPLAY_FULL", + "T62x_TI_UTLB_NEW_MISS", + "T62x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "T62x_SHADER_CORE_ACTIVE", + "T62x_FRAG_ACTIVE", + "T62x_FRAG_PRIMITIVES", + "T62x_FRAG_PRIMITIVES_DROPPED", + "T62x_FRAG_CYCLES_DESC", + "T62x_FRAG_CYCLES_FPKQ_ACTIVE", + "T62x_FRAG_CYCLES_VERT", + "T62x_FRAG_CYCLES_TRISETUP", + "T62x_FRAG_CYCLES_EZS_ACTIVE", + "T62x_FRAG_THREADS", + "T62x_FRAG_DUMMY_THREADS", + "T62x_FRAG_QUADS_RAST", + "T62x_FRAG_QUADS_EZS_TEST", + "T62x_FRAG_QUADS_EZS_KILLED", + "T62x_FRAG_THREADS_LZS_TEST", + "T62x_FRAG_THREADS_LZS_KILLED", + "T62x_FRAG_CYCLES_NO_TILE", + "T62x_FRAG_NUM_TILES", + "T62x_FRAG_TRANS_ELIM", + "T62x_COMPUTE_ACTIVE", + "T62x_COMPUTE_TASKS", + "T62x_COMPUTE_THREADS", + "T62x_COMPUTE_CYCLES_DESC", + "T62x_TRIPIPE_ACTIVE", + "T62x_ARITH_WORDS", + "T62x_ARITH_CYCLES_REG", + "T62x_ARITH_CYCLES_L0", + "T62x_ARITH_FRAG_DEPEND", + "T62x_LS_WORDS", + "T62x_LS_ISSUES", + "T62x_LS_RESTARTS", + "T62x_LS_REISSUES_MISS", + "T62x_LS_REISSUES_VD", + "T62x_LS_REISSUE_ATTRIB_MISS", + "T62x_LS_NO_WB", + "T62x_TEX_WORDS", + "T62x_TEX_BUBBLES", + "T62x_TEX_WORDS_L0", + "T62x_TEX_WORDS_DESC", + "T62x_TEX_ISSUES", + "T62x_TEX_RECIRC_FMISS", + "T62x_TEX_RECIRC_DESC", + "T62x_TEX_RECIRC_MULTI", + "T62x_TEX_RECIRC_PMISS", + "T62x_TEX_RECIRC_CONF", + "T62x_LSC_READ_HITS", + "T62x_LSC_READ_MISSES", + "T62x_LSC_WRITE_HITS", + "T62x_LSC_WRITE_MISSES", + "T62x_LSC_ATOMIC_HITS", + "T62x_LSC_ATOMIC_MISSES", + "T62x_LSC_LINE_FETCHES", + "T62x_LSC_DIRTY_LINE", + "T62x_LSC_SNOOPS", + "T62x_AXI_TLB_STALL", + "T62x_AXI_TLB_MISS", + "T62x_AXI_TLB_TRANSACTION", + "T62x_LS_TLB_MISS", + "T62x_LS_TLB_HIT", + "T62x_AXI_BEATS_READ", + "T62x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T62x_MMU_HIT", + "T62x_MMU_NEW_MISS", + "T62x_MMU_REPLAY_FULL", + "T62x_MMU_REPLAY_MISS", + "T62x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T62x_UTLB_HIT", + "T62x_UTLB_NEW_MISS", + "T62x_UTLB_REPLAY_FULL", + "T62x_UTLB_REPLAY_MISS", + "T62x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T62x_L2_EXT_WRITE_BEATS", + "T62x_L2_EXT_READ_BEATS", + "T62x_L2_ANY_LOOKUP", + "T62x_L2_READ_LOOKUP", + "T62x_L2_SREAD_LOOKUP", + "T62x_L2_READ_REPLAY", + "T62x_L2_READ_SNOOP", + "T62x_L2_READ_HIT", + "T62x_L2_CLEAN_MISS", + "T62x_L2_WRITE_LOOKUP", + "T62x_L2_SWRITE_LOOKUP", + "T62x_L2_WRITE_REPLAY", + "T62x_L2_WRITE_SNOOP", + "T62x_L2_WRITE_HIT", + "T62x_L2_EXT_READ_FULL", + "T62x_L2_EXT_READ_HALF", + "T62x_L2_EXT_WRITE_FULL", + "T62x_L2_EXT_WRITE_HALF", + "T62x_L2_EXT_READ", + "T62x_L2_EXT_READ_LINE", + "T62x_L2_EXT_WRITE", + "T62x_L2_EXT_WRITE_LINE", + "T62x_L2_EXT_WRITE_SMALL", + "T62x_L2_EXT_BARRIER", + "T62x_L2_EXT_AR_STALL", + "T62x_L2_EXT_R_BUF_FULL", + "T62x_L2_EXT_RD_BUF_FULL", + "T62x_L2_EXT_R_RAW", + "T62x_L2_EXT_W_STALL", + "T62x_L2_EXT_W_BUF_FULL", + "T62x_L2_EXT_R_W_HAZARD", + "T62x_L2_TAG_HAZARD", + "T62x_L2_SNOOP_FULL", + "T62x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t72x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T72x_GPU_ACTIVE", + "T72x_IRQ_ACTIVE", + "T72x_JS0_JOBS", + "T72x_JS0_TASKS", + "T72x_JS0_ACTIVE", + "T72x_JS1_JOBS", + "T72x_JS1_TASKS", + "T72x_JS1_ACTIVE", + "T72x_JS2_JOBS", + "T72x_JS2_TASKS", + "T72x_JS2_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T72x_TI_JOBS_PROCESSED", + "T72x_TI_TRIANGLES", + "T72x_TI_QUADS", + "T72x_TI_POLYGONS", + "T72x_TI_POINTS", + "T72x_TI_LINES", + "T72x_TI_FRONT_FACING", + "T72x_TI_BACK_FACING", + "T72x_TI_PRIM_VISIBLE", + "T72x_TI_PRIM_CULLED", + "T72x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T72x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T72x_FRAG_ACTIVE", + "T72x_FRAG_PRIMITIVES", + "T72x_FRAG_PRIMITIVES_DROPPED", + "T72x_FRAG_THREADS", + "T72x_FRAG_DUMMY_THREADS", + "T72x_FRAG_QUADS_RAST", + "T72x_FRAG_QUADS_EZS_TEST", + "T72x_FRAG_QUADS_EZS_KILLED", + "T72x_FRAG_THREADS_LZS_TEST", + "T72x_FRAG_THREADS_LZS_KILLED", + "T72x_FRAG_CYCLES_NO_TILE", + "T72x_FRAG_NUM_TILES", + "T72x_FRAG_TRANS_ELIM", + "T72x_COMPUTE_ACTIVE", + "T72x_COMPUTE_TASKS", + "T72x_COMPUTE_THREADS", + "T72x_TRIPIPE_ACTIVE", + "T72x_ARITH_WORDS", + "T72x_ARITH_CYCLES_REG", + "T72x_LS_WORDS", + "T72x_LS_ISSUES", + "T72x_LS_RESTARTS", + "T72x_LS_REISSUES_MISS", + "T72x_TEX_WORDS", + "T72x_TEX_BUBBLES", + "T72x_TEX_ISSUES", + "T72x_LSC_READ_HITS", + "T72x_LSC_READ_MISSES", + "T72x_LSC_WRITE_HITS", + "T72x_LSC_WRITE_MISSES", + "T72x_LSC_ATOMIC_HITS", + "T72x_LSC_ATOMIC_MISSES", + "T72x_LSC_LINE_FETCHES", + "T72x_LSC_DIRTY_LINE", + "T72x_LSC_SNOOPS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*L2 and MMU */ + "", + "", + "", + "", + "T72x_L2_EXT_WRITE_BEAT", + "T72x_L2_EXT_READ_BEAT", + "T72x_L2_READ_SNOOP", + "T72x_L2_READ_HIT", + "T72x_L2_WRITE_SNOOP", + "T72x_L2_WRITE_HIT", + "T72x_L2_EXT_WRITE_SMALL", + "T72x_L2_EXT_BARRIER", + "T72x_L2_EXT_AR_STALL", + "T72x_L2_EXT_W_STALL", + "T72x_L2_SNOOP_FULL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +static const char * const hardware_counters_mali_t76x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T76x_MESSAGES_SENT", + "T76x_MESSAGES_RECEIVED", + "T76x_GPU_ACTIVE", + "T76x_IRQ_ACTIVE", + "T76x_JS0_JOBS", + "T76x_JS0_TASKS", + "T76x_JS0_ACTIVE", + "", + "T76x_JS0_WAIT_READ", + "T76x_JS0_WAIT_ISSUE", + "T76x_JS0_WAIT_DEPEND", + "T76x_JS0_WAIT_FINISH", + "T76x_JS1_JOBS", + "T76x_JS1_TASKS", + "T76x_JS1_ACTIVE", + "", + "T76x_JS1_WAIT_READ", + "T76x_JS1_WAIT_ISSUE", + "T76x_JS1_WAIT_DEPEND", + "T76x_JS1_WAIT_FINISH", + "T76x_JS2_JOBS", + "T76x_JS2_TASKS", + "T76x_JS2_ACTIVE", + "", + "T76x_JS2_WAIT_READ", + "T76x_JS2_WAIT_ISSUE", + "T76x_JS2_WAIT_DEPEND", + "T76x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T76x_TI_JOBS_PROCESSED", + "T76x_TI_TRIANGLES", + "T76x_TI_QUADS", + "T76x_TI_POLYGONS", + "T76x_TI_POINTS", + "T76x_TI_LINES", + "T76x_TI_VCACHE_HIT", + "T76x_TI_VCACHE_MISS", + "T76x_TI_FRONT_FACING", + "T76x_TI_BACK_FACING", + "T76x_TI_PRIM_VISIBLE", + "T76x_TI_PRIM_CULLED", + "T76x_TI_PRIM_CLIPPED", + "T76x_TI_LEVEL0", + "T76x_TI_LEVEL1", + "T76x_TI_LEVEL2", + "T76x_TI_LEVEL3", + "T76x_TI_LEVEL4", + "T76x_TI_LEVEL5", + "T76x_TI_LEVEL6", + "T76x_TI_LEVEL7", + "T76x_TI_COMMAND_1", + "T76x_TI_COMMAND_2", + "T76x_TI_COMMAND_3", + "T76x_TI_COMMAND_4", + "T76x_TI_COMMAND_5_7", + "T76x_TI_COMMAND_8_15", + "T76x_TI_COMMAND_16_63", + "T76x_TI_COMMAND_64", + "T76x_TI_COMPRESS_IN", + "T76x_TI_COMPRESS_OUT", + "T76x_TI_COMPRESS_FLUSH", + "T76x_TI_TIMESTAMPS", + "T76x_TI_PCACHE_HIT", + "T76x_TI_PCACHE_MISS", + "T76x_TI_PCACHE_LINE", + "T76x_TI_PCACHE_STALL", + "T76x_TI_WRBUF_HIT", + "T76x_TI_WRBUF_MISS", + "T76x_TI_WRBUF_LINE", + "T76x_TI_WRBUF_PARTIAL", + "T76x_TI_WRBUF_STALL", + "T76x_TI_ACTIVE", + "T76x_TI_LOADING_DESC", + "T76x_TI_INDEX_WAIT", + "T76x_TI_INDEX_RANGE_WAIT", + "T76x_TI_VERTEX_WAIT", + "T76x_TI_PCACHE_WAIT", + "T76x_TI_WRBUF_WAIT", + "T76x_TI_BUS_READ", + "T76x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T76x_TI_UTLB_HIT", + "T76x_TI_UTLB_NEW_MISS", + "T76x_TI_UTLB_REPLAY_FULL", + "T76x_TI_UTLB_REPLAY_MISS", + "T76x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T76x_FRAG_ACTIVE", + "T76x_FRAG_PRIMITIVES", + "T76x_FRAG_PRIMITIVES_DROPPED", + "T76x_FRAG_CYCLES_DESC", + "T76x_FRAG_CYCLES_FPKQ_ACTIVE", + "T76x_FRAG_CYCLES_VERT", + "T76x_FRAG_CYCLES_TRISETUP", + "T76x_FRAG_CYCLES_EZS_ACTIVE", + "T76x_FRAG_THREADS", + "T76x_FRAG_DUMMY_THREADS", + "T76x_FRAG_QUADS_RAST", + "T76x_FRAG_QUADS_EZS_TEST", + "T76x_FRAG_QUADS_EZS_KILLED", + "T76x_FRAG_THREADS_LZS_TEST", + "T76x_FRAG_THREADS_LZS_KILLED", + "T76x_FRAG_CYCLES_NO_TILE", + "T76x_FRAG_NUM_TILES", + "T76x_FRAG_TRANS_ELIM", + "T76x_COMPUTE_ACTIVE", + "T76x_COMPUTE_TASKS", + "T76x_COMPUTE_THREADS", + "T76x_COMPUTE_CYCLES_DESC", + "T76x_TRIPIPE_ACTIVE", + "T76x_ARITH_WORDS", + "T76x_ARITH_CYCLES_REG", + "T76x_ARITH_CYCLES_L0", + "T76x_ARITH_FRAG_DEPEND", + "T76x_LS_WORDS", + "T76x_LS_ISSUES", + "T76x_LS_REISSUE_ATTR", + "T76x_LS_REISSUES_VARY", + "T76x_LS_VARY_RV_MISS", + "T76x_LS_VARY_RV_HIT", + "T76x_LS_NO_UNPARK", + "T76x_TEX_WORDS", + "T76x_TEX_BUBBLES", + "T76x_TEX_WORDS_L0", + "T76x_TEX_WORDS_DESC", + "T76x_TEX_ISSUES", + "T76x_TEX_RECIRC_FMISS", + "T76x_TEX_RECIRC_DESC", + "T76x_TEX_RECIRC_MULTI", + "T76x_TEX_RECIRC_PMISS", + "T76x_TEX_RECIRC_CONF", + "T76x_LSC_READ_HITS", + "T76x_LSC_READ_OP", + "T76x_LSC_WRITE_HITS", + "T76x_LSC_WRITE_OP", + "T76x_LSC_ATOMIC_HITS", + "T76x_LSC_ATOMIC_OP", + "T76x_LSC_LINE_FETCHES", + "T76x_LSC_DIRTY_LINE", + "T76x_LSC_SNOOPS", + "T76x_AXI_TLB_STALL", + "T76x_AXI_TLB_MISS", + "T76x_AXI_TLB_TRANSACTION", + "T76x_LS_TLB_MISS", + "T76x_LS_TLB_HIT", + "T76x_AXI_BEATS_READ", + "T76x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T76x_MMU_HIT", + "T76x_MMU_NEW_MISS", + "T76x_MMU_REPLAY_FULL", + "T76x_MMU_REPLAY_MISS", + "T76x_MMU_TABLE_WALK", + "T76x_MMU_REQUESTS", + "", + "", + "T76x_UTLB_HIT", + "T76x_UTLB_NEW_MISS", + "T76x_UTLB_REPLAY_FULL", + "T76x_UTLB_REPLAY_MISS", + "T76x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T76x_L2_EXT_WRITE_BEATS", + "T76x_L2_EXT_READ_BEATS", + "T76x_L2_ANY_LOOKUP", + "T76x_L2_READ_LOOKUP", + "T76x_L2_SREAD_LOOKUP", + "T76x_L2_READ_REPLAY", + "T76x_L2_READ_SNOOP", + "T76x_L2_READ_HIT", + "T76x_L2_CLEAN_MISS", + "T76x_L2_WRITE_LOOKUP", + "T76x_L2_SWRITE_LOOKUP", + "T76x_L2_WRITE_REPLAY", + "T76x_L2_WRITE_SNOOP", + "T76x_L2_WRITE_HIT", + "T76x_L2_EXT_READ_FULL", + "", + "T76x_L2_EXT_WRITE_FULL", + "T76x_L2_EXT_R_W_HAZARD", + "T76x_L2_EXT_READ", + "T76x_L2_EXT_READ_LINE", + "T76x_L2_EXT_WRITE", + "T76x_L2_EXT_WRITE_LINE", + "T76x_L2_EXT_WRITE_SMALL", + "T76x_L2_EXT_BARRIER", + "T76x_L2_EXT_AR_STALL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_EXT_RD_BUF_FULL", + "T76x_L2_EXT_R_RAW", + "T76x_L2_EXT_W_STALL", + "T76x_L2_EXT_W_BUF_FULL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_TAG_HAZARD", + "T76x_L2_SNOOP_FULL", + "T76x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t82x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T82x_MESSAGES_SENT", + "T82x_MESSAGES_RECEIVED", + "T82x_GPU_ACTIVE", + "T82x_IRQ_ACTIVE", + "T82x_JS0_JOBS", + "T82x_JS0_TASKS", + "T82x_JS0_ACTIVE", + "", + "T82x_JS0_WAIT_READ", + "T82x_JS0_WAIT_ISSUE", + "T82x_JS0_WAIT_DEPEND", + "T82x_JS0_WAIT_FINISH", + "T82x_JS1_JOBS", + "T82x_JS1_TASKS", + "T82x_JS1_ACTIVE", + "", + "T82x_JS1_WAIT_READ", + "T82x_JS1_WAIT_ISSUE", + "T82x_JS1_WAIT_DEPEND", + "T82x_JS1_WAIT_FINISH", + "T82x_JS2_JOBS", + "T82x_JS2_TASKS", + "T82x_JS2_ACTIVE", + "", + "T82x_JS2_WAIT_READ", + "T82x_JS2_WAIT_ISSUE", + "T82x_JS2_WAIT_DEPEND", + "T82x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T82x_TI_JOBS_PROCESSED", + "T82x_TI_TRIANGLES", + "T82x_TI_QUADS", + "T82x_TI_POLYGONS", + "T82x_TI_POINTS", + "T82x_TI_LINES", + "T82x_TI_FRONT_FACING", + "T82x_TI_BACK_FACING", + "T82x_TI_PRIM_VISIBLE", + "T82x_TI_PRIM_CULLED", + "T82x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T82x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T82x_FRAG_ACTIVE", + "T82x_FRAG_PRIMITIVES", + "T82x_FRAG_PRIMITIVES_DROPPED", + "T82x_FRAG_CYCLES_DESC", + "T82x_FRAG_CYCLES_FPKQ_ACTIVE", + "T82x_FRAG_CYCLES_VERT", + "T82x_FRAG_CYCLES_TRISETUP", + "T82x_FRAG_CYCLES_EZS_ACTIVE", + "T82x_FRAG_THREADS", + "T82x_FRAG_DUMMY_THREADS", + "T82x_FRAG_QUADS_RAST", + "T82x_FRAG_QUADS_EZS_TEST", + "T82x_FRAG_QUADS_EZS_KILLED", + "T82x_FRAG_THREADS_LZS_TEST", + "T82x_FRAG_THREADS_LZS_KILLED", + "T82x_FRAG_CYCLES_NO_TILE", + "T82x_FRAG_NUM_TILES", + "T82x_FRAG_TRANS_ELIM", + "T82x_COMPUTE_ACTIVE", + "T82x_COMPUTE_TASKS", + "T82x_COMPUTE_THREADS", + "T82x_COMPUTE_CYCLES_DESC", + "T82x_TRIPIPE_ACTIVE", + "T82x_ARITH_WORDS", + "T82x_ARITH_CYCLES_REG", + "T82x_ARITH_CYCLES_L0", + "T82x_ARITH_FRAG_DEPEND", + "T82x_LS_WORDS", + "T82x_LS_ISSUES", + "T82x_LS_REISSUE_ATTR", + "T82x_LS_REISSUES_VARY", + "T82x_LS_VARY_RV_MISS", + "T82x_LS_VARY_RV_HIT", + "T82x_LS_NO_UNPARK", + "T82x_TEX_WORDS", + "T82x_TEX_BUBBLES", + "T82x_TEX_WORDS_L0", + "T82x_TEX_WORDS_DESC", + "T82x_TEX_ISSUES", + "T82x_TEX_RECIRC_FMISS", + "T82x_TEX_RECIRC_DESC", + "T82x_TEX_RECIRC_MULTI", + "T82x_TEX_RECIRC_PMISS", + "T82x_TEX_RECIRC_CONF", + "T82x_LSC_READ_HITS", + "T82x_LSC_READ_OP", + "T82x_LSC_WRITE_HITS", + "T82x_LSC_WRITE_OP", + "T82x_LSC_ATOMIC_HITS", + "T82x_LSC_ATOMIC_OP", + "T82x_LSC_LINE_FETCHES", + "T82x_LSC_DIRTY_LINE", + "T82x_LSC_SNOOPS", + "T82x_AXI_TLB_STALL", + "T82x_AXI_TLB_MISS", + "T82x_AXI_TLB_TRANSACTION", + "T82x_LS_TLB_MISS", + "T82x_LS_TLB_HIT", + "T82x_AXI_BEATS_READ", + "T82x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T82x_MMU_HIT", + "T82x_MMU_NEW_MISS", + "T82x_MMU_REPLAY_FULL", + "T82x_MMU_REPLAY_MISS", + "T82x_MMU_TABLE_WALK", + "T82x_MMU_REQUESTS", + "", + "", + "T82x_UTLB_HIT", + "T82x_UTLB_NEW_MISS", + "T82x_UTLB_REPLAY_FULL", + "T82x_UTLB_REPLAY_MISS", + "T82x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T82x_L2_EXT_WRITE_BEATS", + "T82x_L2_EXT_READ_BEATS", + "T82x_L2_ANY_LOOKUP", + "T82x_L2_READ_LOOKUP", + "T82x_L2_SREAD_LOOKUP", + "T82x_L2_READ_REPLAY", + "T82x_L2_READ_SNOOP", + "T82x_L2_READ_HIT", + "T82x_L2_CLEAN_MISS", + "T82x_L2_WRITE_LOOKUP", + "T82x_L2_SWRITE_LOOKUP", + "T82x_L2_WRITE_REPLAY", + "T82x_L2_WRITE_SNOOP", + "T82x_L2_WRITE_HIT", + "T82x_L2_EXT_READ_FULL", + "", + "T82x_L2_EXT_WRITE_FULL", + "T82x_L2_EXT_R_W_HAZARD", + "T82x_L2_EXT_READ", + "T82x_L2_EXT_READ_LINE", + "T82x_L2_EXT_WRITE", + "T82x_L2_EXT_WRITE_LINE", + "T82x_L2_EXT_WRITE_SMALL", + "T82x_L2_EXT_BARRIER", + "T82x_L2_EXT_AR_STALL", + "T82x_L2_EXT_R_BUF_FULL", + "T82x_L2_EXT_RD_BUF_FULL", + "T82x_L2_EXT_R_RAW", + "T82x_L2_EXT_W_STALL", + "T82x_L2_EXT_W_BUF_FULL", + "T82x_L2_EXT_R_BUF_FULL", + "T82x_L2_TAG_HAZARD", + "T82x_L2_SNOOP_FULL", + "T82x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t83x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T83x_MESSAGES_SENT", + "T83x_MESSAGES_RECEIVED", + "T83x_GPU_ACTIVE", + "T83x_IRQ_ACTIVE", + "T83x_JS0_JOBS", + "T83x_JS0_TASKS", + "T83x_JS0_ACTIVE", + "", + "T83x_JS0_WAIT_READ", + "T83x_JS0_WAIT_ISSUE", + "T83x_JS0_WAIT_DEPEND", + "T83x_JS0_WAIT_FINISH", + "T83x_JS1_JOBS", + "T83x_JS1_TASKS", + "T83x_JS1_ACTIVE", + "", + "T83x_JS1_WAIT_READ", + "T83x_JS1_WAIT_ISSUE", + "T83x_JS1_WAIT_DEPEND", + "T83x_JS1_WAIT_FINISH", + "T83x_JS2_JOBS", + "T83x_JS2_TASKS", + "T83x_JS2_ACTIVE", + "", + "T83x_JS2_WAIT_READ", + "T83x_JS2_WAIT_ISSUE", + "T83x_JS2_WAIT_DEPEND", + "T83x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T83x_TI_JOBS_PROCESSED", + "T83x_TI_TRIANGLES", + "T83x_TI_QUADS", + "T83x_TI_POLYGONS", + "T83x_TI_POINTS", + "T83x_TI_LINES", + "T83x_TI_FRONT_FACING", + "T83x_TI_BACK_FACING", + "T83x_TI_PRIM_VISIBLE", + "T83x_TI_PRIM_CULLED", + "T83x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T83x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T83x_FRAG_ACTIVE", + "T83x_FRAG_PRIMITIVES", + "T83x_FRAG_PRIMITIVES_DROPPED", + "T83x_FRAG_CYCLES_DESC", + "T83x_FRAG_CYCLES_FPKQ_ACTIVE", + "T83x_FRAG_CYCLES_VERT", + "T83x_FRAG_CYCLES_TRISETUP", + "T83x_FRAG_CYCLES_EZS_ACTIVE", + "T83x_FRAG_THREADS", + "T83x_FRAG_DUMMY_THREADS", + "T83x_FRAG_QUADS_RAST", + "T83x_FRAG_QUADS_EZS_TEST", + "T83x_FRAG_QUADS_EZS_KILLED", + "T83x_FRAG_THREADS_LZS_TEST", + "T83x_FRAG_THREADS_LZS_KILLED", + "T83x_FRAG_CYCLES_NO_TILE", + "T83x_FRAG_NUM_TILES", + "T83x_FRAG_TRANS_ELIM", + "T83x_COMPUTE_ACTIVE", + "T83x_COMPUTE_TASKS", + "T83x_COMPUTE_THREADS", + "T83x_COMPUTE_CYCLES_DESC", + "T83x_TRIPIPE_ACTIVE", + "T83x_ARITH_WORDS", + "T83x_ARITH_CYCLES_REG", + "T83x_ARITH_CYCLES_L0", + "T83x_ARITH_FRAG_DEPEND", + "T83x_LS_WORDS", + "T83x_LS_ISSUES", + "T83x_LS_REISSUE_ATTR", + "T83x_LS_REISSUES_VARY", + "T83x_LS_VARY_RV_MISS", + "T83x_LS_VARY_RV_HIT", + "T83x_LS_NO_UNPARK", + "T83x_TEX_WORDS", + "T83x_TEX_BUBBLES", + "T83x_TEX_WORDS_L0", + "T83x_TEX_WORDS_DESC", + "T83x_TEX_ISSUES", + "T83x_TEX_RECIRC_FMISS", + "T83x_TEX_RECIRC_DESC", + "T83x_TEX_RECIRC_MULTI", + "T83x_TEX_RECIRC_PMISS", + "T83x_TEX_RECIRC_CONF", + "T83x_LSC_READ_HITS", + "T83x_LSC_READ_OP", + "T83x_LSC_WRITE_HITS", + "T83x_LSC_WRITE_OP", + "T83x_LSC_ATOMIC_HITS", + "T83x_LSC_ATOMIC_OP", + "T83x_LSC_LINE_FETCHES", + "T83x_LSC_DIRTY_LINE", + "T83x_LSC_SNOOPS", + "T83x_AXI_TLB_STALL", + "T83x_AXI_TLB_MISS", + "T83x_AXI_TLB_TRANSACTION", + "T83x_LS_TLB_MISS", + "T83x_LS_TLB_HIT", + "T83x_AXI_BEATS_READ", + "T83x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T83x_MMU_HIT", + "T83x_MMU_NEW_MISS", + "T83x_MMU_REPLAY_FULL", + "T83x_MMU_REPLAY_MISS", + "T83x_MMU_TABLE_WALK", + "T83x_MMU_REQUESTS", + "", + "", + "T83x_UTLB_HIT", + "T83x_UTLB_NEW_MISS", + "T83x_UTLB_REPLAY_FULL", + "T83x_UTLB_REPLAY_MISS", + "T83x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T83x_L2_EXT_WRITE_BEATS", + "T83x_L2_EXT_READ_BEATS", + "T83x_L2_ANY_LOOKUP", + "T83x_L2_READ_LOOKUP", + "T83x_L2_SREAD_LOOKUP", + "T83x_L2_READ_REPLAY", + "T83x_L2_READ_SNOOP", + "T83x_L2_READ_HIT", + "T83x_L2_CLEAN_MISS", + "T83x_L2_WRITE_LOOKUP", + "T83x_L2_SWRITE_LOOKUP", + "T83x_L2_WRITE_REPLAY", + "T83x_L2_WRITE_SNOOP", + "T83x_L2_WRITE_HIT", + "T83x_L2_EXT_READ_FULL", + "", + "T83x_L2_EXT_WRITE_FULL", + "T83x_L2_EXT_R_W_HAZARD", + "T83x_L2_EXT_READ", + "T83x_L2_EXT_READ_LINE", + "T83x_L2_EXT_WRITE", + "T83x_L2_EXT_WRITE_LINE", + "T83x_L2_EXT_WRITE_SMALL", + "T83x_L2_EXT_BARRIER", + "T83x_L2_EXT_AR_STALL", + "T83x_L2_EXT_R_BUF_FULL", + "T83x_L2_EXT_RD_BUF_FULL", + "T83x_L2_EXT_R_RAW", + "T83x_L2_EXT_W_STALL", + "T83x_L2_EXT_W_BUF_FULL", + "T83x_L2_EXT_R_BUF_FULL", + "T83x_L2_TAG_HAZARD", + "T83x_L2_SNOOP_FULL", + "T83x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t86x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T86x_MESSAGES_SENT", + "T86x_MESSAGES_RECEIVED", + "T86x_GPU_ACTIVE", + "T86x_IRQ_ACTIVE", + "T86x_JS0_JOBS", + "T86x_JS0_TASKS", + "T86x_JS0_ACTIVE", + "", + "T86x_JS0_WAIT_READ", + "T86x_JS0_WAIT_ISSUE", + "T86x_JS0_WAIT_DEPEND", + "T86x_JS0_WAIT_FINISH", + "T86x_JS1_JOBS", + "T86x_JS1_TASKS", + "T86x_JS1_ACTIVE", + "", + "T86x_JS1_WAIT_READ", + "T86x_JS1_WAIT_ISSUE", + "T86x_JS1_WAIT_DEPEND", + "T86x_JS1_WAIT_FINISH", + "T86x_JS2_JOBS", + "T86x_JS2_TASKS", + "T86x_JS2_ACTIVE", + "", + "T86x_JS2_WAIT_READ", + "T86x_JS2_WAIT_ISSUE", + "T86x_JS2_WAIT_DEPEND", + "T86x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T86x_TI_JOBS_PROCESSED", + "T86x_TI_TRIANGLES", + "T86x_TI_QUADS", + "T86x_TI_POLYGONS", + "T86x_TI_POINTS", + "T86x_TI_LINES", + "T86x_TI_VCACHE_HIT", + "T86x_TI_VCACHE_MISS", + "T86x_TI_FRONT_FACING", + "T86x_TI_BACK_FACING", + "T86x_TI_PRIM_VISIBLE", + "T86x_TI_PRIM_CULLED", + "T86x_TI_PRIM_CLIPPED", + "T86x_TI_LEVEL0", + "T86x_TI_LEVEL1", + "T86x_TI_LEVEL2", + "T86x_TI_LEVEL3", + "T86x_TI_LEVEL4", + "T86x_TI_LEVEL5", + "T86x_TI_LEVEL6", + "T86x_TI_LEVEL7", + "T86x_TI_COMMAND_1", + "T86x_TI_COMMAND_2", + "T86x_TI_COMMAND_3", + "T86x_TI_COMMAND_4", + "T86x_TI_COMMAND_5_7", + "T86x_TI_COMMAND_8_15", + "T86x_TI_COMMAND_16_63", + "T86x_TI_COMMAND_64", + "T86x_TI_COMPRESS_IN", + "T86x_TI_COMPRESS_OUT", + "T86x_TI_COMPRESS_FLUSH", + "T86x_TI_TIMESTAMPS", + "T86x_TI_PCACHE_HIT", + "T86x_TI_PCACHE_MISS", + "T86x_TI_PCACHE_LINE", + "T86x_TI_PCACHE_STALL", + "T86x_TI_WRBUF_HIT", + "T86x_TI_WRBUF_MISS", + "T86x_TI_WRBUF_LINE", + "T86x_TI_WRBUF_PARTIAL", + "T86x_TI_WRBUF_STALL", + "T86x_TI_ACTIVE", + "T86x_TI_LOADING_DESC", + "T86x_TI_INDEX_WAIT", + "T86x_TI_INDEX_RANGE_WAIT", + "T86x_TI_VERTEX_WAIT", + "T86x_TI_PCACHE_WAIT", + "T86x_TI_WRBUF_WAIT", + "T86x_TI_BUS_READ", + "T86x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T86x_TI_UTLB_HIT", + "T86x_TI_UTLB_NEW_MISS", + "T86x_TI_UTLB_REPLAY_FULL", + "T86x_TI_UTLB_REPLAY_MISS", + "T86x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T86x_FRAG_ACTIVE", + "T86x_FRAG_PRIMITIVES", + "T86x_FRAG_PRIMITIVES_DROPPED", + "T86x_FRAG_CYCLES_DESC", + "T86x_FRAG_CYCLES_FPKQ_ACTIVE", + "T86x_FRAG_CYCLES_VERT", + "T86x_FRAG_CYCLES_TRISETUP", + "T86x_FRAG_CYCLES_EZS_ACTIVE", + "T86x_FRAG_THREADS", + "T86x_FRAG_DUMMY_THREADS", + "T86x_FRAG_QUADS_RAST", + "T86x_FRAG_QUADS_EZS_TEST", + "T86x_FRAG_QUADS_EZS_KILLED", + "T86x_FRAG_THREADS_LZS_TEST", + "T86x_FRAG_THREADS_LZS_KILLED", + "T86x_FRAG_CYCLES_NO_TILE", + "T86x_FRAG_NUM_TILES", + "T86x_FRAG_TRANS_ELIM", + "T86x_COMPUTE_ACTIVE", + "T86x_COMPUTE_TASKS", + "T86x_COMPUTE_THREADS", + "T86x_COMPUTE_CYCLES_DESC", + "T86x_TRIPIPE_ACTIVE", + "T86x_ARITH_WORDS", + "T86x_ARITH_CYCLES_REG", + "T86x_ARITH_CYCLES_L0", + "T86x_ARITH_FRAG_DEPEND", + "T86x_LS_WORDS", + "T86x_LS_ISSUES", + "T86x_LS_REISSUE_ATTR", + "T86x_LS_REISSUES_VARY", + "T86x_LS_VARY_RV_MISS", + "T86x_LS_VARY_RV_HIT", + "T86x_LS_NO_UNPARK", + "T86x_TEX_WORDS", + "T86x_TEX_BUBBLES", + "T86x_TEX_WORDS_L0", + "T86x_TEX_WORDS_DESC", + "T86x_TEX_ISSUES", + "T86x_TEX_RECIRC_FMISS", + "T86x_TEX_RECIRC_DESC", + "T86x_TEX_RECIRC_MULTI", + "T86x_TEX_RECIRC_PMISS", + "T86x_TEX_RECIRC_CONF", + "T86x_LSC_READ_HITS", + "T86x_LSC_READ_OP", + "T86x_LSC_WRITE_HITS", + "T86x_LSC_WRITE_OP", + "T86x_LSC_ATOMIC_HITS", + "T86x_LSC_ATOMIC_OP", + "T86x_LSC_LINE_FETCHES", + "T86x_LSC_DIRTY_LINE", + "T86x_LSC_SNOOPS", + "T86x_AXI_TLB_STALL", + "T86x_AXI_TLB_MISS", + "T86x_AXI_TLB_TRANSACTION", + "T86x_LS_TLB_MISS", + "T86x_LS_TLB_HIT", + "T86x_AXI_BEATS_READ", + "T86x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T86x_MMU_HIT", + "T86x_MMU_NEW_MISS", + "T86x_MMU_REPLAY_FULL", + "T86x_MMU_REPLAY_MISS", + "T86x_MMU_TABLE_WALK", + "T86x_MMU_REQUESTS", + "", + "", + "T86x_UTLB_HIT", + "T86x_UTLB_NEW_MISS", + "T86x_UTLB_REPLAY_FULL", + "T86x_UTLB_REPLAY_MISS", + "T86x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T86x_L2_EXT_WRITE_BEATS", + "T86x_L2_EXT_READ_BEATS", + "T86x_L2_ANY_LOOKUP", + "T86x_L2_READ_LOOKUP", + "T86x_L2_SREAD_LOOKUP", + "T86x_L2_READ_REPLAY", + "T86x_L2_READ_SNOOP", + "T86x_L2_READ_HIT", + "T86x_L2_CLEAN_MISS", + "T86x_L2_WRITE_LOOKUP", + "T86x_L2_SWRITE_LOOKUP", + "T86x_L2_WRITE_REPLAY", + "T86x_L2_WRITE_SNOOP", + "T86x_L2_WRITE_HIT", + "T86x_L2_EXT_READ_FULL", + "", + "T86x_L2_EXT_WRITE_FULL", + "T86x_L2_EXT_R_W_HAZARD", + "T86x_L2_EXT_READ", + "T86x_L2_EXT_READ_LINE", + "T86x_L2_EXT_WRITE", + "T86x_L2_EXT_WRITE_LINE", + "T86x_L2_EXT_WRITE_SMALL", + "T86x_L2_EXT_BARRIER", + "T86x_L2_EXT_AR_STALL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_EXT_RD_BUF_FULL", + "T86x_L2_EXT_R_RAW", + "T86x_L2_EXT_W_STALL", + "T86x_L2_EXT_W_BUF_FULL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_TAG_HAZARD", + "T86x_L2_SNOOP_FULL", + "T86x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t88x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T88x_MESSAGES_SENT", + "T88x_MESSAGES_RECEIVED", + "T88x_GPU_ACTIVE", + "T88x_IRQ_ACTIVE", + "T88x_JS0_JOBS", + "T88x_JS0_TASKS", + "T88x_JS0_ACTIVE", + "", + "T88x_JS0_WAIT_READ", + "T88x_JS0_WAIT_ISSUE", + "T88x_JS0_WAIT_DEPEND", + "T88x_JS0_WAIT_FINISH", + "T88x_JS1_JOBS", + "T88x_JS1_TASKS", + "T88x_JS1_ACTIVE", + "", + "T88x_JS1_WAIT_READ", + "T88x_JS1_WAIT_ISSUE", + "T88x_JS1_WAIT_DEPEND", + "T88x_JS1_WAIT_FINISH", + "T88x_JS2_JOBS", + "T88x_JS2_TASKS", + "T88x_JS2_ACTIVE", + "", + "T88x_JS2_WAIT_READ", + "T88x_JS2_WAIT_ISSUE", + "T88x_JS2_WAIT_DEPEND", + "T88x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T88x_TI_JOBS_PROCESSED", + "T88x_TI_TRIANGLES", + "T88x_TI_QUADS", + "T88x_TI_POLYGONS", + "T88x_TI_POINTS", + "T88x_TI_LINES", + "T88x_TI_VCACHE_HIT", + "T88x_TI_VCACHE_MISS", + "T88x_TI_FRONT_FACING", + "T88x_TI_BACK_FACING", + "T88x_TI_PRIM_VISIBLE", + "T88x_TI_PRIM_CULLED", + "T88x_TI_PRIM_CLIPPED", + "T88x_TI_LEVEL0", + "T88x_TI_LEVEL1", + "T88x_TI_LEVEL2", + "T88x_TI_LEVEL3", + "T88x_TI_LEVEL4", + "T88x_TI_LEVEL5", + "T88x_TI_LEVEL6", + "T88x_TI_LEVEL7", + "T88x_TI_COMMAND_1", + "T88x_TI_COMMAND_2", + "T88x_TI_COMMAND_3", + "T88x_TI_COMMAND_4", + "T88x_TI_COMMAND_5_7", + "T88x_TI_COMMAND_8_15", + "T88x_TI_COMMAND_16_63", + "T88x_TI_COMMAND_64", + "T88x_TI_COMPRESS_IN", + "T88x_TI_COMPRESS_OUT", + "T88x_TI_COMPRESS_FLUSH", + "T88x_TI_TIMESTAMPS", + "T88x_TI_PCACHE_HIT", + "T88x_TI_PCACHE_MISS", + "T88x_TI_PCACHE_LINE", + "T88x_TI_PCACHE_STALL", + "T88x_TI_WRBUF_HIT", + "T88x_TI_WRBUF_MISS", + "T88x_TI_WRBUF_LINE", + "T88x_TI_WRBUF_PARTIAL", + "T88x_TI_WRBUF_STALL", + "T88x_TI_ACTIVE", + "T88x_TI_LOADING_DESC", + "T88x_TI_INDEX_WAIT", + "T88x_TI_INDEX_RANGE_WAIT", + "T88x_TI_VERTEX_WAIT", + "T88x_TI_PCACHE_WAIT", + "T88x_TI_WRBUF_WAIT", + "T88x_TI_BUS_READ", + "T88x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T88x_TI_UTLB_HIT", + "T88x_TI_UTLB_NEW_MISS", + "T88x_TI_UTLB_REPLAY_FULL", + "T88x_TI_UTLB_REPLAY_MISS", + "T88x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T88x_FRAG_ACTIVE", + "T88x_FRAG_PRIMITIVES", + "T88x_FRAG_PRIMITIVES_DROPPED", + "T88x_FRAG_CYCLES_DESC", + "T88x_FRAG_CYCLES_FPKQ_ACTIVE", + "T88x_FRAG_CYCLES_VERT", + "T88x_FRAG_CYCLES_TRISETUP", + "T88x_FRAG_CYCLES_EZS_ACTIVE", + "T88x_FRAG_THREADS", + "T88x_FRAG_DUMMY_THREADS", + "T88x_FRAG_QUADS_RAST", + "T88x_FRAG_QUADS_EZS_TEST", + "T88x_FRAG_QUADS_EZS_KILLED", + "T88x_FRAG_THREADS_LZS_TEST", + "T88x_FRAG_THREADS_LZS_KILLED", + "T88x_FRAG_CYCLES_NO_TILE", + "T88x_FRAG_NUM_TILES", + "T88x_FRAG_TRANS_ELIM", + "T88x_COMPUTE_ACTIVE", + "T88x_COMPUTE_TASKS", + "T88x_COMPUTE_THREADS", + "T88x_COMPUTE_CYCLES_DESC", + "T88x_TRIPIPE_ACTIVE", + "T88x_ARITH_WORDS", + "T88x_ARITH_CYCLES_REG", + "T88x_ARITH_CYCLES_L0", + "T88x_ARITH_FRAG_DEPEND", + "T88x_LS_WORDS", + "T88x_LS_ISSUES", + "T88x_LS_REISSUE_ATTR", + "T88x_LS_REISSUES_VARY", + "T88x_LS_VARY_RV_MISS", + "T88x_LS_VARY_RV_HIT", + "T88x_LS_NO_UNPARK", + "T88x_TEX_WORDS", + "T88x_TEX_BUBBLES", + "T88x_TEX_WORDS_L0", + "T88x_TEX_WORDS_DESC", + "T88x_TEX_ISSUES", + "T88x_TEX_RECIRC_FMISS", + "T88x_TEX_RECIRC_DESC", + "T88x_TEX_RECIRC_MULTI", + "T88x_TEX_RECIRC_PMISS", + "T88x_TEX_RECIRC_CONF", + "T88x_LSC_READ_HITS", + "T88x_LSC_READ_OP", + "T88x_LSC_WRITE_HITS", + "T88x_LSC_WRITE_OP", + "T88x_LSC_ATOMIC_HITS", + "T88x_LSC_ATOMIC_OP", + "T88x_LSC_LINE_FETCHES", + "T88x_LSC_DIRTY_LINE", + "T88x_LSC_SNOOPS", + "T88x_AXI_TLB_STALL", + "T88x_AXI_TLB_MISS", + "T88x_AXI_TLB_TRANSACTION", + "T88x_LS_TLB_MISS", + "T88x_LS_TLB_HIT", + "T88x_AXI_BEATS_READ", + "T88x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T88x_MMU_HIT", + "T88x_MMU_NEW_MISS", + "T88x_MMU_REPLAY_FULL", + "T88x_MMU_REPLAY_MISS", + "T88x_MMU_TABLE_WALK", + "T88x_MMU_REQUESTS", + "", + "", + "T88x_UTLB_HIT", + "T88x_UTLB_NEW_MISS", + "T88x_UTLB_REPLAY_FULL", + "T88x_UTLB_REPLAY_MISS", + "T88x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T88x_L2_EXT_WRITE_BEATS", + "T88x_L2_EXT_READ_BEATS", + "T88x_L2_ANY_LOOKUP", + "T88x_L2_READ_LOOKUP", + "T88x_L2_SREAD_LOOKUP", + "T88x_L2_READ_REPLAY", + "T88x_L2_READ_SNOOP", + "T88x_L2_READ_HIT", + "T88x_L2_CLEAN_MISS", + "T88x_L2_WRITE_LOOKUP", + "T88x_L2_SWRITE_LOOKUP", + "T88x_L2_WRITE_REPLAY", + "T88x_L2_WRITE_SNOOP", + "T88x_L2_WRITE_HIT", + "T88x_L2_EXT_READ_FULL", + "", + "T88x_L2_EXT_WRITE_FULL", + "T88x_L2_EXT_R_W_HAZARD", + "T88x_L2_EXT_READ", + "T88x_L2_EXT_READ_LINE", + "T88x_L2_EXT_WRITE", + "T88x_L2_EXT_WRITE_LINE", + "T88x_L2_EXT_WRITE_SMALL", + "T88x_L2_EXT_BARRIER", + "T88x_L2_EXT_AR_STALL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_EXT_RD_BUF_FULL", + "T88x_L2_EXT_R_RAW", + "T88x_L2_EXT_W_STALL", + "T88x_L2_EXT_W_BUF_FULL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_TAG_HAZARD", + "T88x_L2_SNOOP_FULL", + "T88x_L2_REPLAY_FULL" +}; + +#include "mali_kbase_gator_hwcnt_names_tmix.h" + +#include "mali_kbase_gator_hwcnt_names_thex.h" + +#include "mali_kbase_gator_hwcnt_names_tsix.h" + + + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_thex.h b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_thex.h new file mode 100644 index 000000000000..15fd4efdc6ca --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_thex.h @@ -0,0 +1,291 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * This header was autogenerated, it should not be edited. + */ + +#ifndef _KBASE_GATOR_HWCNT_NAMES_THEX_H_ +#define _KBASE_GATOR_HWCNT_NAMES_THEX_H_ + +static const char * const hardware_counters_mali_tHEx[] = { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "THEx_MESSAGES_SENT", + "THEx_MESSAGES_RECEIVED", + "THEx_GPU_ACTIVE", + "THEx_IRQ_ACTIVE", + "THEx_JS0_JOBS", + "THEx_JS0_TASKS", + "THEx_JS0_ACTIVE", + "", + "THEx_JS0_WAIT_READ", + "THEx_JS0_WAIT_ISSUE", + "THEx_JS0_WAIT_DEPEND", + "THEx_JS0_WAIT_FINISH", + "THEx_JS1_JOBS", + "THEx_JS1_TASKS", + "THEx_JS1_ACTIVE", + "", + "THEx_JS1_WAIT_READ", + "THEx_JS1_WAIT_ISSUE", + "THEx_JS1_WAIT_DEPEND", + "THEx_JS1_WAIT_FINISH", + "THEx_JS2_JOBS", + "THEx_JS2_TASKS", + "THEx_JS2_ACTIVE", + "", + "THEx_JS2_WAIT_READ", + "THEx_JS2_WAIT_ISSUE", + "THEx_JS2_WAIT_DEPEND", + "THEx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "THEx_TILER_ACTIVE", + "THEx_JOBS_PROCESSED", + "THEx_TRIANGLES", + "THEx_LINES", + "THEx_POINTS", + "THEx_FRONT_FACING", + "THEx_BACK_FACING", + "THEx_PRIM_VISIBLE", + "THEx_PRIM_CULLED", + "THEx_PRIM_CLIPPED", + "THEx_PRIM_SAT_CULLED", + "THEx_BIN_ALLOC_INIT", + "THEx_BIN_ALLOC_OVERFLOW", + "THEx_BUS_READ", + "", + "THEx_BUS_WRITE", + "THEx_LOADING_DESC", + "THEx_IDVS_POS_SHAD_REQ", + "THEx_IDVS_POS_SHAD_WAIT", + "THEx_IDVS_POS_SHAD_STALL", + "THEx_IDVS_POS_FIFO_FULL", + "THEx_PREFETCH_STALL", + "THEx_VCACHE_HIT", + "THEx_VCACHE_MISS", + "THEx_VCACHE_LINE_WAIT", + "THEx_VFETCH_POS_READ_WAIT", + "THEx_VFETCH_VERTEX_WAIT", + "THEx_VFETCH_STALL", + "THEx_PRIMASSY_STALL", + "THEx_BBOX_GEN_STALL", + "THEx_IDVS_VBU_HIT", + "THEx_IDVS_VBU_MISS", + "THEx_IDVS_VBU_LINE_DEALLOCATE", + "THEx_IDVS_VAR_SHAD_REQ", + "THEx_IDVS_VAR_SHAD_STALL", + "THEx_BINNER_STALL", + "THEx_ITER_STALL", + "THEx_COMPRESS_MISS", + "THEx_COMPRESS_STALL", + "THEx_PCACHE_HIT", + "THEx_PCACHE_MISS", + "THEx_PCACHE_MISS_STALL", + "THEx_PCACHE_EVICT_STALL", + "THEx_PMGR_PTR_WR_STALL", + "THEx_PMGR_PTR_RD_STALL", + "THEx_PMGR_CMD_WR_STALL", + "THEx_WRBUF_ACTIVE", + "THEx_WRBUF_HIT", + "THEx_WRBUF_MISS", + "THEx_WRBUF_NO_FREE_LINE_STALL", + "THEx_WRBUF_NO_AXI_ID_STALL", + "THEx_WRBUF_AXI_STALL", + "", + "", + "", + "THEx_UTLB_TRANS", + "THEx_UTLB_TRANS_HIT", + "THEx_UTLB_TRANS_STALL", + "THEx_UTLB_TRANS_MISS_DELAY", + "THEx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "THEx_FRAG_ACTIVE", + "THEx_FRAG_PRIMITIVES", + "THEx_FRAG_PRIM_RAST", + "THEx_FRAG_FPK_ACTIVE", + "THEx_FRAG_STARVING", + "THEx_FRAG_WARPS", + "THEx_FRAG_PARTIAL_WARPS", + "THEx_FRAG_QUADS_RAST", + "THEx_FRAG_QUADS_EZS_TEST", + "THEx_FRAG_QUADS_EZS_UPDATE", + "THEx_FRAG_QUADS_EZS_KILL", + "THEx_FRAG_LZS_TEST", + "THEx_FRAG_LZS_KILL", + "", + "THEx_FRAG_PTILES", + "THEx_FRAG_TRANS_ELIM", + "THEx_QUAD_FPK_KILLER", + "", + "THEx_COMPUTE_ACTIVE", + "THEx_COMPUTE_TASKS", + "THEx_COMPUTE_WARPS", + "THEx_COMPUTE_STARVING", + "THEx_EXEC_CORE_ACTIVE", + "THEx_EXEC_ACTIVE", + "THEx_EXEC_INSTR_COUNT", + "THEx_EXEC_INSTR_DIVERGED", + "THEx_EXEC_INSTR_STARVING", + "THEx_ARITH_INSTR_SINGLE_FMA", + "THEx_ARITH_INSTR_DOUBLE", + "THEx_ARITH_INSTR_MSG", + "THEx_ARITH_INSTR_MSG_ONLY", + "THEx_TEX_INSTR", + "THEx_TEX_INSTR_MIPMAP", + "THEx_TEX_INSTR_COMPRESSED", + "THEx_TEX_INSTR_3D", + "THEx_TEX_INSTR_TRILINEAR", + "THEx_TEX_COORD_ISSUE", + "THEx_TEX_COORD_STALL", + "THEx_TEX_STARVE_CACHE", + "THEx_TEX_STARVE_FILTER", + "THEx_LS_MEM_READ_FULL", + "THEx_LS_MEM_READ_SHORT", + "THEx_LS_MEM_WRITE_FULL", + "THEx_LS_MEM_WRITE_SHORT", + "THEx_LS_MEM_ATOMIC", + "THEx_VARY_INSTR", + "THEx_VARY_SLOT_32", + "THEx_VARY_SLOT_16", + "THEx_ATTR_INSTR", + "THEx_ARITH_INSTR_FP_MUL", + "THEx_BEATS_RD_FTC", + "THEx_BEATS_RD_FTC_EXT", + "THEx_BEATS_RD_LSC", + "THEx_BEATS_RD_LSC_EXT", + "THEx_BEATS_RD_TEX", + "THEx_BEATS_RD_TEX_EXT", + "THEx_BEATS_RD_OTHER", + "THEx_BEATS_WR_LSC", + "THEx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "THEx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "THEx_L2_RD_MSG_IN", + "THEx_L2_RD_MSG_IN_STALL", + "THEx_L2_WR_MSG_IN", + "THEx_L2_WR_MSG_IN_STALL", + "THEx_L2_SNP_MSG_IN", + "THEx_L2_SNP_MSG_IN_STALL", + "THEx_L2_RD_MSG_OUT", + "THEx_L2_RD_MSG_OUT_STALL", + "THEx_L2_WR_MSG_OUT", + "THEx_L2_ANY_LOOKUP", + "THEx_L2_READ_LOOKUP", + "THEx_L2_WRITE_LOOKUP", + "THEx_L2_EXT_SNOOP_LOOKUP", + "THEx_L2_EXT_READ", + "THEx_L2_EXT_READ_NOSNP", + "THEx_L2_EXT_READ_UNIQUE", + "THEx_L2_EXT_READ_BEATS", + "THEx_L2_EXT_AR_STALL", + "THEx_L2_EXT_AR_CNT_Q1", + "THEx_L2_EXT_AR_CNT_Q2", + "THEx_L2_EXT_AR_CNT_Q3", + "THEx_L2_EXT_RRESP_0_127", + "THEx_L2_EXT_RRESP_128_191", + "THEx_L2_EXT_RRESP_192_255", + "THEx_L2_EXT_RRESP_256_319", + "THEx_L2_EXT_RRESP_320_383", + "THEx_L2_EXT_WRITE", + "THEx_L2_EXT_WRITE_NOSNP_FULL", + "THEx_L2_EXT_WRITE_NOSNP_PTL", + "THEx_L2_EXT_WRITE_SNP_FULL", + "THEx_L2_EXT_WRITE_SNP_PTL", + "THEx_L2_EXT_WRITE_BEATS", + "THEx_L2_EXT_W_STALL", + "THEx_L2_EXT_AW_CNT_Q1", + "THEx_L2_EXT_AW_CNT_Q2", + "THEx_L2_EXT_AW_CNT_Q3", + "THEx_L2_EXT_SNOOP", + "THEx_L2_EXT_SNOOP_STALL", + "THEx_L2_EXT_SNOOP_RESP_CLEAN", + "THEx_L2_EXT_SNOOP_RESP_DATA", + "THEx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + "", +}; + +#endif /* _KBASE_GATOR_HWCNT_NAMES_THEX_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tmix.h b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tmix.h new file mode 100644 index 000000000000..8a215f723570 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tmix.h @@ -0,0 +1,291 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * This header was autogenerated, it should not be edited. + */ + +#ifndef _KBASE_GATOR_HWCNT_NAMES_TMIX_H_ +#define _KBASE_GATOR_HWCNT_NAMES_TMIX_H_ + +static const char * const hardware_counters_mali_tMIx[] = { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "TMIx_MESSAGES_SENT", + "TMIx_MESSAGES_RECEIVED", + "TMIx_GPU_ACTIVE", + "TMIx_IRQ_ACTIVE", + "TMIx_JS0_JOBS", + "TMIx_JS0_TASKS", + "TMIx_JS0_ACTIVE", + "", + "TMIx_JS0_WAIT_READ", + "TMIx_JS0_WAIT_ISSUE", + "TMIx_JS0_WAIT_DEPEND", + "TMIx_JS0_WAIT_FINISH", + "TMIx_JS1_JOBS", + "TMIx_JS1_TASKS", + "TMIx_JS1_ACTIVE", + "", + "TMIx_JS1_WAIT_READ", + "TMIx_JS1_WAIT_ISSUE", + "TMIx_JS1_WAIT_DEPEND", + "TMIx_JS1_WAIT_FINISH", + "TMIx_JS2_JOBS", + "TMIx_JS2_TASKS", + "TMIx_JS2_ACTIVE", + "", + "TMIx_JS2_WAIT_READ", + "TMIx_JS2_WAIT_ISSUE", + "TMIx_JS2_WAIT_DEPEND", + "TMIx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "TMIx_TILER_ACTIVE", + "TMIx_JOBS_PROCESSED", + "TMIx_TRIANGLES", + "TMIx_LINES", + "TMIx_POINTS", + "TMIx_FRONT_FACING", + "TMIx_BACK_FACING", + "TMIx_PRIM_VISIBLE", + "TMIx_PRIM_CULLED", + "TMIx_PRIM_CLIPPED", + "TMIx_PRIM_SAT_CULLED", + "TMIx_BIN_ALLOC_INIT", + "TMIx_BIN_ALLOC_OVERFLOW", + "TMIx_BUS_READ", + "", + "TMIx_BUS_WRITE", + "TMIx_LOADING_DESC", + "TMIx_IDVS_POS_SHAD_REQ", + "TMIx_IDVS_POS_SHAD_WAIT", + "TMIx_IDVS_POS_SHAD_STALL", + "TMIx_IDVS_POS_FIFO_FULL", + "TMIx_PREFETCH_STALL", + "TMIx_VCACHE_HIT", + "TMIx_VCACHE_MISS", + "TMIx_VCACHE_LINE_WAIT", + "TMIx_VFETCH_POS_READ_WAIT", + "TMIx_VFETCH_VERTEX_WAIT", + "TMIx_VFETCH_STALL", + "TMIx_PRIMASSY_STALL", + "TMIx_BBOX_GEN_STALL", + "TMIx_IDVS_VBU_HIT", + "TMIx_IDVS_VBU_MISS", + "TMIx_IDVS_VBU_LINE_DEALLOCATE", + "TMIx_IDVS_VAR_SHAD_REQ", + "TMIx_IDVS_VAR_SHAD_STALL", + "TMIx_BINNER_STALL", + "TMIx_ITER_STALL", + "TMIx_COMPRESS_MISS", + "TMIx_COMPRESS_STALL", + "TMIx_PCACHE_HIT", + "TMIx_PCACHE_MISS", + "TMIx_PCACHE_MISS_STALL", + "TMIx_PCACHE_EVICT_STALL", + "TMIx_PMGR_PTR_WR_STALL", + "TMIx_PMGR_PTR_RD_STALL", + "TMIx_PMGR_CMD_WR_STALL", + "TMIx_WRBUF_ACTIVE", + "TMIx_WRBUF_HIT", + "TMIx_WRBUF_MISS", + "TMIx_WRBUF_NO_FREE_LINE_STALL", + "TMIx_WRBUF_NO_AXI_ID_STALL", + "TMIx_WRBUF_AXI_STALL", + "", + "", + "", + "TMIx_UTLB_TRANS", + "TMIx_UTLB_TRANS_HIT", + "TMIx_UTLB_TRANS_STALL", + "TMIx_UTLB_TRANS_MISS_DELAY", + "TMIx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "TMIx_FRAG_ACTIVE", + "TMIx_FRAG_PRIMITIVES", + "TMIx_FRAG_PRIM_RAST", + "TMIx_FRAG_FPK_ACTIVE", + "TMIx_FRAG_STARVING", + "TMIx_FRAG_WARPS", + "TMIx_FRAG_PARTIAL_WARPS", + "TMIx_FRAG_QUADS_RAST", + "TMIx_FRAG_QUADS_EZS_TEST", + "TMIx_FRAG_QUADS_EZS_UPDATE", + "TMIx_FRAG_QUADS_EZS_KILL", + "TMIx_FRAG_LZS_TEST", + "TMIx_FRAG_LZS_KILL", + "", + "TMIx_FRAG_PTILES", + "TMIx_FRAG_TRANS_ELIM", + "TMIx_QUAD_FPK_KILLER", + "", + "TMIx_COMPUTE_ACTIVE", + "TMIx_COMPUTE_TASKS", + "TMIx_COMPUTE_WARPS", + "TMIx_COMPUTE_STARVING", + "TMIx_EXEC_CORE_ACTIVE", + "TMIx_EXEC_ACTIVE", + "TMIx_EXEC_INSTR_COUNT", + "TMIx_EXEC_INSTR_DIVERGED", + "TMIx_EXEC_INSTR_STARVING", + "TMIx_ARITH_INSTR_SINGLE_FMA", + "TMIx_ARITH_INSTR_DOUBLE", + "TMIx_ARITH_INSTR_MSG", + "TMIx_ARITH_INSTR_MSG_ONLY", + "TMIx_TEX_INSTR", + "TMIx_TEX_INSTR_MIPMAP", + "TMIx_TEX_INSTR_COMPRESSED", + "TMIx_TEX_INSTR_3D", + "TMIx_TEX_INSTR_TRILINEAR", + "TMIx_TEX_COORD_ISSUE", + "TMIx_TEX_COORD_STALL", + "TMIx_TEX_STARVE_CACHE", + "TMIx_TEX_STARVE_FILTER", + "TMIx_LS_MEM_READ_FULL", + "TMIx_LS_MEM_READ_SHORT", + "TMIx_LS_MEM_WRITE_FULL", + "TMIx_LS_MEM_WRITE_SHORT", + "TMIx_LS_MEM_ATOMIC", + "TMIx_VARY_INSTR", + "TMIx_VARY_SLOT_32", + "TMIx_VARY_SLOT_16", + "TMIx_ATTR_INSTR", + "TMIx_ARITH_INSTR_FP_MUL", + "TMIx_BEATS_RD_FTC", + "TMIx_BEATS_RD_FTC_EXT", + "TMIx_BEATS_RD_LSC", + "TMIx_BEATS_RD_LSC_EXT", + "TMIx_BEATS_RD_TEX", + "TMIx_BEATS_RD_TEX_EXT", + "TMIx_BEATS_RD_OTHER", + "TMIx_BEATS_WR_LSC", + "TMIx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "TMIx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "TMIx_L2_RD_MSG_IN", + "TMIx_L2_RD_MSG_IN_STALL", + "TMIx_L2_WR_MSG_IN", + "TMIx_L2_WR_MSG_IN_STALL", + "TMIx_L2_SNP_MSG_IN", + "TMIx_L2_SNP_MSG_IN_STALL", + "TMIx_L2_RD_MSG_OUT", + "TMIx_L2_RD_MSG_OUT_STALL", + "TMIx_L2_WR_MSG_OUT", + "TMIx_L2_ANY_LOOKUP", + "TMIx_L2_READ_LOOKUP", + "TMIx_L2_WRITE_LOOKUP", + "TMIx_L2_EXT_SNOOP_LOOKUP", + "TMIx_L2_EXT_READ", + "TMIx_L2_EXT_READ_NOSNP", + "TMIx_L2_EXT_READ_UNIQUE", + "TMIx_L2_EXT_READ_BEATS", + "TMIx_L2_EXT_AR_STALL", + "TMIx_L2_EXT_AR_CNT_Q1", + "TMIx_L2_EXT_AR_CNT_Q2", + "TMIx_L2_EXT_AR_CNT_Q3", + "TMIx_L2_EXT_RRESP_0_127", + "TMIx_L2_EXT_RRESP_128_191", + "TMIx_L2_EXT_RRESP_192_255", + "TMIx_L2_EXT_RRESP_256_319", + "TMIx_L2_EXT_RRESP_320_383", + "TMIx_L2_EXT_WRITE", + "TMIx_L2_EXT_WRITE_NOSNP_FULL", + "TMIx_L2_EXT_WRITE_NOSNP_PTL", + "TMIx_L2_EXT_WRITE_SNP_FULL", + "TMIx_L2_EXT_WRITE_SNP_PTL", + "TMIx_L2_EXT_WRITE_BEATS", + "TMIx_L2_EXT_W_STALL", + "TMIx_L2_EXT_AW_CNT_Q1", + "TMIx_L2_EXT_AW_CNT_Q2", + "TMIx_L2_EXT_AW_CNT_Q3", + "TMIx_L2_EXT_SNOOP", + "TMIx_L2_EXT_SNOOP_STALL", + "TMIx_L2_EXT_SNOOP_RESP_CLEAN", + "TMIx_L2_EXT_SNOOP_RESP_DATA", + "TMIx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + "", +}; + +#endif /* _KBASE_GATOR_HWCNT_NAMES_TMIX_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tsix.h b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tsix.h new file mode 100644 index 000000000000..fb6a1437a1f6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator_hwcnt_names_tsix.h @@ -0,0 +1,291 @@ +/* + * + * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * This header was autogenerated, it should not be edited. + */ + +#ifndef _KBASE_GATOR_HWCNT_NAMES_TSIX_H_ +#define _KBASE_GATOR_HWCNT_NAMES_TSIX_H_ + +static const char * const hardware_counters_mali_tSIx[] = { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "TSIx_MESSAGES_SENT", + "TSIx_MESSAGES_RECEIVED", + "TSIx_GPU_ACTIVE", + "TSIx_IRQ_ACTIVE", + "TSIx_JS0_JOBS", + "TSIx_JS0_TASKS", + "TSIx_JS0_ACTIVE", + "", + "TSIx_JS0_WAIT_READ", + "TSIx_JS0_WAIT_ISSUE", + "TSIx_JS0_WAIT_DEPEND", + "TSIx_JS0_WAIT_FINISH", + "TSIx_JS1_JOBS", + "TSIx_JS1_TASKS", + "TSIx_JS1_ACTIVE", + "", + "TSIx_JS1_WAIT_READ", + "TSIx_JS1_WAIT_ISSUE", + "TSIx_JS1_WAIT_DEPEND", + "TSIx_JS1_WAIT_FINISH", + "TSIx_JS2_JOBS", + "TSIx_JS2_TASKS", + "TSIx_JS2_ACTIVE", + "", + "TSIx_JS2_WAIT_READ", + "TSIx_JS2_WAIT_ISSUE", + "TSIx_JS2_WAIT_DEPEND", + "TSIx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "TSIx_TILER_ACTIVE", + "TSIx_JOBS_PROCESSED", + "TSIx_TRIANGLES", + "TSIx_LINES", + "TSIx_POINTS", + "TSIx_FRONT_FACING", + "TSIx_BACK_FACING", + "TSIx_PRIM_VISIBLE", + "TSIx_PRIM_CULLED", + "TSIx_PRIM_CLIPPED", + "TSIx_PRIM_SAT_CULLED", + "TSIx_BIN_ALLOC_INIT", + "TSIx_BIN_ALLOC_OVERFLOW", + "TSIx_BUS_READ", + "", + "TSIx_BUS_WRITE", + "TSIx_LOADING_DESC", + "TSIx_IDVS_POS_SHAD_REQ", + "TSIx_IDVS_POS_SHAD_WAIT", + "TSIx_IDVS_POS_SHAD_STALL", + "TSIx_IDVS_POS_FIFO_FULL", + "TSIx_PREFETCH_STALL", + "TSIx_VCACHE_HIT", + "TSIx_VCACHE_MISS", + "TSIx_VCACHE_LINE_WAIT", + "TSIx_VFETCH_POS_READ_WAIT", + "TSIx_VFETCH_VERTEX_WAIT", + "TSIx_VFETCH_STALL", + "TSIx_PRIMASSY_STALL", + "TSIx_BBOX_GEN_STALL", + "TSIx_IDVS_VBU_HIT", + "TSIx_IDVS_VBU_MISS", + "TSIx_IDVS_VBU_LINE_DEALLOCATE", + "TSIx_IDVS_VAR_SHAD_REQ", + "TSIx_IDVS_VAR_SHAD_STALL", + "TSIx_BINNER_STALL", + "TSIx_ITER_STALL", + "TSIx_COMPRESS_MISS", + "TSIx_COMPRESS_STALL", + "TSIx_PCACHE_HIT", + "TSIx_PCACHE_MISS", + "TSIx_PCACHE_MISS_STALL", + "TSIx_PCACHE_EVICT_STALL", + "TSIx_PMGR_PTR_WR_STALL", + "TSIx_PMGR_PTR_RD_STALL", + "TSIx_PMGR_CMD_WR_STALL", + "TSIx_WRBUF_ACTIVE", + "TSIx_WRBUF_HIT", + "TSIx_WRBUF_MISS", + "TSIx_WRBUF_NO_FREE_LINE_STALL", + "TSIx_WRBUF_NO_AXI_ID_STALL", + "TSIx_WRBUF_AXI_STALL", + "", + "", + "", + "TSIx_UTLB_TRANS", + "TSIx_UTLB_TRANS_HIT", + "TSIx_UTLB_TRANS_STALL", + "TSIx_UTLB_TRANS_MISS_DELAY", + "TSIx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "TSIx_FRAG_ACTIVE", + "TSIx_FRAG_PRIMITIVES", + "TSIx_FRAG_PRIM_RAST", + "TSIx_FRAG_FPK_ACTIVE", + "TSIx_FRAG_STARVING", + "TSIx_FRAG_WARPS", + "TSIx_FRAG_PARTIAL_WARPS", + "TSIx_FRAG_QUADS_RAST", + "TSIx_FRAG_QUADS_EZS_TEST", + "TSIx_FRAG_QUADS_EZS_UPDATE", + "TSIx_FRAG_QUADS_EZS_KILL", + "TSIx_FRAG_LZS_TEST", + "TSIx_FRAG_LZS_KILL", + "", + "TSIx_FRAG_PTILES", + "TSIx_FRAG_TRANS_ELIM", + "TSIx_QUAD_FPK_KILLER", + "", + "TSIx_COMPUTE_ACTIVE", + "TSIx_COMPUTE_TASKS", + "TSIx_COMPUTE_WARPS", + "TSIx_COMPUTE_STARVING", + "TSIx_EXEC_CORE_ACTIVE", + "TSIx_EXEC_ACTIVE", + "TSIx_EXEC_INSTR_COUNT", + "TSIx_EXEC_INSTR_DIVERGED", + "TSIx_EXEC_INSTR_STARVING", + "TSIx_ARITH_INSTR_SINGLE_FMA", + "TSIx_ARITH_INSTR_DOUBLE", + "TSIx_ARITH_INSTR_MSG", + "TSIx_ARITH_INSTR_MSG_ONLY", + "TSIx_TEX_MSGI_NUM_QUADS", + "TSIx_TEX_DFCH_NUM_PASSES", + "TSIx_TEX_DFCH_NUM_PASSES_MISS", + "TSIx_TEX_DFCH_NUM_PASSES_MIP_MAP", + "TSIx_TEX_TIDX_NUM_SPLIT_MIP_MAP", + "TSIx_TEX_TFCH_NUM_LINES_FETCHED", + "TSIx_TEX_TFCH_NUM_LINES_FETCHED_BLOCK", + "TSIx_TEX_TFCH_NUM_OPERATIONS", + "TSIx_TEX_FILT_NUM_OPERATIONS", + "TSIx_LS_MEM_READ_FULL", + "TSIx_LS_MEM_READ_SHORT", + "TSIx_LS_MEM_WRITE_FULL", + "TSIx_LS_MEM_WRITE_SHORT", + "TSIx_LS_MEM_ATOMIC", + "TSIx_VARY_INSTR", + "TSIx_VARY_SLOT_32", + "TSIx_VARY_SLOT_16", + "TSIx_ATTR_INSTR", + "TSIx_ARITH_INSTR_FP_MUL", + "TSIx_BEATS_RD_FTC", + "TSIx_BEATS_RD_FTC_EXT", + "TSIx_BEATS_RD_LSC", + "TSIx_BEATS_RD_LSC_EXT", + "TSIx_BEATS_RD_TEX", + "TSIx_BEATS_RD_TEX_EXT", + "TSIx_BEATS_RD_OTHER", + "TSIx_BEATS_WR_LSC", + "TSIx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "TSIx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "TSIx_L2_RD_MSG_IN", + "TSIx_L2_RD_MSG_IN_STALL", + "TSIx_L2_WR_MSG_IN", + "TSIx_L2_WR_MSG_IN_STALL", + "TSIx_L2_SNP_MSG_IN", + "TSIx_L2_SNP_MSG_IN_STALL", + "TSIx_L2_RD_MSG_OUT", + "TSIx_L2_RD_MSG_OUT_STALL", + "TSIx_L2_WR_MSG_OUT", + "TSIx_L2_ANY_LOOKUP", + "TSIx_L2_READ_LOOKUP", + "TSIx_L2_WRITE_LOOKUP", + "TSIx_L2_EXT_SNOOP_LOOKUP", + "TSIx_L2_EXT_READ", + "TSIx_L2_EXT_READ_NOSNP", + "TSIx_L2_EXT_READ_UNIQUE", + "TSIx_L2_EXT_READ_BEATS", + "TSIx_L2_EXT_AR_STALL", + "TSIx_L2_EXT_AR_CNT_Q1", + "TSIx_L2_EXT_AR_CNT_Q2", + "TSIx_L2_EXT_AR_CNT_Q3", + "TSIx_L2_EXT_RRESP_0_127", + "TSIx_L2_EXT_RRESP_128_191", + "TSIx_L2_EXT_RRESP_192_255", + "TSIx_L2_EXT_RRESP_256_319", + "TSIx_L2_EXT_RRESP_320_383", + "TSIx_L2_EXT_WRITE", + "TSIx_L2_EXT_WRITE_NOSNP_FULL", + "TSIx_L2_EXT_WRITE_NOSNP_PTL", + "TSIx_L2_EXT_WRITE_SNP_FULL", + "TSIx_L2_EXT_WRITE_SNP_PTL", + "TSIx_L2_EXT_WRITE_BEATS", + "TSIx_L2_EXT_W_STALL", + "TSIx_L2_EXT_AW_CNT_Q1", + "TSIx_L2_EXT_AW_CNT_Q2", + "TSIx_L2_EXT_AW_CNT_Q3", + "TSIx_L2_EXT_SNOOP", + "TSIx_L2_EXT_SNOOP_STALL", + "TSIx_L2_EXT_SNOOP_RESP_CLEAN", + "TSIx_L2_EXT_SNOOP_RESP_DATA", + "TSIx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + "", +}; + +#endif /* _KBASE_GATOR_HWCNT_NAMES_TSIX_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpu_id.h b/drivers/gpu/arm/bifrost/mali_kbase_gpu_id.h new file mode 100644 index 000000000000..2d368dfaf644 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpu_id.h @@ -0,0 +1,118 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef _KBASE_GPU_ID_H_ +#define _KBASE_GPU_ID_H_ + +/* GPU_ID register */ +#define GPU_ID_VERSION_STATUS_SHIFT 0 +#define GPU_ID_VERSION_MINOR_SHIFT 4 +#define GPU_ID_VERSION_MAJOR_SHIFT 12 +#define GPU_ID_VERSION_PRODUCT_ID_SHIFT 16 +#define GPU_ID_VERSION_STATUS (0xF << GPU_ID_VERSION_STATUS_SHIFT) +#define GPU_ID_VERSION_MINOR (0xFF << GPU_ID_VERSION_MINOR_SHIFT) +#define GPU_ID_VERSION_MAJOR (0xF << GPU_ID_VERSION_MAJOR_SHIFT) +#define GPU_ID_VERSION_PRODUCT_ID (0xFFFF << GPU_ID_VERSION_PRODUCT_ID_SHIFT) + +/* Values for GPU_ID_VERSION_PRODUCT_ID bitfield */ +#define GPU_ID_PI_T60X 0x6956 +#define GPU_ID_PI_T62X 0x0620 +#define GPU_ID_PI_T76X 0x0750 +#define GPU_ID_PI_T72X 0x0720 +#define GPU_ID_PI_TFRX 0x0880 +#define GPU_ID_PI_T86X 0x0860 +#define GPU_ID_PI_T82X 0x0820 +#define GPU_ID_PI_T83X 0x0830 + +/* New GPU ID format when PRODUCT_ID is >= 0x1000 (and not 0x6956) */ +#define GPU_ID_PI_NEW_FORMAT_START 0x1000 +#define GPU_ID_IS_NEW_FORMAT(product_id) ((product_id) != GPU_ID_PI_T60X && \ + (product_id) >= \ + GPU_ID_PI_NEW_FORMAT_START) + +#define GPU_ID2_VERSION_STATUS_SHIFT 0 +#define GPU_ID2_VERSION_MINOR_SHIFT 4 +#define GPU_ID2_VERSION_MAJOR_SHIFT 12 +#define GPU_ID2_PRODUCT_MAJOR_SHIFT 16 +#define GPU_ID2_ARCH_REV_SHIFT 20 +#define GPU_ID2_ARCH_MINOR_SHIFT 24 +#define GPU_ID2_ARCH_MAJOR_SHIFT 28 +#define GPU_ID2_VERSION_STATUS (0xF << GPU_ID2_VERSION_STATUS_SHIFT) +#define GPU_ID2_VERSION_MINOR (0xFF << GPU_ID2_VERSION_MINOR_SHIFT) +#define GPU_ID2_VERSION_MAJOR (0xF << GPU_ID2_VERSION_MAJOR_SHIFT) +#define GPU_ID2_PRODUCT_MAJOR (0xF << GPU_ID2_PRODUCT_MAJOR_SHIFT) +#define GPU_ID2_ARCH_REV (0xF << GPU_ID2_ARCH_REV_SHIFT) +#define GPU_ID2_ARCH_MINOR (0xF << GPU_ID2_ARCH_MINOR_SHIFT) +#define GPU_ID2_ARCH_MAJOR (0xF << GPU_ID2_ARCH_MAJOR_SHIFT) +#define GPU_ID2_PRODUCT_MODEL (GPU_ID2_ARCH_MAJOR | GPU_ID2_PRODUCT_MAJOR) +#define GPU_ID2_VERSION (GPU_ID2_VERSION_MAJOR | \ + GPU_ID2_VERSION_MINOR | \ + GPU_ID2_VERSION_STATUS) + +/* Helper macro to create a partial GPU_ID (new format) that defines + a product ignoring its version. */ +#define GPU_ID2_PRODUCT_MAKE(arch_major, arch_minor, arch_rev, product_major) \ + (((arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \ + ((arch_minor) << GPU_ID2_ARCH_MINOR_SHIFT) | \ + ((arch_rev) << GPU_ID2_ARCH_REV_SHIFT) | \ + ((product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT)) + +/* Helper macro to create a partial GPU_ID (new format) that specifies the + revision (major, minor, status) of a product */ +#define GPU_ID2_VERSION_MAKE(version_major, version_minor, version_status) \ + (((version_major) << GPU_ID2_VERSION_MAJOR_SHIFT) | \ + ((version_minor) << GPU_ID2_VERSION_MINOR_SHIFT) | \ + ((version_status) << GPU_ID2_VERSION_STATUS_SHIFT)) + +/* Helper macro to create a complete GPU_ID (new format) */ +#define GPU_ID2_MAKE(arch_major, arch_minor, arch_rev, product_major, \ + version_major, version_minor, version_status) \ + (GPU_ID2_PRODUCT_MAKE(arch_major, arch_minor, arch_rev, \ + product_major) | \ + GPU_ID2_VERSION_MAKE(version_major, version_minor, \ + version_status)) + +/* Helper macro to create a partial GPU_ID (new format) that identifies + a particular GPU model by its arch_major and product_major. */ +#define GPU_ID2_MODEL_MAKE(arch_major, product_major) \ + (((arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \ + ((product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT)) + +/* Strip off the non-relevant bits from a product_id value and make it suitable + for comparison against the GPU_ID2_PRODUCT_xxx values which identify a GPU + model. */ +#define GPU_ID2_MODEL_MATCH_VALUE(product_id) \ + (((product_id) << GPU_ID2_PRODUCT_MAJOR_SHIFT) & \ + GPU_ID2_PRODUCT_MODEL) + +#define GPU_ID2_PRODUCT_TMIX GPU_ID2_MODEL_MAKE(6u, 0) +#define GPU_ID2_PRODUCT_THEX GPU_ID2_MODEL_MAKE(6u, 1) +#define GPU_ID2_PRODUCT_TSIX GPU_ID2_MODEL_MAKE(7u, 0) +#define GPU_ID2_PRODUCT_TDVX GPU_ID2_MODEL_MAKE(7u, 3) + +/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */ +#define GPU_ID_S_15DEV0 0x1 +#define GPU_ID_S_EAC 0x2 + +/* Helper macro to create a GPU_ID assuming valid values for id, major, + minor, status */ +#define GPU_ID_MAKE(id, major, minor, status) \ + (((id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \ + ((major) << GPU_ID_VERSION_MAJOR_SHIFT) | \ + ((minor) << GPU_ID_VERSION_MINOR_SHIFT) | \ + ((status) << GPU_ID_VERSION_STATUS_SHIFT)) + +#endif /* _KBASE_GPU_ID_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.c new file mode 100644 index 000000000000..6df0a1cb1264 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.c @@ -0,0 +1,97 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS +/** Show callback for the @c gpu_memory debugfs file. + * + * This function is called to get the contents of the @c gpu_memory debugfs + * file. This is a report of current gpu memory usage. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ + +static int kbasep_gpu_memory_seq_show(struct seq_file *sfile, void *data) +{ + struct list_head *entry; + const struct list_head *kbdev_list; + + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) { + struct kbase_device *kbdev = NULL; + struct kbasep_kctx_list_element *element; + + kbdev = list_entry(entry, struct kbase_device, entry); + /* output the total memory usage and cap for this device */ + seq_printf(sfile, "%-16s %10u\n", + kbdev->devname, + atomic_read(&(kbdev->memdev.used_pages))); + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry(element, &kbdev->kctx_list, link) { + /* output the memory usage and cap for each kctx + * opened on this device */ + seq_printf(sfile, " %s-0x%p %10u\n", + "kctx", + element->kctx, + atomic_read(&(element->kctx->used_pages))); + } + mutex_unlock(&kbdev->kctx_list_lock); + } + kbase_dev_list_put(kbdev_list); + return 0; +} + +/* + * File operations related to debugfs entry for gpu_memory + */ +static int kbasep_gpu_memory_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_gpu_memory_seq_show , NULL); +} + +static const struct file_operations kbasep_gpu_memory_debugfs_fops = { + .open = kbasep_gpu_memory_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Initialize debugfs entry for gpu_memory + */ +void kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + debugfs_create_file("gpu_memory", S_IRUGO, + kbdev->mali_debugfs_directory, NULL, + &kbasep_gpu_memory_debugfs_fops); + return; +} + +#else +/* + * Stub functions for when debugfs is disabled + */ +void kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + return; +} +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.h new file mode 100644 index 000000000000..7045693eb910 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpu_memory_debugfs.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT 2012-2014, 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpu_memory_debugfs.h + * Header file for gpu_memory entry in debugfs + * + */ + +#ifndef _KBASE_GPU_MEMORY_DEBUGFS_H +#define _KBASE_GPU_MEMORY_DEBUGFS_H + +#include +#include + +/** + * @brief Initialize gpu_memory debugfs entry + */ +void kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev); + +#endif /*_KBASE_GPU_MEMORY_DEBUGFS_H*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c new file mode 100644 index 000000000000..baf3c491c719 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c @@ -0,0 +1,514 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Base kernel property query APIs + */ + +#include +#include +#include +#include +#include +#include "mali_kbase_ioctl.h" +#include + +/** + * KBASE_UBFX32 - Extracts bits from a 32-bit bitfield. + * @value: The value from which to extract bits. + * @offset: The first bit to extract (0 being the LSB). + * @size: The number of bits to extract. + * + * Context: @offset + @size <= 32. + * + * Return: Bits [@offset, @offset + @size) from @value. + */ +/* from mali_cdsb.h */ +#define KBASE_UBFX32(value, offset, size) \ + (((u32)(value) >> (u32)(offset)) & (u32)((1ULL << (u32)(size)) - 1)) + +int kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props) +{ + kbase_gpu_clk_speed_func get_gpu_speed_mhz; + u32 gpu_speed_mhz; + int rc = 1; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kbase_props); + + /* Current GPU speed is requested from the system integrator via the GPU_SPEED_FUNC function. + * If that function fails, or the function is not provided by the system integrator, we report the maximum + * GPU speed as specified by GPU_FREQ_KHZ_MAX. + */ + get_gpu_speed_mhz = (kbase_gpu_clk_speed_func) GPU_SPEED_FUNC; + if (get_gpu_speed_mhz != NULL) { + rc = get_gpu_speed_mhz(&gpu_speed_mhz); +#ifdef CONFIG_MALI_DEBUG + /* Issue a warning message when the reported GPU speed falls outside the min/max range */ + if (rc == 0) { + u32 gpu_speed_khz = gpu_speed_mhz * 1000; + + if (gpu_speed_khz < kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min || + gpu_speed_khz > kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max) + dev_warn(kctx->kbdev->dev, "GPU Speed is outside of min/max range (got %lu Khz, min %lu Khz, max %lu Khz)\n", + (unsigned long)gpu_speed_khz, + (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min, + (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max); + } +#endif /* CONFIG_MALI_DEBUG */ + } + if (kctx->kbdev->clock) { + gpu_speed_mhz = clk_get_rate(kctx->kbdev->clock) / 1000000; + rc = 0; + } + if (rc != 0) + gpu_speed_mhz = kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max / 1000; + + kctx->kbdev->gpu_props.props.core_props.gpu_speed_mhz = gpu_speed_mhz; + + memcpy(&kbase_props->props, &kctx->kbdev->gpu_props.props, sizeof(kbase_props->props)); + + /* Before API 8.2 they expect L3 cache info here, which was always 0 */ + if (kctx->api_version < KBASE_API_VERSION(8, 2)) + kbase_props->props.raw_props.suspend_size = 0; + + return 0; +} + +static void kbase_gpuprops_construct_coherent_groups(base_gpu_props * const props) +{ + struct mali_base_gpu_coherent_group *current_group; + u64 group_present; + u64 group_mask; + u64 first_set, first_set_prev; + u32 num_groups = 0; + + KBASE_DEBUG_ASSERT(NULL != props); + + props->coherency_info.coherency = props->raw_props.mem_features; + props->coherency_info.num_core_groups = hweight64(props->raw_props.l2_present); + + if (props->coherency_info.coherency & GROUPS_L2_COHERENT) { + /* Group is l2 coherent */ + group_present = props->raw_props.l2_present; + } else { + /* Group is l1 coherent */ + group_present = props->raw_props.shader_present; + } + + /* + * The coherent group mask can be computed from the l2 present + * register. + * + * For the coherent group n: + * group_mask[n] = (first_set[n] - 1) & ~(first_set[n-1] - 1) + * where first_set is group_present with only its nth set-bit kept + * (i.e. the position from where a new group starts). + * + * For instance if the groups are l2 coherent and l2_present=0x0..01111: + * The first mask is: + * group_mask[1] = (first_set[1] - 1) & ~(first_set[0] - 1) + * = (0x0..010 - 1) & ~(0x0..01 - 1) + * = 0x0..00f + * The second mask is: + * group_mask[2] = (first_set[2] - 1) & ~(first_set[1] - 1) + * = (0x0..100 - 1) & ~(0x0..010 - 1) + * = 0x0..0f0 + * And so on until all the bits from group_present have been cleared + * (i.e. there is no group left). + */ + + current_group = props->coherency_info.group; + first_set = group_present & ~(group_present - 1); + + while (group_present != 0 && num_groups < BASE_MAX_COHERENT_GROUPS) { + group_present -= first_set; /* Clear the current group bit */ + first_set_prev = first_set; + + first_set = group_present & ~(group_present - 1); + group_mask = (first_set - 1) & ~(first_set_prev - 1); + + /* Populate the coherent_group structure for each group */ + current_group->core_mask = group_mask & props->raw_props.shader_present; + current_group->num_cores = hweight64(current_group->core_mask); + + num_groups++; + current_group++; + } + + if (group_present != 0) + pr_warn("Too many coherent groups (keeping only %d groups).\n", BASE_MAX_COHERENT_GROUPS); + + props->coherency_info.num_groups = num_groups; +} + +/** + * kbase_gpuprops_get_props - Get the GPU configuration + * @gpu_props: The &base_gpu_props structure + * @kbdev: The &struct kbase_device structure for the device + * + * Fill the &base_gpu_props structure with values from the GPU configuration + * registers. Only the raw properties are filled in this function + */ +static void kbase_gpuprops_get_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + struct kbase_gpuprops_regdump regdump; + int i; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != gpu_props); + + /* Dump relevant registers */ + kbase_backend_gpuprops_get(kbdev, ®dump); + + gpu_props->raw_props.gpu_id = regdump.gpu_id; + gpu_props->raw_props.tiler_features = regdump.tiler_features; + gpu_props->raw_props.mem_features = regdump.mem_features; + gpu_props->raw_props.mmu_features = regdump.mmu_features; + gpu_props->raw_props.l2_features = regdump.l2_features; + gpu_props->raw_props.suspend_size = regdump.suspend_size; + + gpu_props->raw_props.as_present = regdump.as_present; + gpu_props->raw_props.js_present = regdump.js_present; + gpu_props->raw_props.shader_present = + ((u64) regdump.shader_present_hi << 32) + + regdump.shader_present_lo; + gpu_props->raw_props.tiler_present = + ((u64) regdump.tiler_present_hi << 32) + + regdump.tiler_present_lo; + gpu_props->raw_props.l2_present = + ((u64) regdump.l2_present_hi << 32) + + regdump.l2_present_lo; +#ifdef CONFIG_MALI_CORESTACK + gpu_props->raw_props.stack_present = + ((u64) regdump.stack_present_hi << 32) + + regdump.stack_present_lo; +#else /* CONFIG_MALI_CORESTACK */ + gpu_props->raw_props.stack_present = 0; +#endif /* CONFIG_MALI_CORESTACK */ + + for (i = 0; i < GPU_MAX_JOB_SLOTS; i++) + gpu_props->raw_props.js_features[i] = regdump.js_features[i]; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->raw_props.texture_features[i] = regdump.texture_features[i]; + + gpu_props->raw_props.thread_max_barrier_size = regdump.thread_max_barrier_size; + gpu_props->raw_props.thread_max_threads = regdump.thread_max_threads; + gpu_props->raw_props.thread_max_workgroup_size = regdump.thread_max_workgroup_size; + gpu_props->raw_props.thread_features = regdump.thread_features; +} + +void kbase_gpuprops_update_core_props_gpu_id(base_gpu_props * const gpu_props) +{ + gpu_props->core_props.version_status = + KBASE_UBFX32(gpu_props->raw_props.gpu_id, 0U, 4); + gpu_props->core_props.minor_revision = + KBASE_UBFX32(gpu_props->raw_props.gpu_id, 4U, 8); + gpu_props->core_props.major_revision = + KBASE_UBFX32(gpu_props->raw_props.gpu_id, 12U, 4); + gpu_props->core_props.product_id = + KBASE_UBFX32(gpu_props->raw_props.gpu_id, 16U, 16); +} + +/** + * kbase_gpuprops_calculate_props - Calculate the derived properties + * @gpu_props: The &base_gpu_props structure + * @kbdev: The &struct kbase_device structure for the device + * + * Fill the &base_gpu_props structure with values derived from the GPU + * configuration registers + */ +static void kbase_gpuprops_calculate_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + int i; + + /* Populate the base_gpu_props structure */ + kbase_gpuprops_update_core_props_gpu_id(gpu_props); + gpu_props->core_props.log2_program_counter_size = KBASE_GPU_PC_SIZE_LOG2; + gpu_props->core_props.gpu_available_memory_size = totalram_pages << PAGE_SHIFT; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i]; + + gpu_props->l2_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 0U, 8); + gpu_props->l2_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 16U, 8); + + /* Field with number of l2 slices is added to MEM_FEATURES register + * since t76x. Below code assumes that for older GPU reserved bits will + * be read as zero. */ + gpu_props->l2_props.num_l2_slices = + KBASE_UBFX32(gpu_props->raw_props.mem_features, 8U, 4) + 1; + + gpu_props->tiler_props.bin_size_bytes = 1 << KBASE_UBFX32(gpu_props->raw_props.tiler_features, 0U, 6); + gpu_props->tiler_props.max_active_levels = KBASE_UBFX32(gpu_props->raw_props.tiler_features, 8U, 4); + + if (gpu_props->raw_props.thread_max_threads == 0) + gpu_props->thread_props.max_threads = THREAD_MT_DEFAULT; + else + gpu_props->thread_props.max_threads = gpu_props->raw_props.thread_max_threads; + + if (gpu_props->raw_props.thread_max_workgroup_size == 0) + gpu_props->thread_props.max_workgroup_size = THREAD_MWS_DEFAULT; + else + gpu_props->thread_props.max_workgroup_size = gpu_props->raw_props.thread_max_workgroup_size; + + if (gpu_props->raw_props.thread_max_barrier_size == 0) + gpu_props->thread_props.max_barrier_size = THREAD_MBS_DEFAULT; + else + gpu_props->thread_props.max_barrier_size = gpu_props->raw_props.thread_max_barrier_size; + + gpu_props->thread_props.max_registers = KBASE_UBFX32(gpu_props->raw_props.thread_features, 0U, 16); + gpu_props->thread_props.max_task_queue = KBASE_UBFX32(gpu_props->raw_props.thread_features, 16U, 8); + gpu_props->thread_props.max_thread_group_split = KBASE_UBFX32(gpu_props->raw_props.thread_features, 24U, 6); + gpu_props->thread_props.impl_tech = KBASE_UBFX32(gpu_props->raw_props.thread_features, 30U, 2); + + /* If values are not specified, then use defaults */ + if (gpu_props->thread_props.max_registers == 0) { + gpu_props->thread_props.max_registers = THREAD_MR_DEFAULT; + gpu_props->thread_props.max_task_queue = THREAD_MTQ_DEFAULT; + gpu_props->thread_props.max_thread_group_split = THREAD_MTGS_DEFAULT; + } + /* Initialize the coherent_group structure for each group */ + kbase_gpuprops_construct_coherent_groups(gpu_props); +} + +void kbase_gpuprops_set(struct kbase_device *kbdev) +{ + struct kbase_gpu_props *gpu_props; + struct gpu_raw_gpu_props *raw; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + gpu_props = &kbdev->gpu_props; + raw = &gpu_props->props.raw_props; + + /* Initialize the base_gpu_props structure from the hardware */ + kbase_gpuprops_get_props(&gpu_props->props, kbdev); + + /* Populate the derived properties */ + kbase_gpuprops_calculate_props(&gpu_props->props, kbdev); + + /* Populate kbase-only fields */ + gpu_props->l2_props.associativity = KBASE_UBFX32(raw->l2_features, 8U, 8); + gpu_props->l2_props.external_bus_width = KBASE_UBFX32(raw->l2_features, 24U, 8); + + gpu_props->mem.core_group = KBASE_UBFX32(raw->mem_features, 0U, 1); + + gpu_props->mmu.va_bits = KBASE_UBFX32(raw->mmu_features, 0U, 8); + gpu_props->mmu.pa_bits = KBASE_UBFX32(raw->mmu_features, 8U, 8); + + gpu_props->num_cores = hweight64(raw->shader_present); + gpu_props->num_core_groups = hweight64(raw->l2_present); + gpu_props->num_address_spaces = hweight32(raw->as_present); + gpu_props->num_job_slots = hweight32(raw->js_present); +} + +void kbase_gpuprops_set_features(struct kbase_device *kbdev) +{ + base_gpu_props *gpu_props; + struct kbase_gpuprops_regdump regdump; + + gpu_props = &kbdev->gpu_props.props; + + /* Dump relevant registers */ + kbase_backend_gpuprops_get_features(kbdev, ®dump); + + /* + * Copy the raw value from the register, later this will get turned + * into the selected coherency mode. + * Additionally, add non-coherent mode, as this is always supported. + */ + gpu_props->raw_props.coherency_mode = regdump.coherency_features | + COHERENCY_FEATURE_BIT(COHERENCY_NONE); +} + +static struct { + u32 type; + size_t offset; + int size; +} gpu_property_mapping[] = { +#define PROP(name, member) \ + {KBASE_GPUPROP_ ## name, offsetof(struct mali_base_gpu_props, member), \ + sizeof(((struct mali_base_gpu_props *)0)->member)} + PROP(PRODUCT_ID, core_props.product_id), + PROP(VERSION_STATUS, core_props.version_status), + PROP(MINOR_REVISION, core_props.minor_revision), + PROP(MAJOR_REVISION, core_props.major_revision), + PROP(GPU_SPEED_MHZ, core_props.gpu_speed_mhz), + PROP(GPU_FREQ_KHZ_MAX, core_props.gpu_freq_khz_max), + PROP(GPU_FREQ_KHZ_MIN, core_props.gpu_freq_khz_min), + PROP(LOG2_PROGRAM_COUNTER_SIZE, core_props.log2_program_counter_size), + PROP(TEXTURE_FEATURES_0, core_props.texture_features[0]), + PROP(TEXTURE_FEATURES_1, core_props.texture_features[1]), + PROP(TEXTURE_FEATURES_2, core_props.texture_features[2]), + PROP(GPU_AVAILABLE_MEMORY_SIZE, core_props.gpu_available_memory_size), + + PROP(L2_LOG2_LINE_SIZE, l2_props.log2_line_size), + PROP(L2_LOG2_CACHE_SIZE, l2_props.log2_cache_size), + PROP(L2_NUM_L2_SLICES, l2_props.num_l2_slices), + + PROP(TILER_BIN_SIZE_BYTES, tiler_props.bin_size_bytes), + PROP(TILER_MAX_ACTIVE_LEVELS, tiler_props.max_active_levels), + + PROP(MAX_THREADS, thread_props.max_threads), + PROP(MAX_WORKGROUP_SIZE, thread_props.max_workgroup_size), + PROP(MAX_BARRIER_SIZE, thread_props.max_barrier_size), + PROP(MAX_REGISTERS, thread_props.max_registers), + PROP(MAX_TASK_QUEUE, thread_props.max_task_queue), + PROP(MAX_THREAD_GROUP_SPLIT, thread_props.max_thread_group_split), + PROP(IMPL_TECH, thread_props.impl_tech), + + PROP(RAW_SHADER_PRESENT, raw_props.shader_present), + PROP(RAW_TILER_PRESENT, raw_props.tiler_present), + PROP(RAW_L2_PRESENT, raw_props.l2_present), + PROP(RAW_STACK_PRESENT, raw_props.stack_present), + PROP(RAW_L2_FEATURES, raw_props.l2_features), + PROP(RAW_SUSPEND_SIZE, raw_props.suspend_size), + PROP(RAW_MEM_FEATURES, raw_props.mem_features), + PROP(RAW_MMU_FEATURES, raw_props.mmu_features), + PROP(RAW_AS_PRESENT, raw_props.as_present), + PROP(RAW_JS_PRESENT, raw_props.js_present), + PROP(RAW_JS_FEATURES_0, raw_props.js_features[0]), + PROP(RAW_JS_FEATURES_1, raw_props.js_features[1]), + PROP(RAW_JS_FEATURES_2, raw_props.js_features[2]), + PROP(RAW_JS_FEATURES_3, raw_props.js_features[3]), + PROP(RAW_JS_FEATURES_4, raw_props.js_features[4]), + PROP(RAW_JS_FEATURES_5, raw_props.js_features[5]), + PROP(RAW_JS_FEATURES_6, raw_props.js_features[6]), + PROP(RAW_JS_FEATURES_7, raw_props.js_features[7]), + PROP(RAW_JS_FEATURES_8, raw_props.js_features[8]), + PROP(RAW_JS_FEATURES_9, raw_props.js_features[9]), + PROP(RAW_JS_FEATURES_10, raw_props.js_features[10]), + PROP(RAW_JS_FEATURES_11, raw_props.js_features[11]), + PROP(RAW_JS_FEATURES_12, raw_props.js_features[12]), + PROP(RAW_JS_FEATURES_13, raw_props.js_features[13]), + PROP(RAW_JS_FEATURES_14, raw_props.js_features[14]), + PROP(RAW_JS_FEATURES_15, raw_props.js_features[15]), + PROP(RAW_TILER_FEATURES, raw_props.tiler_features), + PROP(RAW_TEXTURE_FEATURES_0, raw_props.texture_features[0]), + PROP(RAW_TEXTURE_FEATURES_1, raw_props.texture_features[1]), + PROP(RAW_TEXTURE_FEATURES_2, raw_props.texture_features[2]), + PROP(RAW_GPU_ID, raw_props.gpu_id), + PROP(RAW_THREAD_MAX_THREADS, raw_props.thread_max_threads), + PROP(RAW_THREAD_MAX_WORKGROUP_SIZE, + raw_props.thread_max_workgroup_size), + PROP(RAW_THREAD_MAX_BARRIER_SIZE, raw_props.thread_max_barrier_size), + PROP(RAW_THREAD_FEATURES, raw_props.thread_features), + PROP(RAW_COHERENCY_MODE, raw_props.coherency_mode), + + PROP(COHERENCY_NUM_GROUPS, coherency_info.num_groups), + PROP(COHERENCY_NUM_CORE_GROUPS, coherency_info.num_core_groups), + PROP(COHERENCY_COHERENCY, coherency_info.coherency), + PROP(COHERENCY_GROUP_0, coherency_info.group[0].core_mask), + PROP(COHERENCY_GROUP_1, coherency_info.group[1].core_mask), + PROP(COHERENCY_GROUP_2, coherency_info.group[2].core_mask), + PROP(COHERENCY_GROUP_3, coherency_info.group[3].core_mask), + PROP(COHERENCY_GROUP_4, coherency_info.group[4].core_mask), + PROP(COHERENCY_GROUP_5, coherency_info.group[5].core_mask), + PROP(COHERENCY_GROUP_6, coherency_info.group[6].core_mask), + PROP(COHERENCY_GROUP_7, coherency_info.group[7].core_mask), + PROP(COHERENCY_GROUP_8, coherency_info.group[8].core_mask), + PROP(COHERENCY_GROUP_9, coherency_info.group[9].core_mask), + PROP(COHERENCY_GROUP_10, coherency_info.group[10].core_mask), + PROP(COHERENCY_GROUP_11, coherency_info.group[11].core_mask), + PROP(COHERENCY_GROUP_12, coherency_info.group[12].core_mask), + PROP(COHERENCY_GROUP_13, coherency_info.group[13].core_mask), + PROP(COHERENCY_GROUP_14, coherency_info.group[14].core_mask), + PROP(COHERENCY_GROUP_15, coherency_info.group[15].core_mask), + +#undef PROP +}; + +int kbase_gpuprops_populate_user_buffer(struct kbase_device *kbdev) +{ + struct kbase_gpu_props *kprops = &kbdev->gpu_props; + struct mali_base_gpu_props *props = &kprops->props; + u32 count = ARRAY_SIZE(gpu_property_mapping); + u32 i; + u32 size = 0; + u8 *p; + + for (i = 0; i < count; i++) { + /* 4 bytes for the ID, and the size of the property */ + size += 4 + gpu_property_mapping[i].size; + } + + kprops->prop_buffer_size = size; + kprops->prop_buffer = kmalloc(size, GFP_KERNEL); + + if (!kprops->prop_buffer) { + kprops->prop_buffer_size = 0; + return -ENOMEM; + } + + p = kprops->prop_buffer; + +#define WRITE_U8(v) (*p++ = (v) & 0xFF) +#define WRITE_U16(v) do { WRITE_U8(v); WRITE_U8((v) >> 8); } while (0) +#define WRITE_U32(v) do { WRITE_U16(v); WRITE_U16((v) >> 16); } while (0) +#define WRITE_U64(v) do { WRITE_U32(v); WRITE_U32((v) >> 32); } while (0) + + for (i = 0; i < count; i++) { + u32 type = gpu_property_mapping[i].type; + u8 type_size; + void *field = ((u8 *)props) + gpu_property_mapping[i].offset; + + switch (gpu_property_mapping[i].size) { + case 1: + type_size = KBASE_GPUPROP_VALUE_SIZE_U8; + break; + case 2: + type_size = KBASE_GPUPROP_VALUE_SIZE_U16; + break; + case 4: + type_size = KBASE_GPUPROP_VALUE_SIZE_U32; + break; + case 8: + type_size = KBASE_GPUPROP_VALUE_SIZE_U64; + break; + default: + dev_err(kbdev->dev, + "Invalid gpu_property_mapping type=%d size=%d", + type, gpu_property_mapping[i].size); + return -EINVAL; + } + + WRITE_U32((type<<2) | type_size); + + switch (type_size) { + case KBASE_GPUPROP_VALUE_SIZE_U8: + WRITE_U8(*((u8 *)field)); + break; + case KBASE_GPUPROP_VALUE_SIZE_U16: + WRITE_U16(*((u16 *)field)); + break; + case KBASE_GPUPROP_VALUE_SIZE_U32: + WRITE_U32(*((u32 *)field)); + break; + case KBASE_GPUPROP_VALUE_SIZE_U64: + WRITE_U64(*((u64 *)field)); + break; + default: /* Cannot be reached */ + WARN_ON(1); + return -EINVAL; + } + } + + return 0; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.h b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.h new file mode 100644 index 000000000000..57b3eaf9cd53 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.h @@ -0,0 +1,84 @@ +/* + * + * (C) COPYRIGHT 2011-2015,2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_H_ +#define _KBASE_GPUPROPS_H_ + +#include "mali_kbase_gpuprops_types.h" + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +/** + * @brief Set up Kbase GPU properties. + * + * Set up Kbase GPU properties with information from the GPU registers + * + * @param kbdev The struct kbase_device structure for the device + */ +void kbase_gpuprops_set(struct kbase_device *kbdev); + +/** + * kbase_gpuprops_set_features - Set up Kbase GPU properties + * @kbdev: Device pointer + * + * This function sets up GPU properties that are dependent on the hardware + * features bitmask. This function must be preceeded by a call to + * kbase_hw_set_features_mask(). + */ +void kbase_gpuprops_set_features(struct kbase_device *kbdev); + +/** + * @brief Provide GPU properties to userside through UKU call. + * + * Fill the struct kbase_uk_gpuprops with values from GPU configuration registers. + * + * @param kctx The struct kbase_context structure + * @param kbase_props A copy of the struct kbase_uk_gpuprops structure from userspace + * + * @return 0 on success. Any other value indicates failure. + */ +int kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props); + +/** + * kbase_gpuprops_populate_user_buffer - Populate the GPU properties buffer + * @kbdev: The kbase device + * + * Fills kbdev->gpu_props->prop_buffer with the GPU properties for user + * space to read. + */ +int kbase_gpuprops_populate_user_buffer(struct kbase_device *kbdev); + +/** + * kbase_gpuprops_update_core_props_gpu_id - break down gpu id value + * @gpu_props: the &base_gpu_props structure + * + * Break down gpu_id value stored in base_gpu_props::raw_props.gpu_id into + * separate fields (version_status, minor_revision, major_revision, product_id) + * stored in base_gpu_props::core_props. + */ +void kbase_gpuprops_update_core_props_gpu_id(base_gpu_props * const gpu_props); + + +#endif /* _KBASE_GPUPROPS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops_types.h b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops_types.h new file mode 100644 index 000000000000..10794fc27318 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops_types.h @@ -0,0 +1,92 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops_types.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_TYPES_H_ +#define _KBASE_GPUPROPS_TYPES_H_ + +#include "mali_base_kernel.h" + +#define KBASE_GPU_SPEED_MHZ 123 +#define KBASE_GPU_PC_SIZE_LOG2 24U + +struct kbase_gpuprops_regdump { + u32 gpu_id; + u32 l2_features; + u32 suspend_size; /* API 8.2+ */ + u32 tiler_features; + u32 mem_features; + u32 mmu_features; + u32 as_present; + u32 js_present; + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + u32 js_features[GPU_MAX_JOB_SLOTS]; + u32 shader_present_lo; + u32 shader_present_hi; + u32 tiler_present_lo; + u32 tiler_present_hi; + u32 l2_present_lo; + u32 l2_present_hi; + u32 stack_present_lo; + u32 stack_present_hi; + u32 coherency_features; +}; + +struct kbase_gpu_cache_props { + u8 associativity; + u8 external_bus_width; +}; + +struct kbase_gpu_mem_props { + u8 core_group; +}; + +struct kbase_gpu_mmu_props { + u8 va_bits; + u8 pa_bits; +}; + +struct kbase_gpu_props { + /* kernel-only properties */ + u8 num_cores; + u8 num_core_groups; + u8 num_address_spaces; + u8 num_job_slots; + + struct kbase_gpu_cache_props l2_props; + + struct kbase_gpu_mem_props mem; + struct kbase_gpu_mmu_props mmu; + + /* Properties shared with userspace */ + base_gpu_props props; + + u32 prop_buffer_size; + void *prop_buffer; +}; + +#endif /* _KBASE_GPUPROPS_TYPES_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hw.c b/drivers/gpu/arm/bifrost/mali_kbase_hw.c new file mode 100644 index 000000000000..eb8368ccee5e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hw.c @@ -0,0 +1,446 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Run-time work-arounds helpers + */ + +#include +#include +#include +#include "mali_kbase.h" +#include "mali_kbase_hw.h" + +void kbase_hw_set_features_mask(struct kbase_device *kbdev) +{ + const enum base_hw_feature *features; + u32 gpu_id; + u32 product_id; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + product_id = gpu_id & GPU_ID_VERSION_PRODUCT_ID; + product_id >>= GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + if (GPU_ID_IS_NEW_FORMAT(product_id)) { + switch (gpu_id & GPU_ID2_PRODUCT_MODEL) { + case GPU_ID2_PRODUCT_TMIX: + features = base_hw_features_tMIx; + break; + case GPU_ID2_PRODUCT_THEX: + features = base_hw_features_tHEx; + break; + case GPU_ID2_PRODUCT_TSIX: + features = base_hw_features_tSIx; + break; + case GPU_ID2_PRODUCT_TDVX: + features = base_hw_features_tDVx; + break; + default: + features = base_hw_features_generic; + break; + } + } else { + switch (product_id) { + case GPU_ID_PI_TFRX: + /* FALLTHROUGH */ + case GPU_ID_PI_T86X: + features = base_hw_features_tFxx; + break; + case GPU_ID_PI_T83X: + features = base_hw_features_t83x; + break; + case GPU_ID_PI_T82X: + features = base_hw_features_t82x; + break; + case GPU_ID_PI_T76X: + features = base_hw_features_t76x; + break; + case GPU_ID_PI_T72X: + features = base_hw_features_t72x; + break; + case GPU_ID_PI_T62X: + features = base_hw_features_t62x; + break; + case GPU_ID_PI_T60X: + features = base_hw_features_t60x; + break; + default: + features = base_hw_features_generic; + break; + } + } + + for (; *features != BASE_HW_FEATURE_END; features++) + set_bit(*features, &kbdev->hw_features_mask[0]); +} + +/** + * kbase_hw_get_issues_for_new_id - Get the hardware issues for a new GPU ID + * @kbdev: Device pointer + * + * Return: pointer to an array of hardware issues, terminated by + * BASE_HW_ISSUE_END. + * + * This function can only be used on new-format GPU IDs, i.e. those for which + * GPU_ID_IS_NEW_FORMAT evaluates as true. The GPU ID is read from the @kbdev. + * + * In debugging versions of the driver, unknown versions of a known GPU will + * be treated as the most recent known version not later than the actual + * version. In such circumstances, the GPU ID in @kbdev will also be replaced + * with the most recent known version. + * + * Note: The GPU configuration must have been read by kbase_gpuprops_get_props() + * before calling this function. + */ +static const enum base_hw_issue *kbase_hw_get_issues_for_new_id( + struct kbase_device *kbdev) +{ + const enum base_hw_issue *issues = NULL; + + struct base_hw_product { + u32 product_model; + struct { + u32 version; + const enum base_hw_issue *issues; + } map[7]; + }; + + static const struct base_hw_product base_hw_products[] = { + {GPU_ID2_PRODUCT_TMIX, + {{GPU_ID2_VERSION_MAKE(0, 0, 1), + base_hw_issues_tMIx_r0p0_05dev0}, + {GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tMIx_r0p0}, + {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tMIx_r0p1}, + {U32_MAX /* sentinel value */, NULL} } }, + + {GPU_ID2_PRODUCT_THEX, + {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tHEx_r0p0}, + {GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tHEx_r0p0}, + {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tHEx_r0p1}, + {GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tHEx_r0p1}, + {GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tHEx_r0p2}, + {GPU_ID2_VERSION_MAKE(0, 3, 0), base_hw_issues_tHEx_r0p3}, + {U32_MAX, NULL} } }, + + {GPU_ID2_PRODUCT_TSIX, + {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tSIx_r0p0}, + {GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tSIx_r0p0}, + {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tSIx_r0p1}, + {GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tSIx_r1p0}, + {GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tSIx_r1p1}, + {U32_MAX, NULL} } }, + + {GPU_ID2_PRODUCT_TDVX, + {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDVx_r0p0}, + {U32_MAX, NULL} } }, + + + + + }; + + u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + const u32 product_model = gpu_id & GPU_ID2_PRODUCT_MODEL; + const struct base_hw_product *product = NULL; + size_t p; + + /* Stop when we reach the end of the products array. */ + for (p = 0; p < ARRAY_SIZE(base_hw_products); ++p) { + if (product_model == base_hw_products[p].product_model) { + product = &base_hw_products[p]; + break; + } + } + + if (product != NULL) { + /* Found a matching product. */ + const u32 version = gpu_id & GPU_ID2_VERSION; +#if !MALI_CUSTOMER_RELEASE + u32 fallback_version = 0; + const enum base_hw_issue *fallback_issues = NULL; +#endif + size_t v; + + /* Stop when we reach the end of the map. */ + for (v = 0; product->map[v].version != U32_MAX; ++v) { + + if (version == product->map[v].version) { + /* Exact match so stop. */ + issues = product->map[v].issues; + break; + } + +#if !MALI_CUSTOMER_RELEASE + /* Check whether this is a candidate for most recent + known version not later than the actual + version. */ + if ((version > product->map[v].version) && + (product->map[v].version >= fallback_version)) { + fallback_version = product->map[v].version; + fallback_issues = product->map[v].issues; + } +#endif + } + +#if !MALI_CUSTOMER_RELEASE + if ((issues == NULL) && (fallback_issues != NULL)) { + /* Fall back to the issue set of the most recent known + version not later than the actual version. */ + issues = fallback_issues; + + dev_info(kbdev->dev, + "r%dp%d status %d is unknown; treating as r%dp%d status %d", + (gpu_id & GPU_ID2_VERSION_MAJOR) >> + GPU_ID2_VERSION_MAJOR_SHIFT, + (gpu_id & GPU_ID2_VERSION_MINOR) >> + GPU_ID2_VERSION_MINOR_SHIFT, + (gpu_id & GPU_ID2_VERSION_STATUS) >> + GPU_ID2_VERSION_STATUS_SHIFT, + (fallback_version & GPU_ID2_VERSION_MAJOR) >> + GPU_ID2_VERSION_MAJOR_SHIFT, + (fallback_version & GPU_ID2_VERSION_MINOR) >> + GPU_ID2_VERSION_MINOR_SHIFT, + (fallback_version & GPU_ID2_VERSION_STATUS) >> + GPU_ID2_VERSION_STATUS_SHIFT); + + gpu_id &= ~GPU_ID2_VERSION; + gpu_id |= fallback_version; + kbdev->gpu_props.props.raw_props.gpu_id = gpu_id; + + kbase_gpuprops_update_core_props_gpu_id( + &kbdev->gpu_props.props); + } +#endif + } + return issues; +} + +int kbase_hw_set_issues_mask(struct kbase_device *kbdev) +{ + const enum base_hw_issue *issues; + u32 gpu_id; + u32 product_id; + u32 impl_tech; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + product_id = gpu_id & GPU_ID_VERSION_PRODUCT_ID; + product_id >>= GPU_ID_VERSION_PRODUCT_ID_SHIFT; + impl_tech = kbdev->gpu_props.props.thread_props.impl_tech; + + if (impl_tech != IMPLEMENTATION_MODEL) { + if (GPU_ID_IS_NEW_FORMAT(product_id)) { + issues = kbase_hw_get_issues_for_new_id(kbdev); + if (issues == NULL) { + dev_err(kbdev->dev, + "Unknown GPU ID %x", gpu_id); + return -EINVAL; + } + +#if !MALI_CUSTOMER_RELEASE + /* The GPU ID might have been replaced with the last + known version of the same GPU. */ + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; +#endif + + } else { + switch (gpu_id) { + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0): + issues = base_hw_issues_t60x_r0p0_15dev0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC): + issues = base_hw_issues_t60x_r0p0_eac; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0): + issues = base_hw_issues_t60x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0): + issues = base_hw_issues_t62x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 1): + issues = base_hw_issues_t62x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 1, 0): + issues = base_hw_issues_t62x_r1p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 0, 1): + issues = base_hw_issues_t76x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 1): + issues = base_hw_issues_t76x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 9): + issues = base_hw_issues_t76x_r0p1_50rel0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 2, 1): + issues = base_hw_issues_t76x_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 3, 1): + issues = base_hw_issues_t76x_r0p3; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 1, 0, 0): + issues = base_hw_issues_t76x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 1): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 2): + issues = base_hw_issues_t72x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 0, 0): + issues = base_hw_issues_t72x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 1, 0): + issues = base_hw_issues_t72x_r1p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 1, 2): + issues = base_hw_issues_tFRx_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 2, 0): + issues = base_hw_issues_tFRx_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 1, 0, 8): + issues = base_hw_issues_tFRx_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 2, 0, 0): + issues = base_hw_issues_tFRx_r2p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 0, 2, 0): + issues = base_hw_issues_t86x_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T86X, 1, 0, 8): + issues = base_hw_issues_t86x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 2, 0, 0): + issues = base_hw_issues_t86x_r2p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T83X, 0, 1, 0): + issues = base_hw_issues_t83x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T83X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T83X, 1, 0, 8): + issues = base_hw_issues_t83x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T82X, 0, 0, 0): + issues = base_hw_issues_t82x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T82X, 0, 1, 0): + issues = base_hw_issues_t82x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T82X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T82X, 1, 0, 8): + issues = base_hw_issues_t82x_r1p0; + break; + default: + dev_err(kbdev->dev, + "Unknown GPU ID %x", gpu_id); + return -EINVAL; + } + } + } else { + /* Software model */ + if (GPU_ID_IS_NEW_FORMAT(product_id)) { + switch (gpu_id & GPU_ID2_PRODUCT_MODEL) { + case GPU_ID2_PRODUCT_TMIX: + issues = base_hw_issues_model_tMIx; + break; + case GPU_ID2_PRODUCT_THEX: + issues = base_hw_issues_model_tHEx; + break; + case GPU_ID2_PRODUCT_TSIX: + issues = base_hw_issues_model_tSIx; + break; + case GPU_ID2_PRODUCT_TDVX: + issues = base_hw_issues_model_tDVx; + break; + default: + dev_err(kbdev->dev, + "Unknown GPU ID %x", gpu_id); + return -EINVAL; + } + } else { + switch (product_id) { + case GPU_ID_PI_T60X: + issues = base_hw_issues_model_t60x; + break; + case GPU_ID_PI_T62X: + issues = base_hw_issues_model_t62x; + break; + case GPU_ID_PI_T72X: + issues = base_hw_issues_model_t72x; + break; + case GPU_ID_PI_T76X: + issues = base_hw_issues_model_t76x; + break; + case GPU_ID_PI_TFRX: + issues = base_hw_issues_model_tFRx; + break; + case GPU_ID_PI_T86X: + issues = base_hw_issues_model_t86x; + break; + case GPU_ID_PI_T83X: + issues = base_hw_issues_model_t83x; + break; + case GPU_ID_PI_T82X: + issues = base_hw_issues_model_t82x; + break; + default: + dev_err(kbdev->dev, "Unknown GPU ID %x", + gpu_id); + return -EINVAL; + } + } + } + + if (GPU_ID_IS_NEW_FORMAT(product_id)) { + dev_info(kbdev->dev, + "GPU identified as 0x%x arch %d.%d.%d r%dp%d status %d", + (gpu_id & GPU_ID2_PRODUCT_MAJOR) >> + GPU_ID2_PRODUCT_MAJOR_SHIFT, + (gpu_id & GPU_ID2_ARCH_MAJOR) >> + GPU_ID2_ARCH_MAJOR_SHIFT, + (gpu_id & GPU_ID2_ARCH_MINOR) >> + GPU_ID2_ARCH_MINOR_SHIFT, + (gpu_id & GPU_ID2_ARCH_REV) >> + GPU_ID2_ARCH_REV_SHIFT, + (gpu_id & GPU_ID2_VERSION_MAJOR) >> + GPU_ID2_VERSION_MAJOR_SHIFT, + (gpu_id & GPU_ID2_VERSION_MINOR) >> + GPU_ID2_VERSION_MINOR_SHIFT, + (gpu_id & GPU_ID2_VERSION_STATUS) >> + GPU_ID2_VERSION_STATUS_SHIFT); + } else { + dev_info(kbdev->dev, + "GPU identified as 0x%04x r%dp%d status %d", + (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> + GPU_ID_VERSION_PRODUCT_ID_SHIFT, + (gpu_id & GPU_ID_VERSION_MAJOR) >> + GPU_ID_VERSION_MAJOR_SHIFT, + (gpu_id & GPU_ID_VERSION_MINOR) >> + GPU_ID_VERSION_MINOR_SHIFT, + (gpu_id & GPU_ID_VERSION_STATUS) >> + GPU_ID_VERSION_STATUS_SHIFT); + } + + for (; *issues != BASE_HW_ISSUE_END; issues++) + set_bit(*issues, &kbdev->hw_issues_mask[0]); + + return 0; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hw.h b/drivers/gpu/arm/bifrost/mali_kbase_hw.h new file mode 100644 index 000000000000..754250ce968d --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hw.h @@ -0,0 +1,65 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Run-time work-arounds helpers + */ + +#ifndef _KBASE_HW_H_ +#define _KBASE_HW_H_ + +#include "mali_kbase_defs.h" + +/** + * @brief Tell whether a work-around should be enabled + */ +#define kbase_hw_has_issue(kbdev, issue)\ + test_bit(issue, &(kbdev)->hw_issues_mask[0]) + +/** + * @brief Tell whether a feature is supported + */ +#define kbase_hw_has_feature(kbdev, feature)\ + test_bit(feature, &(kbdev)->hw_features_mask[0]) + +/** + * kbase_hw_set_issues_mask - Set the hardware issues mask based on the GPU ID + * @kbdev: Device pointer + * + * Return: 0 if the GPU ID was recognized, otherwise -EINVAL. + * + * The GPU ID is read from the @kbdev. + * + * In debugging versions of the driver, unknown versions of a known GPU with a + * new-format ID will be treated as the most recent known version not later + * than the actual version. In such circumstances, the GPU ID in @kbdev will + * also be replaced with the most recent known version. + * + * Note: The GPU configuration must have been read by + * kbase_gpuprops_get_props() before calling this function. + */ +int kbase_hw_set_issues_mask(struct kbase_device *kbdev); + +/** + * @brief Set the features mask depending on the GPU ID + */ +void kbase_hw_set_features_mask(struct kbase_device *kbdev); + +#endif /* _KBASE_HW_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_backend.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_backend.h new file mode 100644 index 000000000000..b09be99e6b4e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_backend.h @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * HW access backend common APIs + */ + +#ifndef _KBASE_HWACCESS_BACKEND_H_ +#define _KBASE_HWACCESS_BACKEND_H_ + +/** + * kbase_backend_early_init - Perform any backend-specific initialization. + * @kbdev: Device pointer + * + * Return: 0 on success, or an error code on failure. + */ +int kbase_backend_early_init(struct kbase_device *kbdev); + +/** + * kbase_backend_late_init - Perform any backend-specific initialization. + * @kbdev: Device pointer + * + * Return: 0 on success, or an error code on failure. + */ +int kbase_backend_late_init(struct kbase_device *kbdev); + +/** + * kbase_backend_early_term - Perform any backend-specific termination. + * @kbdev: Device pointer + */ +void kbase_backend_early_term(struct kbase_device *kbdev); + +/** + * kbase_backend_late_term - Perform any backend-specific termination. + * @kbdev: Device pointer + */ +void kbase_backend_late_term(struct kbase_device *kbdev); + +#endif /* _KBASE_HWACCESS_BACKEND_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_defs.h new file mode 100644 index 000000000000..0acf297192fd --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_defs.h @@ -0,0 +1,36 @@ +/* + * + * (C) COPYRIGHT 2014, 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * @file mali_kbase_hwaccess_gpu_defs.h + * HW access common definitions + */ + +#ifndef _KBASE_HWACCESS_DEFS_H_ +#define _KBASE_HWACCESS_DEFS_H_ + +#include + +/* The hwaccess_lock (a spinlock) must be held when accessing this structure */ +struct kbase_hwaccess_data { + struct kbase_context *active_kctx; + + struct kbase_backend_data backend; +}; + +#endif /* _KBASE_HWACCESS_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_gpuprops.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_gpuprops.h new file mode 100644 index 000000000000..cf8a8131c22e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_gpuprops.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * Base kernel property query backend APIs + */ + +#ifndef _KBASE_HWACCESS_GPUPROPS_H_ +#define _KBASE_HWACCESS_GPUPROPS_H_ + +/** + * kbase_backend_gpuprops_get() - Fill @regdump with GPU properties read from + * GPU + * @kbdev: Device pointer + * @regdump: Pointer to struct kbase_gpuprops_regdump structure + */ +void kbase_backend_gpuprops_get(struct kbase_device *kbdev, + struct kbase_gpuprops_regdump *regdump); + +/** + * kbase_backend_gpuprops_get - Fill @regdump with GPU properties read from GPU + * @kbdev: Device pointer + * @regdump: Pointer to struct kbase_gpuprops_regdump structure + * + * This function reads GPU properties that are dependent on the hardware + * features bitmask + */ +void kbase_backend_gpuprops_get_features(struct kbase_device *kbdev, + struct kbase_gpuprops_regdump *regdump); + + +#endif /* _KBASE_HWACCESS_GPUPROPS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_instr.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_instr.h new file mode 100644 index 000000000000..5de2b7535bb4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_instr.h @@ -0,0 +1,116 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * HW Access instrumentation common APIs + */ + +#ifndef _KBASE_HWACCESS_INSTR_H_ +#define _KBASE_HWACCESS_INSTR_H_ + +#include + +/** + * kbase_instr_hwcnt_enable_internal - Enable HW counters collection + * @kbdev: Kbase device + * @kctx: Kbase context + * @setup: HW counter setup parameters + * + * Context: might sleep, waiting for reset to complete + * + * Return: 0 on success + */ +int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbase_uk_hwcnt_setup *setup); + +/** + * kbase_instr_hwcnt_disable_internal - Disable HW counters collection + * @kctx: Kbase context + * + * Context: might sleep, waiting for an ongoing dump to complete + * + * Return: 0 on success + */ +int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx); + +/** + * kbase_instr_hwcnt_request_dump() - Request HW counter dump from GPU + * @kctx: Kbase context + * + * Caller must either wait for kbase_instr_hwcnt_dump_complete() to return true, + * of call kbase_instr_hwcnt_wait_for_dump(). + * + * Return: 0 on success + */ +int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx); + +/** + * kbase_instr_hwcnt_wait_for_dump() - Wait until pending HW counter dump has + * completed. + * @kctx: Kbase context + * + * Context: will sleep, waiting for dump to complete + * + * Return: 0 on success + */ +int kbase_instr_hwcnt_wait_for_dump(struct kbase_context *kctx); + +/** + * kbase_instr_hwcnt_dump_complete - Tell whether the HW counters dump has + * completed + * @kctx: Kbase context + * @success: Set to true if successful + * + * Context: does not sleep. + * + * Return: true if the dump is complete + */ +bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, + bool * const success); + +/** + * kbase_instr_hwcnt_clear() - Clear HW counters + * @kctx: Kbase context + * + * Context: might sleep, waiting for reset to complete + * + * Return: 0 on success + */ +int kbase_instr_hwcnt_clear(struct kbase_context *kctx); + +/** + * kbase_instr_backend_init() - Initialise the instrumentation backend + * @kbdev: Kbase device + * + * This function should be called during driver initialization. + * + * Return: 0 on success + */ +int kbase_instr_backend_init(struct kbase_device *kbdev); + +/** + * kbase_instr_backend_init() - Terminate the instrumentation backend + * @kbdev: Kbase device + * + * This function should be called during driver termination. + */ +void kbase_instr_backend_term(struct kbase_device *kbdev); + +#endif /* _KBASE_HWACCESS_INSTR_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_jm.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_jm.h new file mode 100644 index 000000000000..750fda2cd81d --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_jm.h @@ -0,0 +1,381 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * HW access job manager common APIs + */ + +#ifndef _KBASE_HWACCESS_JM_H_ +#define _KBASE_HWACCESS_JM_H_ + +/** + * kbase_backend_run_atom() - Run an atom on the GPU + * @kbdev: Device pointer + * @atom: Atom to run + * + * Caller must hold the HW access lock + */ +void kbase_backend_run_atom(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +/** + * kbase_backend_slot_update - Update state based on slot ringbuffers + * + * @kbdev: Device pointer + * + * Inspect the jobs in the slot ringbuffers and update state. + * + * This will cause jobs to be submitted to hardware if they are unblocked + */ +void kbase_backend_slot_update(struct kbase_device *kbdev); + +/** + * kbase_backend_find_and_release_free_address_space() - Release a free AS + * @kbdev: Device pointer + * @kctx: Context pointer + * + * This function can evict an idle context from the runpool, freeing up the + * address space it was using. + * + * The address space is marked as in use. The caller must either assign a + * context using kbase_gpu_use_ctx(), or release it using + * kbase_ctx_sched_release() + * + * Return: Number of free address space, or KBASEP_AS_NR_INVALID if none + * available + */ +int kbase_backend_find_and_release_free_address_space( + struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * kbase_backend_use_ctx() - Activate a currently unscheduled context, using the + * provided address space. + * @kbdev: Device pointer + * @kctx: Context pointer. May be NULL + * @as_nr: Free address space to use + * + * kbase_gpu_next_job() will pull atoms from the active context. + * + * Return: true if successful, false if ASID not assigned. + */ +bool kbase_backend_use_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx, + int as_nr); + +/** + * kbase_backend_use_ctx_sched() - Activate a context. + * @kbdev: Device pointer + * @kctx: Context pointer + * + * kbase_gpu_next_job() will pull atoms from the active context. + * + * The context must already be scheduled and assigned to an address space. If + * the context is not scheduled, then kbase_gpu_use_ctx() should be used + * instead. + * + * Caller must hold hwaccess_lock + * + * Return: true if context is now active, false otherwise (ie if context does + * not have an address space assigned) + */ +bool kbase_backend_use_ctx_sched(struct kbase_device *kbdev, + struct kbase_context *kctx); + +/** + * kbase_backend_release_ctx_irq - Release a context from the GPU. This will + * de-assign the assigned address space. + * @kbdev: Device pointer + * @kctx: Context pointer + * + * Caller must hold kbase_device->mmu_hw_mutex and hwaccess_lock + */ +void kbase_backend_release_ctx_irq(struct kbase_device *kbdev, + struct kbase_context *kctx); + +/** + * kbase_backend_release_ctx_noirq - Release a context from the GPU. This will + * de-assign the assigned address space. + * @kbdev: Device pointer + * @kctx: Context pointer + * + * Caller must hold kbase_device->mmu_hw_mutex + * + * This function must perform any operations that could not be performed in IRQ + * context by kbase_backend_release_ctx_irq(). + */ +void kbase_backend_release_ctx_noirq(struct kbase_device *kbdev, + struct kbase_context *kctx); + +/** + * kbase_backend_cacheclean - Perform a cache clean if the given atom requires + * one + * @kbdev: Device pointer + * @katom: Pointer to the failed atom + * + * On some GPUs, the GPU cache must be cleaned following a failed atom. This + * function performs a clean if it is required by @katom. + */ +void kbase_backend_cacheclean(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + + +/** + * kbase_backend_complete_wq() - Perform backend-specific actions required on + * completing an atom. + * @kbdev: Device pointer + * @katom: Pointer to the atom to complete + * + * This function should only be called from kbase_jd_done_worker() or + * js_return_worker(). + * + * Return: true if atom has completed, false if atom should be re-submitted + */ +void kbase_backend_complete_wq(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +/** + * kbase_backend_complete_wq_post_sched - Perform backend-specific actions + * required on completing an atom, after + * any scheduling has taken place. + * @kbdev: Device pointer + * @core_req: Core requirements of atom + * @affinity: Affinity of atom + * @coreref_state: Coreref state of atom + * + * This function should only be called from kbase_jd_done_worker() or + * js_return_worker(). + */ +void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev, + base_jd_core_req core_req, u64 affinity, + enum kbase_atom_coreref_state coreref_state); + +/** + * kbase_backend_reset() - The GPU is being reset. Cancel all jobs on the GPU + * and remove any others from the ringbuffers. + * @kbdev: Device pointer + * @end_timestamp: Timestamp of reset + */ +void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp); + +/** + * kbase_backend_inspect_head() - Return the atom currently at the head of slot + * @js + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return : Atom currently at the head of slot @js, or NULL + */ +struct kbase_jd_atom *kbase_backend_inspect_head(struct kbase_device *kbdev, + int js); + +/** + * kbase_backend_inspect_tail - Return the atom currently at the tail of slot + * @js + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return : Atom currently at the head of slot @js, or NULL + */ +struct kbase_jd_atom *kbase_backend_inspect_tail(struct kbase_device *kbdev, + int js); + +/** + * kbase_backend_nr_atoms_on_slot() - Return the number of atoms currently on a + * slot. + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return : Number of atoms currently on slot + */ +int kbase_backend_nr_atoms_on_slot(struct kbase_device *kbdev, int js); + +/** + * kbase_backend_nr_atoms_submitted() - Return the number of atoms on a slot + * that are currently on the GPU. + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return : Number of atoms currently on slot @js that are currently on the GPU. + */ +int kbase_backend_nr_atoms_submitted(struct kbase_device *kbdev, int js); + +/** + * kbase_backend_ctx_count_changed() - Number of contexts ready to submit jobs + * has changed. + * @kbdev: Device pointer + * + * Perform any required backend-specific actions (eg starting/stopping + * scheduling timers). + */ +void kbase_backend_ctx_count_changed(struct kbase_device *kbdev); + +/** + * kbase_backend_timeouts_changed() - Job Scheduler timeouts have changed. + * @kbdev: Device pointer + * + * Perform any required backend-specific actions (eg updating timeouts of + * currently running atoms). + */ +void kbase_backend_timeouts_changed(struct kbase_device *kbdev); + +/** + * kbase_backend_slot_free() - Return the number of jobs that can be currently + * submitted to slot @js. + * @kbdev: Device pointer + * @js: Job slot to inspect + * + * Return : Number of jobs that can be submitted. + */ +int kbase_backend_slot_free(struct kbase_device *kbdev, int js); + +/** + * kbase_job_check_enter_disjoint - potentially leave disjoint state + * @kbdev: kbase device + * @target_katom: atom which is finishing + * + * Work out whether to leave disjoint state when finishing an atom that was + * originated by kbase_job_check_enter_disjoint(). + */ +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom); + +/** + * kbase_backend_jm_kill_jobs_from_kctx - Kill all jobs that are currently + * running from a context + * @kctx: Context pointer + * + * This is used in response to a page fault to remove all jobs from the faulting + * context from the hardware. + */ +void kbase_backend_jm_kill_jobs_from_kctx(struct kbase_context *kctx); + +/** + * kbase_jm_wait_for_zero_jobs - Wait for context to have zero jobs running, and + * to be descheduled. + * @kctx: Context pointer + * + * This should be called following kbase_js_zap_context(), to ensure the context + * can be safely destroyed. + */ +void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx); + +/** + * kbase_backend_get_current_flush_id - Return the current flush ID + * + * @kbdev: Device pointer + * + * Return: the current flush ID to be recorded for each job chain + */ +u32 kbase_backend_get_current_flush_id(struct kbase_device *kbdev); + +#if KBASE_GPU_RESET_EN +/** + * kbase_prepare_to_reset_gpu - Prepare for resetting the GPU. + * @kbdev: Device pointer + * + * This function just soft-stops all the slots to ensure that as many jobs as + * possible are saved. + * + * Return: a boolean which should be interpreted as follows: + * - true - Prepared for reset, kbase_reset_gpu should be called. + * - false - Another thread is performing a reset, kbase_reset_gpu should + * not be called. + */ +bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev); + +/** + * kbase_reset_gpu - Reset the GPU + * @kbdev: Device pointer + * + * This function should be called after kbase_prepare_to_reset_gpu if it returns + * true. It should never be called without a corresponding call to + * kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu + * returned false), the caller should wait for kbdev->reset_waitq to be + * signalled to know when the reset has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev); + +/** + * kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU. + * @kbdev: Device pointer + * + * This function just soft-stops all the slots to ensure that as many jobs as + * possible are saved. + * + * Return: a boolean which should be interpreted as follows: + * - true - Prepared for reset, kbase_reset_gpu should be called. + * - false - Another thread is performing a reset, kbase_reset_gpu should + * not be called. + */ +bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev); + +/** + * kbase_reset_gpu_locked - Reset the GPU + * @kbdev: Device pointer + * + * This function should be called after kbase_prepare_to_reset_gpu if it + * returns true. It should never be called without a corresponding call to + * kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu + * returned false), the caller should wait for kbdev->reset_waitq to be + * signalled to know when the reset has completed. + */ +void kbase_reset_gpu_locked(struct kbase_device *kbdev); + +/** + * kbase_reset_gpu_silent - Reset the GPU silently + * @kbdev: Device pointer + * + * Reset the GPU without trying to cancel jobs and don't emit messages into + * the kernel log while doing the reset. + * + * This function should be used in cases where we are doing a controlled reset + * of the GPU as part of normal processing (e.g. exiting protected mode) where + * the driver will have ensured the scheduler has been idled and all other + * users of the GPU (e.g. instrumentation) have been suspended. + */ +void kbase_reset_gpu_silent(struct kbase_device *kbdev); + +/** + * kbase_reset_gpu_active - Reports if the GPU is being reset + * @kbdev: Device pointer + * + * Return: True if the GPU is in the process of being reset. + */ +bool kbase_reset_gpu_active(struct kbase_device *kbdev); +#endif + +/** + * kbase_job_slot_hardstop - Hard-stop the specified job slot + * @kctx: The kbase context that contains the job(s) that should + * be hard-stopped + * @js: The job slot to hard-stop + * @target_katom: The job that should be hard-stopped (or NULL for all + * jobs from the context) + * Context: + * The job slot lock must be held when calling this function. + */ +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom); + +extern struct protected_mode_ops kbase_native_protected_ops; + +#endif /* _KBASE_HWACCESS_JM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_pm.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_pm.h new file mode 100644 index 000000000000..71c7d495c40a --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_pm.h @@ -0,0 +1,209 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * @file mali_kbase_hwaccess_pm.h + * HW access power manager common APIs + */ + +#ifndef _KBASE_HWACCESS_PM_H_ +#define _KBASE_HWACCESS_PM_H_ + +#include +#include + +#include + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +/* Functions common to all HW access backends */ + +/** + * Initialize the power management framework. + * + * Must be called before any other power management function + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + * + * @return 0 if the power management framework was successfully + * initialized. + */ +int kbase_hwaccess_pm_init(struct kbase_device *kbdev); + +/** + * Terminate the power management framework. + * + * No power management functions may be called after this (except + * @ref kbase_pm_init) + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_term(struct kbase_device *kbdev); + +/** + * kbase_hwaccess_pm_powerup - Power up the GPU. + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * @flags: Flags to pass on to kbase_pm_init_hw + * + * Power up GPU after all modules have been initialized and interrupt handlers + * installed. + * + * Return: 0 if powerup was successful. + */ +int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, + unsigned int flags); + +/** + * Halt the power management framework. + * + * Should ensure that no new interrupts are generated, but allow any currently + * running interrupt handlers to complete successfully. The GPU is forced off by + * the time this function returns, regardless of whether or not the active power + * policy asks for the GPU to be powered off. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_halt(struct kbase_device *kbdev); + +/** + * Perform any backend-specific actions to suspend the GPU + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_suspend(struct kbase_device *kbdev); + +/** + * Perform any backend-specific actions to resume the GPU from a suspend + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_resume(struct kbase_device *kbdev); + +/** + * Perform any required actions for activating the GPU. Called when the first + * context goes active. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev); + +/** + * Perform any required actions for idling the GPU. Called when the last + * context goes idle. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_hwaccess_pm_gpu_idle(struct kbase_device *kbdev); + + +/** + * Set the debug core mask. + * + * This determines which cores the power manager is allowed to use. + * + * @param kbdev The kbase device structure for the device (must be a + * valid pointer) + * @param new_core_mask_js0 The core mask to use for job slot 0 + * @param new_core_mask_js0 The core mask to use for job slot 1 + * @param new_core_mask_js0 The core mask to use for job slot 2 + */ +void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, + u64 new_core_mask_js0, u64 new_core_mask_js1, + u64 new_core_mask_js2); + + +/** + * Get the current policy. + * + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + * + * @return The current policy + */ +const struct kbase_pm_ca_policy +*kbase_pm_ca_get_policy(struct kbase_device *kbdev); + +/** + * Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + * @param policy The policy to change to (valid pointer returned from + * @ref kbase_pm_ca_list_policies) + */ +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, + const struct kbase_pm_ca_policy *policy); + +/** + * Retrieve a static list of the available policies. + * + * @param[out] policies An array pointer to take the list of policies. This may + * be NULL. The contents of this array must not be + * modified. + * + * @return The number of policies + */ +int +kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **policies); + + +/** + * Get the current policy. + * + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + * + * @return The current policy + */ +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev); + +/** + * Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + * @param policy The policy to change to (valid pointer returned from + * @ref kbase_pm_list_policies) + */ +void kbase_pm_set_policy(struct kbase_device *kbdev, + const struct kbase_pm_policy *policy); + +/** + * Retrieve a static list of the available policies. + * + * @param[out] policies An array pointer to take the list of policies. This may + * be NULL. The contents of this array must not be + * modified. + * + * @return The number of policies + */ +int kbase_pm_list_policies(const struct kbase_pm_policy * const **policies); + +#endif /* _KBASE_HWACCESS_PM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h new file mode 100644 index 000000000000..89d26eaf09a4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h @@ -0,0 +1,53 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * + */ + +#ifndef _KBASE_BACKEND_TIME_H_ +#define _KBASE_BACKEND_TIME_H_ + +/** + * kbase_backend_get_gpu_time() - Get current GPU time + * @kbdev: Device pointer + * @cycle_counter: Pointer to u64 to store cycle counter in + * @system_time: Pointer to u64 to store system time in + * @ts: Pointer to struct timespec to store current monotonic + * time in + */ +void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, + u64 *system_time, struct timespec *ts); + +/** + * kbase_wait_write_flush() - Wait for GPU write flush + * @kctx: Context pointer + * + * Wait 1000 GPU clock cycles. This delay is known to give the GPU time to flush + * its write buffer. + * + * If GPU resets occur then the counters are reset to zero, the delay may not be + * as expected. + * + * This function is only in use for BASE_HW_ISSUE_6367 + */ +#ifndef CONFIG_MALI_NO_MALI +void kbase_wait_write_flush(struct kbase_context *kctx); +#endif + +#endif /* _KBASE_BACKEND_TIME_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h new file mode 100644 index 000000000000..cf7bf1b35dc5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h @@ -0,0 +1,66 @@ +/* + * + * (C) COPYRIGHT 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_HWCNT_READER_H_ +#define _KBASE_HWCNT_READER_H_ + +/* The ids of ioctl commands. */ +#define KBASE_HWCNT_READER 0xBE +#define KBASE_HWCNT_READER_GET_HWVER _IOR(KBASE_HWCNT_READER, 0x00, u32) +#define KBASE_HWCNT_READER_GET_BUFFER_SIZE _IOR(KBASE_HWCNT_READER, 0x01, u32) +#define KBASE_HWCNT_READER_DUMP _IOW(KBASE_HWCNT_READER, 0x10, u32) +#define KBASE_HWCNT_READER_CLEAR _IOW(KBASE_HWCNT_READER, 0x11, u32) +#define KBASE_HWCNT_READER_GET_BUFFER _IOR(KBASE_HWCNT_READER, 0x20,\ + struct kbase_hwcnt_reader_metadata) +#define KBASE_HWCNT_READER_PUT_BUFFER _IOW(KBASE_HWCNT_READER, 0x21,\ + struct kbase_hwcnt_reader_metadata) +#define KBASE_HWCNT_READER_SET_INTERVAL _IOW(KBASE_HWCNT_READER, 0x30, u32) +#define KBASE_HWCNT_READER_ENABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x40, u32) +#define KBASE_HWCNT_READER_DISABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x41, u32) +#define KBASE_HWCNT_READER_GET_API_VERSION _IOW(KBASE_HWCNT_READER, 0xFF, u32) + +/** + * struct kbase_hwcnt_reader_metadata - hwcnt reader sample buffer metadata + * @timestamp: time when sample was collected + * @event_id: id of an event that triggered sample collection + * @buffer_idx: position in sampling area where sample buffer was stored + */ +struct kbase_hwcnt_reader_metadata { + u64 timestamp; + u32 event_id; + u32 buffer_idx; +}; + +/** + * enum base_hwcnt_reader_event - hwcnt dumping events + * @BASE_HWCNT_READER_EVENT_MANUAL: manual request for dump + * @BASE_HWCNT_READER_EVENT_PERIODIC: periodic dump + * @BASE_HWCNT_READER_EVENT_PREJOB: prejob dump request + * @BASE_HWCNT_READER_EVENT_POSTJOB: postjob dump request + * @BASE_HWCNT_READER_EVENT_COUNT: number of supported events + */ +enum base_hwcnt_reader_event { + BASE_HWCNT_READER_EVENT_MANUAL, + BASE_HWCNT_READER_EVENT_PERIODIC, + BASE_HWCNT_READER_EVENT_PREJOB, + BASE_HWCNT_READER_EVENT_POSTJOB, + + BASE_HWCNT_READER_EVENT_COUNT +}; + +#endif /* _KBASE_HWCNT_READER_H_ */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_ioctl.h b/drivers/gpu/arm/bifrost/mali_kbase_ioctl.h new file mode 100644 index 000000000000..e7c1daee470b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_ioctl.h @@ -0,0 +1,658 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_IOCTL_H_ +#define _KBASE_IOCTL_H_ + +#ifdef __cpluscplus +extern "C" { +#endif + +#include + +#define KBASE_IOCTL_TYPE 0x80 + +#ifdef ANDROID +/* Android's definition of ioctl is incorrect, specifying the type argument as + * 'int'. This creates a warning when using _IOWR (as the top bit is set). Work + * round this by redefining _IOC to include a case to 'int'. + */ +#undef _IOC +#define _IOC(dir, type, nr, size) \ + ((int)(((dir) << _IOC_DIRSHIFT) | ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT))) +#endif + +/** + * struct kbase_ioctl_version_check - Check version compatibility with kernel + * + * @major: Major version number + * @minor: Minor version number + */ +struct kbase_ioctl_version_check { + __u16 major; + __u16 minor; +}; + +#define KBASE_IOCTL_VERSION_CHECK \ + _IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check) + +/** + * struct kbase_ioctl_set_flags - Set kernel context creation flags + * + * @create_flags: Flags - see base_context_create_flags + */ +struct kbase_ioctl_set_flags { + __u32 create_flags; +}; + +#define KBASE_IOCTL_SET_FLAGS \ + _IOW(KBASE_IOCTL_TYPE, 1, struct kbase_ioctl_set_flags) + +/** + * struct kbase_ioctl_job_submit - Submit jobs/atoms to the kernel + * + * @addr: Memory address of an array of struct base_jd_atom_v2 + * @nr_atoms: Number of entries in the array + * @stride: sizeof(struct base_jd_atom_v2) + */ +struct kbase_ioctl_job_submit { + __u64 addr; + __u32 nr_atoms; + __u32 stride; +}; + +#define KBASE_IOCTL_JOB_SUBMIT \ + _IOW(KBASE_IOCTL_TYPE, 2, struct kbase_ioctl_job_submit) + +/** + * struct kbase_ioctl_get_gpuprops - Read GPU properties from the kernel + * + * @buffer: Pointer to the buffer to store properties into + * @size: Size of the buffer + * @flags: Flags - must be zero for now + * + * The ioctl will return the number of bytes stored into @buffer or an error + * on failure (e.g. @size is too small). If @size is specified as 0 then no + * data will be written but the return value will be the number of bytes needed + * for all the properties. + * + * @flags may be used in the future to request a different format for the + * buffer. With @flags == 0 the following format is used. + * + * The buffer will be filled with pairs of values, a u32 key identifying the + * property followed by the value. The size of the value is identified using + * the bottom bits of the key. The value then immediately followed the key and + * is tightly packed (there is no padding). All keys and values are + * little-endian. + * + * 00 = u8 + * 01 = u16 + * 10 = u32 + * 11 = u64 + */ +struct kbase_ioctl_get_gpuprops { + __u64 buffer; + __u32 size; + __u32 flags; +}; + +#define KBASE_IOCTL_GET_GPUPROPS \ + _IOW(KBASE_IOCTL_TYPE, 3, struct kbase_ioctl_get_gpuprops) + +#define KBASE_IOCTL_POST_TERM \ + _IO(KBASE_IOCTL_TYPE, 4) + +/** + * union kbase_ioctl_mem_alloc - Allocate memory on the GPU + * + * @va_pages: The number of pages of virtual address space to reserve + * @commit_pages: The number of physical pages to allocate + * @extent: The number of extra pages to allocate on each GPU fault which grows + * the region + * @flags: Flags + * @gpu_va: The GPU virtual address which is allocated + * + * @in: Input parameters + * @out: Output parameters + */ +union kbase_ioctl_mem_alloc { + struct { + __u64 va_pages; + __u64 commit_pages; + __u64 extent; + __u64 flags; + } in; + struct { + __u64 flags; + __u64 gpu_va; + } out; +}; + +#define KBASE_IOCTL_MEM_ALLOC \ + _IOWR(KBASE_IOCTL_TYPE, 5, union kbase_ioctl_mem_alloc) + +/** + * struct kbase_ioctl_mem_query - Query properties of a GPU memory region + * @gpu_addr: A GPU address contained within the region + * @query: The type of query + * @value: The result of the query + * + * Use a %KBASE_MEM_QUERY_xxx flag as input for @query. + * + * @in: Input parameters + * @out: Output parameters + */ +union kbase_ioctl_mem_query { + struct { + __u64 gpu_addr; + __u64 query; + } in; + struct { + __u64 value; + } out; +}; + +#define KBASE_IOCTL_MEM_QUERY \ + _IOWR(KBASE_IOCTL_TYPE, 6, union kbase_ioctl_mem_query) + +#define KBASE_MEM_QUERY_COMMIT_SIZE 1 +#define KBASE_MEM_QUERY_VA_SIZE 2 +#define KBASE_MEM_QUERY_FLAGS 3 + +/** + * struct kbase_ioctl_mem_free - Free a memory region + * @gpu_addr: Handle to the region to free + */ +struct kbase_ioctl_mem_free { + __u64 gpu_addr; +}; + +#define KBASE_IOCTL_MEM_FREE \ + _IOW(KBASE_IOCTL_TYPE, 7, struct kbase_ioctl_mem_free) + +/** + * struct kbase_ioctl_hwcnt_reader_setup - Setup HWC dumper/reader + * @buffer_count: requested number of dumping buffers + * @jm_bm: counters selection bitmask (JM) + * @shader_bm: counters selection bitmask (Shader) + * @tiler_bm: counters selection bitmask (Tiler) + * @mmu_l2_bm: counters selection bitmask (MMU_L2) + * + * A fd is returned from the ioctl if successful, or a negative value on error + */ +struct kbase_ioctl_hwcnt_reader_setup { + __u32 buffer_count; + __u32 jm_bm; + __u32 shader_bm; + __u32 tiler_bm; + __u32 mmu_l2_bm; +}; + +#define KBASE_IOCTL_HWCNT_READER_SETUP \ + _IOW(KBASE_IOCTL_TYPE, 8, struct kbase_ioctl_hwcnt_reader_setup) + +/** + * struct kbase_ioctl_hwcnt_enable - Enable hardware counter collection + * @dump_buffer: GPU address to write counters to + * @jm_bm: counters selection bitmask (JM) + * @shader_bm: counters selection bitmask (Shader) + * @tiler_bm: counters selection bitmask (Tiler) + * @mmu_l2_bm: counters selection bitmask (MMU_L2) + */ +struct kbase_ioctl_hwcnt_enable { + __u64 dump_buffer; + __u32 jm_bm; + __u32 shader_bm; + __u32 tiler_bm; + __u32 mmu_l2_bm; +}; + +#define KBASE_IOCTL_HWCNT_ENABLE \ + _IOW(KBASE_IOCTL_TYPE, 9, struct kbase_ioctl_hwcnt_enable) + +#define KBASE_IOCTL_HWCNT_DUMP \ + _IO(KBASE_IOCTL_TYPE, 10) + +#define KBASE_IOCTL_HWCNT_CLEAR \ + _IO(KBASE_IOCTL_TYPE, 11) + +/** + * struct kbase_ioctl_disjoint_query - Query the disjoint counter + * @counter: A counter of disjoint events in the kernel + */ +struct kbase_ioctl_disjoint_query { + __u32 counter; +}; + +#define KBASE_IOCTL_DISJOINT_QUERY \ + _IOR(KBASE_IOCTL_TYPE, 12, struct kbase_ioctl_disjoint_query) + +/** + * struct kbase_ioctl_get_ddk_version - Query the kernel version + * @version_buffer: Buffer to receive the kernel version string + * @size: Size of the buffer + * + * The ioctl will return the number of bytes written into version_buffer + * (which includes a NULL byte) or a negative error code + */ +struct kbase_ioctl_get_ddk_version { + __u64 version_buffer; + __u32 size; +}; + +#define KBASE_IOCTL_GET_DDK_VERSION \ + _IOW(KBASE_IOCTL_TYPE, 13, struct kbase_ioctl_get_ddk_version) + +/** + * struct kbase_ioctl_mem_jit_init - Initialise the JIT memory allocator + * + * @va_pages: Number of VA pages to reserve for JIT + * + * Note that depending on the VA size of the application and GPU, the value + * specified in @va_pages may be ignored. + */ +struct kbase_ioctl_mem_jit_init { + __u64 va_pages; +}; + +#define KBASE_IOCTL_MEM_JIT_INIT \ + _IOW(KBASE_IOCTL_TYPE, 14, struct kbase_ioctl_mem_jit_init) + +/** + * struct kbase_ioctl_mem_sync - Perform cache maintenance on memory + * + * @handle: GPU memory handle (GPU VA) + * @user_addr: The address where it is mapped in user space + * @size: The number of bytes to synchronise + * @type: The direction to synchronise: 0 is sync to memory (clean), + * 1 is sync from memory (invalidate). Use the BASE_SYNCSET_OP_xxx constants. + * @padding: Padding to round up to a multiple of 8 bytes, must be zero + */ +struct kbase_ioctl_mem_sync { + __u64 handle; + __u64 user_addr; + __u64 size; + __u8 type; + __u8 padding[7]; +}; + +#define KBASE_IOCTL_MEM_SYNC \ + _IOW(KBASE_IOCTL_TYPE, 15, struct kbase_ioctl_mem_sync) + +/** + * union kbase_ioctl_mem_find_cpu_offset - Find the offset of a CPU pointer + * + * @gpu_addr: The GPU address of the memory region + * @cpu_addr: The CPU address to locate + * @size: A size in bytes to validate is contained within the region + * @offset: The offset from the start of the memory region to @cpu_addr + * + * @in: Input parameters + * @out: Output parameters + */ +union kbase_ioctl_mem_find_cpu_offset { + struct { + __u64 gpu_addr; + __u64 cpu_addr; + __u64 size; + } in; + struct { + __u64 offset; + } out; +}; + +#define KBASE_IOCTL_MEM_FIND_CPU_OFFSET \ + _IOWR(KBASE_IOCTL_TYPE, 16, union kbase_ioctl_mem_find_cpu_offset) + +/** + * struct kbase_ioctl_get_context_id - Get the kernel context ID + * + * @id: The kernel context ID + */ +struct kbase_ioctl_get_context_id { + __u32 id; +}; + +#define KBASE_IOCTL_GET_CONTEXT_ID \ + _IOR(KBASE_IOCTL_TYPE, 17, struct kbase_ioctl_get_context_id) + +/** + * struct kbase_ioctl_tlstream_acquire - Acquire a tlstream fd + * + * @flags: Flags + * + * The ioctl returns a file descriptor when successful + */ +struct kbase_ioctl_tlstream_acquire { + __u32 flags; +}; + +#define KBASE_IOCTL_TLSTREAM_ACQUIRE \ + _IOW(KBASE_IOCTL_TYPE, 18, struct kbase_ioctl_tlstream_acquire) + +#define KBASE_IOCTL_TLSTREAM_FLUSH \ + _IO(KBASE_IOCTL_TYPE, 19) + +/** + * struct kbase_ioctl_mem_commit - Change the amount of memory backing a region + * + * @gpu_addr: The memory region to modify + * @pages: The number of physical pages that should be present + * + * The ioctl may return on the following error codes or 0 for success: + * -ENOMEM: Out of memory + * -EINVAL: Invalid arguments + */ +struct kbase_ioctl_mem_commit { + __u64 gpu_addr; + __u64 pages; +}; + +#define KBASE_IOCTL_MEM_COMMIT \ + _IOW(KBASE_IOCTL_TYPE, 20, struct kbase_ioctl_mem_commit) + +/** + * union kbase_ioctl_mem_alias - Create an alias of memory regions + * @flags: Flags, see BASE_MEM_xxx + * @stride: Bytes between start of each memory region + * @nents: The number of regions to pack together into the alias + * @aliasing_info: Pointer to an array of struct base_mem_aliasing_info + * @gpu_va: Address of the new alias + * @va_pages: Size of the new alias + * + * @in: Input parameters + * @out: Output parameters + */ +union kbase_ioctl_mem_alias { + struct { + __u64 flags; + __u64 stride; + __u64 nents; + __u64 aliasing_info; + } in; + struct { + __u64 flags; + __u64 gpu_va; + __u64 va_pages; + } out; +}; + +#define KBASE_IOCTL_MEM_ALIAS \ + _IOWR(KBASE_IOCTL_TYPE, 21, union kbase_ioctl_mem_alias) + +/** + * union kbase_ioctl_mem_import - Import memory for use by the GPU + * @flags: Flags, see BASE_MEM_xxx + * @phandle: Handle to the external memory + * @type: Type of external memory, see base_mem_import_type + * @padding: Amount of extra VA pages to append to the imported buffer + * @gpu_va: Address of the new alias + * @va_pages: Size of the new alias + * + * @in: Input parameters + * @out: Output parameters + */ +union kbase_ioctl_mem_import { + struct { + __u64 flags; + __u64 phandle; + __u32 type; + __u32 padding; + } in; + struct { + __u64 flags; + __u64 gpu_va; + __u64 va_pages; + } out; +}; + +#define KBASE_IOCTL_MEM_IMPORT \ + _IOWR(KBASE_IOCTL_TYPE, 22, union kbase_ioctl_mem_import) + +/** + * struct kbase_ioctl_mem_flags_change - Change the flags for a memory region + * @gpu_va: The GPU region to modify + * @flags: The new flags to set + * @mask: Mask of the flags to modify + */ +struct kbase_ioctl_mem_flags_change { + __u64 gpu_va; + __u64 flags; + __u64 mask; +}; + +#define KBASE_IOCTL_MEM_FLAGS_CHANGE \ + _IOW(KBASE_IOCTL_TYPE, 23, struct kbase_ioctl_mem_flags_change) + +/** + * struct kbase_ioctl_stream_create - Create a synchronisation stream + * @name: A name to identify this stream. Must be NULL-terminated. + * + * Note that this is also called a "timeline", but is named stream to avoid + * confusion with other uses of the word. + * + * Unused bytes in @name (after the first NULL byte) must be also be NULL bytes. + * + * The ioctl returns a file descriptor. + */ +struct kbase_ioctl_stream_create { + char name[32]; +}; + +#define KBASE_IOCTL_STREAM_CREATE \ + _IOW(KBASE_IOCTL_TYPE, 24, struct kbase_ioctl_stream_create) + +/** + * struct kbase_ioctl_fence_validate - Validate a fd refers to a fence + * @fd: The file descriptor to validate + */ +struct kbase_ioctl_fence_validate { + int fd; +}; + +#define KBASE_IOCTL_FENCE_VALIDATE \ + _IOW(KBASE_IOCTL_TYPE, 25, struct kbase_ioctl_fence_validate) + +/** + * struct kbase_ioctl_get_profiling_controls - Get the profiling controls + * @count: The size of @buffer in u32 words + * @buffer: The buffer to receive the profiling controls + */ +struct kbase_ioctl_get_profiling_controls { + __u64 buffer; + __u32 count; +}; + +#define KBASE_IOCTL_GET_PROFILING_CONTROLS \ + _IOW(KBASE_IOCTL_TYPE, 26, struct kbase_ioctl_get_profiling_controls) + +/** + * struct kbase_ioctl_mem_profile_add - Provide profiling information to kernel + * @buffer: Pointer to the information + * @len: Length + * @padding: Padding + * + * The data provided is accessible through a debugfs file + */ +struct kbase_ioctl_mem_profile_add { + __u64 buffer; + __u32 len; + __u32 padding; +}; + +#define KBASE_IOCTL_MEM_PROFILE_ADD \ + _IOW(KBASE_IOCTL_TYPE, 27, struct kbase_ioctl_mem_profile_add) + +/** + * struct kbase_ioctl_soft_event_update - Update the status of a soft-event + * @event: GPU address of the event which has been updated + * @new_status: The new status to set + * @flags: Flags for future expansion + */ +struct kbase_ioctl_soft_event_update { + __u64 event; + __u32 new_status; + __u32 flags; +}; + +#define KBASE_IOCTL_SOFT_EVENT_UPDATE \ + _IOW(KBASE_IOCTL_TYPE, 28, struct kbase_ioctl_soft_event_update) + +/* IOCTLs 29-32 are reserved */ + +/*************** + * test ioctls * + ***************/ +#if MALI_UNIT_TEST +/* These ioctls are purely for test purposes and are not used in the production + * driver, they therefore may change without notice + */ + +#define KBASE_IOCTL_TEST_TYPE (KBASE_IOCTL_TYPE + 1) + +/** + * struct kbase_ioctl_tlstream_test - Start a timeline stream test + * + * @tpw_count: number of trace point writers in each context + * @msg_delay: time delay between tracepoints from one writer in milliseconds + * @msg_count: number of trace points written by one writer + * @aux_msg: if non-zero aux messages will be included + */ +struct kbase_ioctl_tlstream_test { + __u32 tpw_count; + __u32 msg_delay; + __u32 msg_count; + __u32 aux_msg; +}; + +#define KBASE_IOCTL_TLSTREAM_TEST \ + _IOW(KBASE_IOCTL_TEST_TYPE, 1, struct kbase_ioctl_tlstream_test) + +/** + * struct kbase_ioctl_tlstream_stats - Read tlstream stats for test purposes + * @bytes_collected: number of bytes read by user + * @bytes_generated: number of bytes generated by tracepoints + */ +struct kbase_ioctl_tlstream_stats { + __u32 bytes_collected; + __u32 bytes_generated; +}; + +#define KBASE_IOCTL_TLSTREAM_STATS \ + _IOR(KBASE_IOCTL_TEST_TYPE, 2, struct kbase_ioctl_tlstream_stats) + +#endif + +/********************************** + * Definitions for GPU properties * + **********************************/ +#define KBASE_GPUPROP_VALUE_SIZE_U8 (0x0) +#define KBASE_GPUPROP_VALUE_SIZE_U16 (0x1) +#define KBASE_GPUPROP_VALUE_SIZE_U32 (0x2) +#define KBASE_GPUPROP_VALUE_SIZE_U64 (0x3) + +#define KBASE_GPUPROP_PRODUCT_ID 1 +#define KBASE_GPUPROP_VERSION_STATUS 2 +#define KBASE_GPUPROP_MINOR_REVISION 3 +#define KBASE_GPUPROP_MAJOR_REVISION 4 +#define KBASE_GPUPROP_GPU_SPEED_MHZ 5 +#define KBASE_GPUPROP_GPU_FREQ_KHZ_MAX 6 +#define KBASE_GPUPROP_GPU_FREQ_KHZ_MIN 7 +#define KBASE_GPUPROP_LOG2_PROGRAM_COUNTER_SIZE 8 +#define KBASE_GPUPROP_TEXTURE_FEATURES_0 9 +#define KBASE_GPUPROP_TEXTURE_FEATURES_1 10 +#define KBASE_GPUPROP_TEXTURE_FEATURES_2 11 +#define KBASE_GPUPROP_GPU_AVAILABLE_MEMORY_SIZE 12 + +#define KBASE_GPUPROP_L2_LOG2_LINE_SIZE 13 +#define KBASE_GPUPROP_L2_LOG2_CACHE_SIZE 14 +#define KBASE_GPUPROP_L2_NUM_L2_SLICES 15 + +#define KBASE_GPUPROP_TILER_BIN_SIZE_BYTES 16 +#define KBASE_GPUPROP_TILER_MAX_ACTIVE_LEVELS 17 + +#define KBASE_GPUPROP_MAX_THREADS 18 +#define KBASE_GPUPROP_MAX_WORKGROUP_SIZE 19 +#define KBASE_GPUPROP_MAX_BARRIER_SIZE 20 +#define KBASE_GPUPROP_MAX_REGISTERS 21 +#define KBASE_GPUPROP_MAX_TASK_QUEUE 22 +#define KBASE_GPUPROP_MAX_THREAD_GROUP_SPLIT 23 +#define KBASE_GPUPROP_IMPL_TECH 24 + +#define KBASE_GPUPROP_RAW_SHADER_PRESENT 25 +#define KBASE_GPUPROP_RAW_TILER_PRESENT 26 +#define KBASE_GPUPROP_RAW_L2_PRESENT 27 +#define KBASE_GPUPROP_RAW_STACK_PRESENT 28 +#define KBASE_GPUPROP_RAW_L2_FEATURES 29 +#define KBASE_GPUPROP_RAW_SUSPEND_SIZE 30 +#define KBASE_GPUPROP_RAW_MEM_FEATURES 31 +#define KBASE_GPUPROP_RAW_MMU_FEATURES 32 +#define KBASE_GPUPROP_RAW_AS_PRESENT 33 +#define KBASE_GPUPROP_RAW_JS_PRESENT 34 +#define KBASE_GPUPROP_RAW_JS_FEATURES_0 35 +#define KBASE_GPUPROP_RAW_JS_FEATURES_1 36 +#define KBASE_GPUPROP_RAW_JS_FEATURES_2 37 +#define KBASE_GPUPROP_RAW_JS_FEATURES_3 38 +#define KBASE_GPUPROP_RAW_JS_FEATURES_4 39 +#define KBASE_GPUPROP_RAW_JS_FEATURES_5 40 +#define KBASE_GPUPROP_RAW_JS_FEATURES_6 41 +#define KBASE_GPUPROP_RAW_JS_FEATURES_7 42 +#define KBASE_GPUPROP_RAW_JS_FEATURES_8 43 +#define KBASE_GPUPROP_RAW_JS_FEATURES_9 44 +#define KBASE_GPUPROP_RAW_JS_FEATURES_10 45 +#define KBASE_GPUPROP_RAW_JS_FEATURES_11 46 +#define KBASE_GPUPROP_RAW_JS_FEATURES_12 47 +#define KBASE_GPUPROP_RAW_JS_FEATURES_13 48 +#define KBASE_GPUPROP_RAW_JS_FEATURES_14 49 +#define KBASE_GPUPROP_RAW_JS_FEATURES_15 50 +#define KBASE_GPUPROP_RAW_TILER_FEATURES 51 +#define KBASE_GPUPROP_RAW_TEXTURE_FEATURES_0 52 +#define KBASE_GPUPROP_RAW_TEXTURE_FEATURES_1 53 +#define KBASE_GPUPROP_RAW_TEXTURE_FEATURES_2 54 +#define KBASE_GPUPROP_RAW_GPU_ID 55 +#define KBASE_GPUPROP_RAW_THREAD_MAX_THREADS 56 +#define KBASE_GPUPROP_RAW_THREAD_MAX_WORKGROUP_SIZE 57 +#define KBASE_GPUPROP_RAW_THREAD_MAX_BARRIER_SIZE 58 +#define KBASE_GPUPROP_RAW_THREAD_FEATURES 59 +#define KBASE_GPUPROP_RAW_COHERENCY_MODE 60 + +#define KBASE_GPUPROP_COHERENCY_NUM_GROUPS 61 +#define KBASE_GPUPROP_COHERENCY_NUM_CORE_GROUPS 62 +#define KBASE_GPUPROP_COHERENCY_COHERENCY 63 +#define KBASE_GPUPROP_COHERENCY_GROUP_0 64 +#define KBASE_GPUPROP_COHERENCY_GROUP_1 65 +#define KBASE_GPUPROP_COHERENCY_GROUP_2 66 +#define KBASE_GPUPROP_COHERENCY_GROUP_3 67 +#define KBASE_GPUPROP_COHERENCY_GROUP_4 68 +#define KBASE_GPUPROP_COHERENCY_GROUP_5 69 +#define KBASE_GPUPROP_COHERENCY_GROUP_6 70 +#define KBASE_GPUPROP_COHERENCY_GROUP_7 71 +#define KBASE_GPUPROP_COHERENCY_GROUP_8 72 +#define KBASE_GPUPROP_COHERENCY_GROUP_9 73 +#define KBASE_GPUPROP_COHERENCY_GROUP_10 74 +#define KBASE_GPUPROP_COHERENCY_GROUP_11 75 +#define KBASE_GPUPROP_COHERENCY_GROUP_12 76 +#define KBASE_GPUPROP_COHERENCY_GROUP_13 77 +#define KBASE_GPUPROP_COHERENCY_GROUP_14 78 +#define KBASE_GPUPROP_COHERENCY_GROUP_15 79 + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd.c b/drivers/gpu/arm/bifrost/mali_kbase_jd.c new file mode 100644 index 000000000000..9f9e0c44bcb0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd.c @@ -0,0 +1,1847 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ +#ifdef CONFIG_COMPAT +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mali_kbase_dma_fence.h" + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +/* random32 was renamed to prandom_u32 in 3.8 */ +#define prandom_u32 random32 +#endif + +/* Return whether katom will run on the GPU or not. Currently only soft jobs and + * dependency-only atoms do not run on the GPU */ +#define IS_GPU_ATOM(katom) (!((katom->core_req & BASE_JD_REQ_SOFT_JOB) || \ + ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) == \ + BASE_JD_REQ_DEP))) +/* + * This is the kernel side of the API. Only entry points are: + * - kbase_jd_submit(): Called from userspace to submit a single bag + * - kbase_jd_done(): Called from interrupt context to track the + * completion of a job. + * Callouts: + * - to the job manager (enqueue a job) + * - to the event subsystem (signals the completion/failure of bag/job-chains). + */ + +static void __user * +get_compat_pointer(struct kbase_context *kctx, const u64 p) +{ +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + return compat_ptr(p); +#endif + return u64_to_user_ptr(p); +} + +/* Runs an atom, either by handing to the JS or by immediately running it in the case of soft-jobs + * + * Returns whether the JS needs a reschedule. + * + * Note that the caller must also check the atom status and + * if it is KBASE_JD_ATOM_STATE_COMPLETED must call jd_done_nolock + */ +static int jd_run_atom(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + + if ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) { + /* Dependency only atom */ + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + return 0; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + /* Soft-job */ + if (katom->will_fail_event_code) { + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + return 0; + } + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (!kbase_replay_process(katom)) + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } else if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } + return 0; + } + + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + /* Queue an action about whether we should try scheduling a context */ + return kbasep_js_add_job(kctx, katom); +} + +#if defined(CONFIG_KDS) || defined(CONFIG_MALI_DMA_FENCE) +void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom) +{ + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(katom); + kbdev = katom->kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + /* Check whether the atom's other dependencies were already met. If + * katom is a GPU atom then the job scheduler may be able to represent + * the dependencies, hence we may attempt to submit it before they are + * met. Other atoms must have had both dependencies resolved. + */ + if (IS_GPU_ATOM(katom) || + (!kbase_jd_katom_dep_atom(&katom->dep[0]) && + !kbase_jd_katom_dep_atom(&katom->dep[1]))) { + /* katom dep complete, attempt to run it */ + bool resched = false; + + resched = jd_run_atom(katom); + + if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + /* The atom has already finished */ + resched |= jd_done_nolock(katom, NULL); + } + + if (resched) + kbase_js_sched_all(kbdev); + } +} +#endif + +#ifdef CONFIG_KDS + +/* Add the katom to the kds waiting list. + * Atoms must be added to the waiting list after a successful call to kds_async_waitall. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_add(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + list_add_tail(&katom->node, &kctx->waiting_kds_resource); +} + +/* Remove the katom from the kds waiting list. + * Atoms must be removed from the waiting list before a call to kds_resource_set_release_sync. + * The supplied katom must first have been added to the list with a call to kbase_jd_kds_waiters_add. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_remove(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + list_del(&katom->node); +} + +static void kds_dep_clear(void *callback_parameter, void *callback_extra_parameter) +{ + struct kbase_jd_atom *katom; + struct kbase_jd_context *ctx; + + katom = (struct kbase_jd_atom *)callback_parameter; + KBASE_DEBUG_ASSERT(katom); + + ctx = &katom->kctx->jctx; + + /* If KDS resource has already been satisfied (e.g. due to zapping) + * do nothing. + */ + mutex_lock(&ctx->lock); + if (!katom->kds_dep_satisfied) { + katom->kds_dep_satisfied = true; + kbase_jd_dep_clear_locked(katom); + } + mutex_unlock(&ctx->lock); +} + +static void kbase_cancel_kds_wait_job(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + + /* Prevent job_done_nolock from being called twice on an atom when + * there is a race between job completion and cancellation */ + + if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { + /* Wait was cancelled - zap the atom */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(katom->kctx->kbdev); + } +} +#endif /* CONFIG_KDS */ + +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) +{ +#ifdef CONFIG_KDS + if (katom->kds_rset) { + struct kbase_jd_context *jctx = &katom->kctx->jctx; + + /* + * As the atom is no longer waiting, remove it from + * the waiting list. + */ + + mutex_lock(&jctx->lock); + kbase_jd_kds_waiters_remove(katom); + mutex_unlock(&jctx->lock); + + /* Release the kds resource or cancel if zapping */ + kds_resource_set_release_sync(&katom->kds_rset); + } +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_MALI_DMA_FENCE + /* Flush dma-fence workqueue to ensure that any callbacks that may have + * been queued are done before continuing. + * Any successfully completed atom would have had all it's callbacks + * completed before the atom was run, so only flush for failed atoms. + */ + if (katom->event_code != BASE_JD_EVENT_DONE) + flush_workqueue(katom->kctx->dma_fence.wq); +#endif /* CONFIG_MALI_DMA_FENCE */ +} + +static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + +#ifdef CONFIG_KDS + /* Prevent the KDS resource from triggering the atom in case of zapping */ + if (katom->kds_rset) + katom->kds_dep_satisfied = true; +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_MALI_DMA_FENCE + kbase_dma_fence_signal(katom); +#endif /* CONFIG_MALI_DMA_FENCE */ + + kbase_gpu_vm_lock(katom->kctx); + /* only roll back if extres is non-NULL */ + if (katom->extres) { + u32 res_no; + + res_no = katom->nr_extres; + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; + struct kbase_va_region *reg; + + reg = kbase_region_tracker_find_region_base_address( + katom->kctx, + katom->extres[res_no].gpu_address); + kbase_unmap_external_resource(katom->kctx, reg, alloc); + } + kfree(katom->extres); + katom->extres = NULL; + } + kbase_gpu_vm_unlock(katom->kctx); +} + +/* + * Set up external resources needed by this job. + * + * jctx.lock must be held when this is called. + */ + +static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom_v2 *user_atom) +{ + int err_ret_val = -EINVAL; + u32 res_no; +#ifdef CONFIG_KDS + u32 kds_res_count = 0; + struct kds_resource **kds_resources = NULL; + unsigned long *kds_access_bitmap = NULL; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_MALI_DMA_FENCE + struct kbase_dma_fence_resv_info info = { + .dma_fence_resv_count = 0, + }; +#ifdef CONFIG_SYNC + /* + * When both dma-buf fence and Android native sync is enabled, we + * disable dma-buf fence for contexts that are using Android native + * fences. + */ + const bool implicit_sync = !kbase_ctx_flag(katom->kctx, + KCTX_NO_IMPLICIT_SYNC); +#else /* CONFIG_SYNC */ + const bool implicit_sync = true; +#endif /* CONFIG_SYNC */ +#endif /* CONFIG_MALI_DMA_FENCE */ + struct base_external_resource *input_extres; + + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + + /* no resources encoded, early out */ + if (!katom->nr_extres) + return -EINVAL; + + katom->extres = kmalloc_array(katom->nr_extres, sizeof(*katom->extres), GFP_KERNEL); + if (NULL == katom->extres) { + err_ret_val = -ENOMEM; + goto early_err_out; + } + + /* copy user buffer to the end of our real buffer. + * Make sure the struct sizes haven't changed in a way + * we don't support */ + BUILD_BUG_ON(sizeof(*input_extres) > sizeof(*katom->extres)); + input_extres = (struct base_external_resource *) + (((unsigned char *)katom->extres) + + (sizeof(*katom->extres) - sizeof(*input_extres)) * + katom->nr_extres); + + if (copy_from_user(input_extres, + get_compat_pointer(katom->kctx, user_atom->extres_list), + sizeof(*input_extres) * katom->nr_extres) != 0) { + err_ret_val = -EINVAL; + goto early_err_out; + } +#ifdef CONFIG_KDS + /* assume we have to wait for all */ + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_resources = kmalloc_array(katom->nr_extres, sizeof(struct kds_resource *), GFP_KERNEL); + + if (!kds_resources) { + err_ret_val = -ENOMEM; + goto early_err_out; + } + + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_access_bitmap = kcalloc(BITS_TO_LONGS(katom->nr_extres), + sizeof(unsigned long), + GFP_KERNEL); + if (!kds_access_bitmap) { + err_ret_val = -ENOMEM; + goto early_err_out; + } +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_MALI_DMA_FENCE + if (implicit_sync) { + info.resv_objs = kmalloc_array(katom->nr_extres, + sizeof(struct reservation_object *), + GFP_KERNEL); + if (!info.resv_objs) { + err_ret_val = -ENOMEM; + goto early_err_out; + } + + info.dma_fence_excl_bitmap = + kcalloc(BITS_TO_LONGS(katom->nr_extres), + sizeof(unsigned long), GFP_KERNEL); + if (!info.dma_fence_excl_bitmap) { + err_ret_val = -ENOMEM; + goto early_err_out; + } + } +#endif /* CONFIG_MALI_DMA_FENCE */ + + /* Take the processes mmap lock */ + down_read(¤t->mm->mmap_sem); + + /* need to keep the GPU VM locked while we set up UMM buffers */ + kbase_gpu_vm_lock(katom->kctx); + for (res_no = 0; res_no < katom->nr_extres; res_no++) { + struct base_external_resource *res; + struct kbase_va_region *reg; + struct kbase_mem_phy_alloc *alloc; + bool exclusive; + + res = &input_extres[res_no]; + exclusive = (res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE) + ? true : false; + reg = kbase_region_tracker_find_region_enclosing_address( + katom->kctx, + res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + /* did we find a matching region object? */ + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) { + /* roll back */ + goto failed_loop; + } + + if (!(katom->core_req & BASE_JD_REQ_SOFT_JOB) && + (reg->flags & KBASE_REG_SECURE)) { + katom->atom_flags |= KBASE_KATOM_FLAG_PROTECTED; + } + + alloc = kbase_map_external_resource(katom->kctx, reg, + current->mm +#ifdef CONFIG_KDS + , &kds_res_count, kds_resources, + kds_access_bitmap, exclusive +#endif + ); + if (!alloc) { + err_ret_val = -EINVAL; + goto failed_loop; + } + +#ifdef CONFIG_MALI_DMA_FENCE + if (implicit_sync && + reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + struct reservation_object *resv; + + resv = reg->gpu_alloc->imported.umm.dma_buf->resv; + if (resv) + kbase_dma_fence_add_reservation(resv, &info, + exclusive); + } +#endif /* CONFIG_MALI_DMA_FENCE */ + + /* finish with updating out array with the data we found */ + /* NOTE: It is important that this is the last thing we do (or + * at least not before the first write) as we overwrite elements + * as we loop and could be overwriting ourself, so no writes + * until the last read for an element. + * */ + katom->extres[res_no].gpu_address = reg->start_pfn << PAGE_SHIFT; /* save the start_pfn (as an address, not pfn) to use fast lookup later */ + katom->extres[res_no].alloc = alloc; + } + /* successfully parsed the extres array */ + /* drop the vm lock before we call into kds */ + kbase_gpu_vm_unlock(katom->kctx); + + /* Release the processes mmap lock */ + up_read(¤t->mm->mmap_sem); + +#ifdef CONFIG_KDS + if (kds_res_count) { + int wait_failed; + + /* We have resources to wait for with kds */ + katom->kds_dep_satisfied = false; + + wait_failed = kds_async_waitall(&katom->kds_rset, + &katom->kctx->jctx.kds_cb, katom, NULL, + kds_res_count, kds_access_bitmap, + kds_resources); + + if (wait_failed) + goto failed_kds_setup; + else + kbase_jd_kds_waiters_add(katom); + } else { + /* Nothing to wait for, so kds dep met */ + katom->kds_dep_satisfied = true; + } + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_MALI_DMA_FENCE + if (implicit_sync) { + if (info.dma_fence_resv_count) { + int ret; + + ret = kbase_dma_fence_wait(katom, &info); + if (ret < 0) + goto failed_dma_fence_setup; + } + + kfree(info.resv_objs); + kfree(info.dma_fence_excl_bitmap); + } +#endif /* CONFIG_MALI_DMA_FENCE */ + + /* all done OK */ + return 0; + +/* error handling section */ + +#ifdef CONFIG_MALI_DMA_FENCE +failed_dma_fence_setup: +#ifdef CONFIG_KDS + /* If we are here, dma_fence setup failed but KDS didn't. + * Revert KDS setup if any. + */ + if (kds_res_count) { + mutex_unlock(&katom->kctx->jctx.lock); + kds_resource_set_release_sync(&katom->kds_rset); + mutex_lock(&katom->kctx->jctx.lock); + + kbase_jd_kds_waiters_remove(katom); + katom->kds_dep_satisfied = true; + } +#endif /* CONFIG_KDS */ +#endif /* CONFIG_MALI_DMA_FENCE */ +#ifdef CONFIG_KDS +failed_kds_setup: +#endif +#if defined(CONFIG_KDS) || defined(CONFIG_MALI_DMA_FENCE) + /* Lock the processes mmap lock */ + down_read(¤t->mm->mmap_sem); + + /* lock before we unmap */ + kbase_gpu_vm_lock(katom->kctx); +#endif + + failed_loop: + /* undo the loop work */ + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; + + kbase_unmap_external_resource(katom->kctx, NULL, alloc); + } + kbase_gpu_vm_unlock(katom->kctx); + + /* Release the processes mmap lock */ + up_read(¤t->mm->mmap_sem); + + early_err_out: + kfree(katom->extres); + katom->extres = NULL; +#ifdef CONFIG_KDS + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ +#ifdef CONFIG_MALI_DMA_FENCE + if (implicit_sync) { + kfree(info.resv_objs); + kfree(info.dma_fence_excl_bitmap); + } +#endif + return err_ret_val; +} + +static inline void jd_resolve_dep(struct list_head *out_list, + struct kbase_jd_atom *katom, + u8 d, bool ctx_is_dying) +{ + u8 other_d = !d; + + while (!list_empty(&katom->dep_head[d])) { + struct kbase_jd_atom *dep_atom; + struct kbase_jd_atom *other_dep_atom; + u8 dep_type; + + dep_atom = list_entry(katom->dep_head[d].next, + struct kbase_jd_atom, dep_item[d]); + list_del(katom->dep_head[d].next); + + dep_type = kbase_jd_katom_dep_type(&dep_atom->dep[d]); + kbase_jd_katom_dep_clear(&dep_atom->dep[d]); + + if (katom->event_code != BASE_JD_EVENT_DONE && + (dep_type != BASE_JD_DEP_TYPE_ORDER)) { +#ifdef CONFIG_KDS + if (!dep_atom->kds_dep_satisfied) { + /* Just set kds_dep_satisfied to true. If the callback happens after this then it will early out and + * do nothing. If the callback doesn't happen then kbase_jd_post_external_resources will clean up + */ + dep_atom->kds_dep_satisfied = true; + } +#endif + +#ifdef CONFIG_MALI_DMA_FENCE + kbase_dma_fence_cancel_callbacks(dep_atom); +#endif + + dep_atom->event_code = katom->event_code; + KBASE_DEBUG_ASSERT(dep_atom->status != + KBASE_JD_ATOM_STATE_UNUSED); + + if ((dep_atom->core_req & BASE_JD_REQ_SOFT_REPLAY) + != BASE_JD_REQ_SOFT_REPLAY) { + dep_atom->will_fail_event_code = + dep_atom->event_code; + } else { + dep_atom->status = + KBASE_JD_ATOM_STATE_COMPLETED; + } + } + other_dep_atom = (struct kbase_jd_atom *) + kbase_jd_katom_dep_atom(&dep_atom->dep[other_d]); + + if (!dep_atom->in_jd_list && (!other_dep_atom || + (IS_GPU_ATOM(dep_atom) && !ctx_is_dying && + !dep_atom->will_fail_event_code && + !other_dep_atom->will_fail_event_code))) { + bool dep_satisfied = true; +#ifdef CONFIG_MALI_DMA_FENCE + int dep_count; + + dep_count = kbase_fence_dep_count_read(dep_atom); + if (likely(dep_count == -1)) { + dep_satisfied = true; + } else { + /* + * There are either still active callbacks, or + * all fences for this @dep_atom has signaled, + * but the worker that will queue the atom has + * not yet run. + * + * Wait for the fences to signal and the fence + * worker to run and handle @dep_atom. If + * @dep_atom was completed due to error on + * @katom, then the fence worker will pick up + * the complete status and error code set on + * @dep_atom above. + */ + dep_satisfied = false; + } +#endif /* CONFIG_MALI_DMA_FENCE */ + +#ifdef CONFIG_KDS + dep_satisfied = dep_satisfied && dep_atom->kds_dep_satisfied; +#endif + + if (dep_satisfied) { + dep_atom->in_jd_list = true; + list_add_tail(&dep_atom->jd_item, out_list); + } + } + } +} + +KBASE_EXPORT_TEST_API(jd_resolve_dep); + +#if MALI_CUSTOMER_RELEASE == 0 +static void jd_force_failure(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + kbdev->force_replay_count++; + + if (kbdev->force_replay_count >= kbdev->force_replay_limit) { + kbdev->force_replay_count = 0; + katom->event_code = BASE_JD_EVENT_FORCE_REPLAY; + + if (kbdev->force_replay_random) + kbdev->force_replay_limit = + (prandom_u32() % KBASEP_FORCE_REPLAY_RANDOM_LIMIT) + 1; + + dev_info(kbdev->dev, "force_replay : promoting to error\n"); + } +} + +/** Test to see if atom should be forced to fail. + * + * This function will check if an atom has a replay job as a dependent. If so + * then it will be considered for forced failure. */ +static void jd_check_force_failure(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + int i; + + if ((kbdev->force_replay_limit == KBASEP_FORCE_REPLAY_DISABLED) || + (katom->core_req & BASEP_JD_REQ_EVENT_NEVER)) + return; + + for (i = 1; i < BASE_JD_ATOM_COUNT; i++) { + if (kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[0]) == katom || + kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[1]) == katom) { + struct kbase_jd_atom *dep_atom = &kctx->jctx.atoms[i]; + + if ((dep_atom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == + BASE_JD_REQ_SOFT_REPLAY && + (dep_atom->core_req & kbdev->force_replay_core_req) + == kbdev->force_replay_core_req) { + jd_force_failure(kbdev, katom); + return; + } + } + } +} +#endif + +/** + * is_dep_valid - Validate that a dependency is valid for early dependency + * submission + * @katom: Dependency atom to validate + * + * A dependency is valid if any of the following are true : + * - It does not exist (a non-existent dependency does not block submission) + * - It is in the job scheduler + * - It has completed, does not have a failure event code, and has not been + * marked to fail in the future + * + * Return: true if valid, false otherwise + */ +static bool is_dep_valid(struct kbase_jd_atom *katom) +{ + /* If there's no dependency then this is 'valid' from the perspective of + * early dependency submission */ + if (!katom) + return true; + + /* Dependency must have reached the job scheduler */ + if (katom->status < KBASE_JD_ATOM_STATE_IN_JS) + return false; + + /* If dependency has completed and has failed or will fail then it is + * not valid */ + if (katom->status >= KBASE_JD_ATOM_STATE_HW_COMPLETED && + (katom->event_code != BASE_JD_EVENT_DONE || + katom->will_fail_event_code)) + return false; + + return true; +} + +static void jd_try_submitting_deps(struct list_head *out_list, + struct kbase_jd_atom *node) +{ + int i; + + for (i = 0; i < 2; i++) { + struct list_head *pos; + + list_for_each(pos, &node->dep_head[i]) { + struct kbase_jd_atom *dep_atom = list_entry(pos, + struct kbase_jd_atom, dep_item[i]); + + if (IS_GPU_ATOM(dep_atom) && !dep_atom->in_jd_list) { + /*Check if atom deps look sane*/ + bool dep0_valid = is_dep_valid( + dep_atom->dep[0].atom); + bool dep1_valid = is_dep_valid( + dep_atom->dep[1].atom); + bool dep_satisfied = true; +#ifdef CONFIG_MALI_DMA_FENCE + int dep_count; + + dep_count = kbase_fence_dep_count_read( + dep_atom); + if (likely(dep_count == -1)) { + dep_satisfied = true; + } else { + /* + * There are either still active callbacks, or + * all fences for this @dep_atom has signaled, + * but the worker that will queue the atom has + * not yet run. + * + * Wait for the fences to signal and the fence + * worker to run and handle @dep_atom. If + * @dep_atom was completed due to error on + * @katom, then the fence worker will pick up + * the complete status and error code set on + * @dep_atom above. + */ + dep_satisfied = false; + } +#endif /* CONFIG_MALI_DMA_FENCE */ +#ifdef CONFIG_KDS + dep_satisfied = dep_satisfied && + dep_atom->kds_dep_satisfied; +#endif + + if (dep0_valid && dep1_valid && dep_satisfied) { + dep_atom->in_jd_list = true; + list_add(&dep_atom->jd_item, out_list); + } + } + } + } +} + +/* + * Perform the necessary handling of an atom that has finished running + * on the GPU. + * + * Note that if this is a soft-job that has had kbase_prepare_soft_job called on it then the caller + * is responsible for calling kbase_finish_soft_job *before* calling this function. + * + * The caller must hold the kbase_jd_context.lock. + */ +bool jd_done_nolock(struct kbase_jd_atom *katom, + struct list_head *completed_jobs_ctx) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + struct list_head completed_jobs; + struct list_head runnable_jobs; + bool need_to_try_schedule_context = false; + int i; + + INIT_LIST_HEAD(&completed_jobs); + INIT_LIST_HEAD(&runnable_jobs); + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + +#if MALI_CUSTOMER_RELEASE == 0 + jd_check_force_failure(katom); +#endif + + /* This is needed in case an atom is failed due to being invalid, this + * can happen *before* the jobs that the atom depends on have completed */ + for (i = 0; i < 2; i++) { + if (kbase_jd_katom_dep_atom(&katom->dep[i])) { + list_del(&katom->dep_item[i]); + kbase_jd_katom_dep_clear(&katom->dep[i]); + } + } + + /* With PRLAM-10817 or PRLAM-10959 the last tile of a fragment job being soft-stopped can fail with + * BASE_JD_EVENT_TILE_RANGE_FAULT. + * + * So here if the fragment job failed with TILE_RANGE_FAULT and it has been soft-stopped, then we promote the + * error code to BASE_JD_EVENT_DONE + */ + + if ((kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10817) || kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10959)) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT) { + if ((katom->core_req & BASE_JD_REQ_FS) && (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED)) { + /* Promote the failure to job done */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->atom_flags = katom->atom_flags & (~KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED); + } + } + + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + list_add_tail(&katom->jd_item, &completed_jobs); + + while (!list_empty(&completed_jobs)) { + katom = list_entry(completed_jobs.prev, struct kbase_jd_atom, jd_item); + list_del(completed_jobs.prev); + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + for (i = 0; i < 2; i++) + jd_resolve_dep(&runnable_jobs, katom, i, + kbase_ctx_flag(kctx, KCTX_DYING)); + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_post_external_resources(katom); + + while (!list_empty(&runnable_jobs)) { + struct kbase_jd_atom *node; + + node = list_entry(runnable_jobs.next, + struct kbase_jd_atom, jd_item); + list_del(runnable_jobs.next); + node->in_jd_list = false; + + KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED); + + if (node->status != KBASE_JD_ATOM_STATE_COMPLETED && + !kbase_ctx_flag(kctx, KCTX_DYING)) { + need_to_try_schedule_context |= jd_run_atom(node); + } else { + node->event_code = katom->event_code; + + if ((node->core_req & + BASE_JD_REQ_SOFT_JOB_TYPE) == + BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(node)) + /* Don't complete this atom */ + continue; + } else if (node->core_req & + BASE_JD_REQ_SOFT_JOB) { + /* If this is a fence wait soft job + * then remove it from the list of sync + * waiters. + */ + if (BASE_JD_REQ_SOFT_FENCE_WAIT == node->core_req) + kbasep_remove_waiting_soft_job(node); + + kbase_finish_soft_job(node); + } + node->status = KBASE_JD_ATOM_STATE_COMPLETED; + } + + if (node->status == KBASE_JD_ATOM_STATE_COMPLETED) { + list_add_tail(&node->jd_item, &completed_jobs); + } else if (node->status == KBASE_JD_ATOM_STATE_IN_JS && + !node->will_fail_event_code) { + /* Node successfully submitted, try submitting + * dependencies as they may now be representable + * in JS */ + jd_try_submitting_deps(&runnable_jobs, node); + } + } + + /* Register a completed job as a disjoint event when the GPU + * is in a disjoint state (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kctx->kbdev); + if (completed_jobs_ctx) + list_add_tail(&katom->jd_item, completed_jobs_ctx); + else + kbase_event_post(kctx, katom); + + /* Decrement and check the TOTAL number of jobs. This includes + * those not tracked by the scheduler: 'not ready to run' and + * 'dependency-only' jobs. */ + if (--kctx->jctx.job_nr == 0) + wake_up(&kctx->jctx.zero_jobs_wait); /* All events are safely queued now, and we can signal any waiter + * that we've got no more jobs (so we can be safely terminated) */ + } + + return need_to_try_schedule_context; +} + +KBASE_EXPORT_TEST_API(jd_done_nolock); + +#ifdef CONFIG_GPU_TRACEPOINTS +enum { + CORE_REQ_DEP_ONLY, + CORE_REQ_SOFT, + CORE_REQ_COMPUTE, + CORE_REQ_FRAGMENT, + CORE_REQ_VERTEX, + CORE_REQ_TILER, + CORE_REQ_FRAGMENT_VERTEX, + CORE_REQ_FRAGMENT_VERTEX_TILER, + CORE_REQ_FRAGMENT_TILER, + CORE_REQ_VERTEX_TILER, + CORE_REQ_UNKNOWN +}; +static const char * const core_req_strings[] = { + "Dependency Only Job", + "Soft Job", + "Compute Shader Job", + "Fragment Shader Job", + "Vertex/Geometry Shader Job", + "Tiler Job", + "Fragment Shader + Vertex/Geometry Shader Job", + "Fragment Shader + Vertex/Geometry Shader Job + Tiler Job", + "Fragment Shader + Tiler Job", + "Vertex/Geometry Shader Job + Tiler Job", + "Unknown Job" +}; +static const char *kbasep_map_core_reqs_to_string(base_jd_core_req core_req) +{ + if (core_req & BASE_JD_REQ_SOFT_JOB) + return core_req_strings[CORE_REQ_SOFT]; + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + return core_req_strings[CORE_REQ_COMPUTE]; + switch (core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) { + case BASE_JD_REQ_DEP: + return core_req_strings[CORE_REQ_DEP_ONLY]; + case BASE_JD_REQ_FS: + return core_req_strings[CORE_REQ_FRAGMENT]; + case BASE_JD_REQ_CS: + return core_req_strings[CORE_REQ_VERTEX]; + case BASE_JD_REQ_T: + return core_req_strings[CORE_REQ_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_TILER]; + case (BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_VERTEX_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX_TILER]; + } + return core_req_strings[CORE_REQ_UNKNOWN]; +} +#endif + +bool jd_submit_atom(struct kbase_context *kctx, const struct base_jd_atom_v2 *user_atom, struct kbase_jd_atom *katom) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + int queued = 0; + int i; + int sched_prio; + bool ret; + bool will_fail = false; + + /* Update the TOTAL number of jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + jctx->job_nr++; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) + katom->start_timestamp.tv64 = 0; +#else + katom->start_timestamp = 0; +#endif + katom->udata = user_atom->udata; + katom->kctx = kctx; + katom->nr_extres = user_atom->nr_extres; + katom->extres = NULL; + katom->device_nr = user_atom->device_nr; + katom->affinity = 0; + katom->jc = user_atom->jc; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; + katom->core_req = user_atom->core_req; + katom->atom_flags = 0; + katom->retry_count = 0; + katom->need_cache_flush_cores_retained = 0; + katom->pre_dep = NULL; + katom->post_dep = NULL; + katom->x_pre_dep = NULL; + katom->x_post_dep = NULL; + katom->will_fail_event_code = BASE_JD_EVENT_NOT_STARTED; + + /* Implicitly sets katom->protected_state.enter as well. */ + katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; + + katom->age = kctx->age_count++; + + INIT_LIST_HEAD(&katom->jd_item); +#ifdef CONFIG_KDS + /* Start by assuming that the KDS dependencies are satisfied, + * kbase_jd_pre_external_resources will correct this if there are dependencies */ + katom->kds_dep_satisfied = true; + katom->kds_rset = NULL; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_MALI_DMA_FENCE + kbase_fence_dep_count_set(katom, -1); +#endif + + /* Don't do anything if there is a mess up with dependencies. + This is done in a separate cycle to check both the dependencies at ones, otherwise + it will be extra complexity to deal with 1st dependency ( just added to the list ) + if only the 2nd one has invalid config. + */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; + + if (dep_atom_number) { + if (dep_atom_type != BASE_JD_DEP_TYPE_ORDER && + dep_atom_type != BASE_JD_DEP_TYPE_DATA) { + katom->event_code = BASE_JD_EVENT_JOB_CONFIG_FAULT; + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + + /* Wrong dependency setup. Atom will be sent + * back to user space. Do not record any + * dependencies. */ + KBASE_TLSTREAM_TL_NEW_ATOM( + katom, + kbase_jd_atom_id(kctx, katom)); + KBASE_TLSTREAM_TL_RET_ATOM_CTX( + katom, kctx); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(katom, + TL_ATOM_STATE_IDLE); + + ret = jd_done_nolock(katom, NULL); + goto out; + } + } + } + + /* Add dependencies */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type; + struct kbase_jd_atom *dep_atom = &jctx->atoms[dep_atom_number]; + + dep_atom_type = user_atom->pre_dep[i].dependency_type; + kbase_jd_katom_dep_clear(&katom->dep[i]); + + if (!dep_atom_number) + continue; + + if (dep_atom->status == KBASE_JD_ATOM_STATE_UNUSED || + dep_atom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + + if (dep_atom->event_code == BASE_JD_EVENT_DONE) + continue; + /* don't stop this atom if it has an order dependency + * only to the failed one, try to submit it through + * the normal path + */ + if (dep_atom_type == BASE_JD_DEP_TYPE_ORDER && + dep_atom->event_code > BASE_JD_EVENT_ACTIVE) { + continue; + } + + /* Atom has completed, propagate the error code if any */ + katom->event_code = dep_atom->event_code; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + + /* This atom is going through soft replay or + * will be sent back to user space. Do not record any + * dependencies. */ + KBASE_TLSTREAM_TL_NEW_ATOM( + katom, + kbase_jd_atom_id(kctx, katom)); + KBASE_TLSTREAM_TL_RET_ATOM_CTX(katom, kctx); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(katom, + TL_ATOM_STATE_IDLE); + + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) { + ret = false; + goto out; + } + } + will_fail = true; + + } else { + /* Atom is in progress, add this atom to the list */ + list_add_tail(&katom->dep_item[i], &dep_atom->dep_head[i]); + kbase_jd_katom_dep_set(&katom->dep[i], dep_atom, dep_atom_type); + queued = 1; + } + } + + if (will_fail) { + if (!queued) { + ret = jd_done_nolock(katom, NULL); + + goto out; + } else { + katom->will_fail_event_code = katom->event_code; + ret = false; + + goto out; + } + } else { + /* These must occur after the above loop to ensure that an atom + * that depends on a previous atom with the same number behaves + * as expected */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + } + + /* For invalid priority, be most lenient and choose the default */ + sched_prio = kbasep_js_atom_prio_to_sched_prio(user_atom->prio); + if (sched_prio == KBASE_JS_ATOM_SCHED_PRIO_INVALID) + sched_prio = KBASE_JS_ATOM_SCHED_PRIO_DEFAULT; + katom->sched_priority = sched_prio; + + /* Create a new atom recording all dependencies it was set up with. */ + KBASE_TLSTREAM_TL_NEW_ATOM( + katom, + kbase_jd_atom_id(kctx, katom)); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(katom, TL_ATOM_STATE_IDLE); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY(katom, katom->sched_priority); + KBASE_TLSTREAM_TL_RET_ATOM_CTX(katom, kctx); + for (i = 0; i < 2; i++) + if (BASE_JD_DEP_TYPE_INVALID != kbase_jd_katom_dep_type( + &katom->dep[i])) { + KBASE_TLSTREAM_TL_DEP_ATOM_ATOM( + (void *)kbase_jd_katom_dep_atom( + &katom->dep[i]), + (void *)katom); + } else if (BASE_JD_DEP_TYPE_INVALID != + user_atom->pre_dep[i].dependency_type) { + /* Resolved dependency. */ + int dep_atom_number = + user_atom->pre_dep[i].atom_id; + struct kbase_jd_atom *dep_atom = + &jctx->atoms[dep_atom_number]; + + KBASE_TLSTREAM_TL_RDEP_ATOM_ATOM( + (void *)dep_atom, + (void *)katom); + } + + /* Reject atoms with job chain = NULL, as these cause issues with soft-stop */ + if (!katom->jc && (katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + dev_warn(kctx->kbdev->dev, "Rejecting atom with jc = NULL"); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom, NULL); + goto out; + } + + /* Reject atoms with an invalid device_nr */ + if ((katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) && + (katom->device_nr >= kctx->kbdev->gpu_props.num_core_groups)) { + dev_warn(kctx->kbdev->dev, + "Rejecting atom with invalid device_nr %d", + katom->device_nr); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom, NULL); + goto out; + } + + /* Reject atoms with invalid core requirements */ + if ((katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) && + (katom->core_req & BASE_JD_REQ_EVENT_COALESCE)) { + dev_warn(kctx->kbdev->dev, + "Rejecting atom with invalid core requirements"); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + katom->core_req &= ~BASE_JD_REQ_EVENT_COALESCE; + ret = jd_done_nolock(katom, NULL); + goto out; + } + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + /* handle what we need to do to access the external resources */ + if (kbase_jd_pre_external_resources(katom, user_atom) != 0) { + /* setup failed (no access, bad resource, unknown resource types, etc.) */ + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom, NULL); + goto out; + } + } + + /* Validate the atom. Function will return error if the atom is + * malformed. + * + * Soft-jobs never enter the job scheduler but have their own initialize method. + * + * If either fail then we immediately complete the atom with an error. + */ + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) { + if (!kbase_js_is_atom_valid(kctx->kbdev, katom)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom, NULL); + goto out; + } + } else { + /* Soft-job */ + if (kbase_prepare_soft_job(katom) != 0) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom, NULL); + goto out; + } + } + +#ifdef CONFIG_GPU_TRACEPOINTS + katom->work_id = atomic_inc_return(&jctx->work_id); + trace_gpu_job_enqueue(kctx->id, katom->work_id, + kbasep_map_core_reqs_to_string(katom->core_req)); +#endif + + if (queued && !IS_GPU_ATOM(katom)) { + ret = false; + goto out; + } +#ifdef CONFIG_KDS + if (!katom->kds_dep_satisfied) { + /* Queue atom due to KDS dependency */ + ret = false; + goto out; + } +#endif /* CONFIG_KDS */ + + +#ifdef CONFIG_MALI_DMA_FENCE + if (kbase_fence_dep_count_read(katom) != -1) { + ret = false; + goto out; + } +#endif /* CONFIG_MALI_DMA_FENCE */ + + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) + ret = false; + else + ret = jd_done_nolock(katom, NULL); + + goto out; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + ret = jd_done_nolock(katom, NULL); + goto out; + } + + ret = false; + } else if ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + ret = kbasep_js_add_job(kctx, katom); + /* If job was cancelled then resolve immediately */ + if (katom->event_code == BASE_JD_EVENT_JOB_CANCELLED) + ret = jd_done_nolock(katom, NULL); + } else { + /* This is a pure dependency. Resolve it immediately */ + ret = jd_done_nolock(katom, NULL); + } + + out: + return ret; +} + +int kbase_jd_submit(struct kbase_context *kctx, + void __user *user_addr, u32 nr_atoms, u32 stride, + bool uk6_atom) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + int err = 0; + int i; + bool need_to_try_schedule_context = false; + struct kbase_device *kbdev; + u32 latest_flush; + + /* + * kbase_jd_submit isn't expected to fail and so all errors with the + * jobs are reported by immediately failing them (through event system) + */ + kbdev = kctx->kbdev; + + beenthere(kctx, "%s", "Enter"); + + if (kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { + dev_err(kbdev->dev, "Attempt to submit to a context that has SUBMIT_DISABLED set on it"); + return -EINVAL; + } + + if (stride != sizeof(base_jd_atom_v2)) { + dev_err(kbdev->dev, "Stride passed to job_submit doesn't match kernel"); + return -EINVAL; + } + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_add_return(nr_atoms, + &kctx->timeline.jd_atoms_in_flight)); + + /* All atoms submitted in this call have the same flush ID */ + latest_flush = kbase_backend_get_current_flush_id(kbdev); + + for (i = 0; i < nr_atoms; i++) { + struct base_jd_atom_v2 user_atom; + struct kbase_jd_atom *katom; + + if (copy_from_user(&user_atom, user_addr, + sizeof(user_atom)) != 0) { + err = -EINVAL; + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, + atomic_sub_return(nr_atoms - i, + &kctx->timeline.jd_atoms_in_flight)); + break; + } + +#ifdef BASE_LEGACY_UK10_2_SUPPORT + if (KBASE_API_VERSION(10, 3) > kctx->api_version) + user_atom.core_req = (u32)(user_atom.compat_core_req + & 0x7fff); +#endif /* BASE_LEGACY_UK10_2_SUPPORT */ + + user_addr = (void __user *)((uintptr_t) user_addr + stride); + + mutex_lock(&jctx->lock); +#ifndef compiletime_assert +#define compiletime_assert_defined +#define compiletime_assert(x, msg) do { switch (0) { case 0: case (x):; } } \ +while (false) +#endif + compiletime_assert((1 << (8*sizeof(user_atom.atom_number))) == + BASE_JD_ATOM_COUNT, + "BASE_JD_ATOM_COUNT and base_atom_id type out of sync"); + compiletime_assert(sizeof(user_atom.pre_dep[0].atom_id) == + sizeof(user_atom.atom_number), + "BASE_JD_ATOM_COUNT and base_atom_id type out of sync"); +#ifdef compiletime_assert_defined +#undef compiletime_assert +#undef compiletime_assert_defined +#endif + katom = &jctx->atoms[user_atom.atom_number]; + + /* Record the flush ID for the cache flush optimisation */ + katom->flush_id = latest_flush; + + while (katom->status != KBASE_JD_ATOM_STATE_UNUSED) { + /* Atom number is already in use, wait for the atom to + * complete + */ + mutex_unlock(&jctx->lock); + + /* This thread will wait for the atom to complete. Due + * to thread scheduling we are not sure that the other + * thread that owns the atom will also schedule the + * context, so we force the scheduler to be active and + * hence eventually schedule this context at some point + * later. + */ + kbase_js_sched_all(kbdev); + + if (wait_event_killable(katom->completed, + katom->status == + KBASE_JD_ATOM_STATE_UNUSED) != 0) { + /* We're being killed so the result code + * doesn't really matter + */ + return 0; + } + mutex_lock(&jctx->lock); + } + + need_to_try_schedule_context |= + jd_submit_atom(kctx, &user_atom, katom); + + /* Register a completed job as a disjoint event when the GPU is in a disjoint state + * (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kbdev); + + mutex_unlock(&jctx->lock); + } + + if (need_to_try_schedule_context) + kbase_js_sched_all(kbdev); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_submit); + +void kbase_jd_done_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + u64 cache_jc = katom->jc; + struct kbasep_js_atom_retained_state katom_retained_state; + bool context_idle; + base_jd_core_req core_req = katom->core_req; + u64 affinity = katom->affinity; + enum kbase_atom_coreref_state coreref_state = katom->coreref_state; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + jctx = &kctx->jctx; + kbdev = kctx->kbdev; + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0); + + kbase_backend_complete_wq(kbdev, katom); + + /* + * Begin transaction on JD context and JS context + */ + mutex_lock(&jctx->lock); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(katom, TL_ATOM_STATE_DONE); + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* This worker only gets called on contexts that are scheduled *in*. This is + * because it only happens in response to an IRQ from a job that was + * running. + */ + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + if (katom->event_code == BASE_JD_EVENT_STOPPED) { + /* Atom has been promoted to stopped */ + unsigned long flags; + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + kbase_js_unpull(kctx, katom); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&jctx->lock); + + return; + } + + if (katom->event_code != BASE_JD_EVENT_DONE) + dev_err(kbdev->dev, + "t6xx: GPU fault 0x%02lx from job slot %d\n", + (unsigned long)katom->event_code, + katom->slot_nr); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + kbase_as_poking_timer_release_atom(kbdev, kctx, katom); + + /* Retain state before the katom disappears */ + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + + context_idle = kbase_js_complete_atom_wq(kctx, katom); + + KBASE_DEBUG_ASSERT(kbasep_js_has_atom_finished(&katom_retained_state)); + + kbasep_js_remove_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + katom->atom_flags &= ~KBASE_KATOM_FLAG_HOLDING_CTX_REF; + /* jd_done_nolock() requires the jsctx_mutex lock to be dropped */ + jd_done_nolock(katom, &kctx->completed_jobs); + + /* katom may have been freed now, do not use! */ + + if (context_idle) { + unsigned long flags; + + context_idle = false; + mutex_lock(&js_devdata->queue_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* If kbase_sched() has scheduled this context back in then + * KCTX_ACTIVE will have been set after we marked it as + * inactive, and another pm reference will have been taken, so + * drop our reference. But do not call kbase_jm_idle_ctx(), as + * the context is active and fast-starting is allowed. + * + * If an atom has been fast-started then kctx->atoms_pulled will + * be non-zero but KCTX_ACTIVE will still be false (as the + * previous pm reference has been inherited). Do NOT drop our + * reference, as it has been re-used, and leave the context as + * active. + * + * If no new atoms have been started then KCTX_ACTIVE will still + * be false and atoms_pulled will be zero, so drop the reference + * and call kbase_jm_idle_ctx(). + * + * As the checks are done under both the queue_mutex and + * hwaccess_lock is should be impossible for this to race + * with the scheduler code. + */ + if (kbase_ctx_flag(kctx, KCTX_ACTIVE) || + !atomic_read(&kctx->atoms_pulled)) { + /* Calling kbase_jm_idle_ctx() here will ensure that + * atoms are not fast-started when we drop the + * hwaccess_lock. This is not performed if + * KCTX_ACTIVE is set as in that case another pm + * reference has been taken and a fast-start would be + * valid. + */ + if (!kbase_ctx_flag(kctx, KCTX_ACTIVE)) + kbase_jm_idle_ctx(kbdev, kctx); + context_idle = true; + } else { + kbase_ctx_flag_set(kctx, KCTX_ACTIVE); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&js_devdata->queue_mutex); + } + + /* + * Transaction complete + */ + mutex_unlock(&jctx->lock); + + /* Job is now no longer running, so can now safely release the context + * reference, and handle any actions that were logged against the atom's retained state */ + + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); + + kbase_js_sched_all(kbdev); + + if (!atomic_dec_return(&kctx->work_count)) { + /* If worker now idle then post all events that jd_done_nolock() + * has queued */ + mutex_lock(&jctx->lock); + while (!list_empty(&kctx->completed_jobs)) { + struct kbase_jd_atom *atom = list_entry( + kctx->completed_jobs.next, + struct kbase_jd_atom, jd_item); + list_del(kctx->completed_jobs.next); + + kbase_event_post(kctx, atom); + } + mutex_unlock(&jctx->lock); + } + + kbase_backend_complete_wq_post_sched(kbdev, core_req, affinity, + coreref_state); + + if (context_idle) + kbase_pm_context_idle(kbdev); + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0); +} + +/** + * jd_cancel_worker - Work queue job cancel function. + * @data: a &struct work_struct + * + * Only called as part of 'Zapping' a context (which occurs on termination). + * Operates serially with the kbase_jd_done_worker() on the work queue. + * + * This can only be called on contexts that aren't scheduled. + * + * We don't need to release most of the resources that would occur on + * kbase_jd_done() or kbase_jd_done_worker(), because the atoms here must not be + * running (by virtue of only being called on contexts that aren't + * scheduled). + */ +static void jd_cancel_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + bool need_to_try_schedule_context; + bool attr_state_changed; + struct kbase_device *kbdev; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + kbdev = kctx->kbdev; + jctx = &kctx->jctx; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD(kbdev, JD_CANCEL_WORKER, kctx, katom, katom->jc, 0); + + /* This only gets called on contexts that are scheduled out. Hence, we must + * make sure we don't de-ref the number of running jobs (there aren't + * any), nor must we try to schedule out the context (it's already + * scheduled out). + */ + KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + /* Scheduler: Remove the job from the system */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + attr_state_changed = kbasep_js_remove_cancelled_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + mutex_lock(&jctx->lock); + + need_to_try_schedule_context = jd_done_nolock(katom, NULL); + /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to + * schedule the context. There's also no need for the jsctx_mutex to have been taken + * around this too. */ + KBASE_DEBUG_ASSERT(!need_to_try_schedule_context); + + /* katom may have been freed now, do not use! */ + mutex_unlock(&jctx->lock); + + if (attr_state_changed) + kbase_js_sched_all(kbdev); +} + +/** + * kbase_jd_done - Complete a job that has been removed from the Hardware + * @katom: atom which has been completed + * @slot_nr: slot the atom was on + * @end_timestamp: completion time + * @done_code: completion code + * + * This must be used whenever a job has been removed from the Hardware, e.g.: + * An IRQ indicates that the job finished (for both error and 'done' codes), or + * the job was evicted from the JS_HEAD_NEXT registers during a Soft/Hard stop. + * + * Some work is carried out immediately, and the rest is deferred onto a + * workqueue + * + * Context: + * This can be called safely from atomic context. + * The caller must hold kbdev->hwaccess_lock + */ +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, + ktime_t *end_timestamp, kbasep_js_atom_done_code done_code) +{ + struct kbase_context *kctx; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) + katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; + + KBASE_TRACE_ADD(kbdev, JD_DONE, kctx, katom, katom->jc, 0); + + kbase_job_check_leave_disjoint(kbdev, katom); + + katom->slot_nr = slot_nr; + + atomic_inc(&kctx->work_count); + +#ifdef CONFIG_DEBUG_FS + /* a failed job happened and is waiting for dumping*/ + if (!katom->will_fail_event_code && + kbase_debug_job_fault_process(katom, katom->event_code)) + return; +#endif + + WARN_ON(work_pending(&katom->work)); + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, kbase_jd_done_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +KBASE_EXPORT_TEST_API(kbase_jd_done); + +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(NULL != kctx); + + KBASE_TRACE_ADD(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0); + + /* This should only be done from a context that is not scheduled */ + KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + WARN_ON(work_pending(&katom->work)); + + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, jd_cancel_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + + +void kbase_jd_zap_context(struct kbase_context *kctx) +{ + struct kbase_jd_atom *katom; + struct list_head *entry, *tmp; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(kctx); + + kbdev = kctx->kbdev; + + KBASE_TRACE_ADD(kbdev, JD_ZAP_CONTEXT, kctx, NULL, 0u, 0u); + + kbase_js_zap_context(kctx); + + mutex_lock(&kctx->jctx.lock); + + /* + * While holding the struct kbase_jd_context lock clean up jobs which are known to kbase but are + * queued outside the job scheduler. + */ + + del_timer_sync(&kctx->soft_job_timeout); + list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { + katom = list_entry(entry, struct kbase_jd_atom, queue); + kbase_cancel_soft_job(katom); + } + + +#ifdef CONFIG_KDS + + /* For each job waiting on a kds resource, cancel the wait and force the job to + * complete early, this is done so that we don't leave jobs outstanding waiting + * on kds resources which may never be released when contexts are zapped, resulting + * in a hang. + * + * Note that we can safely iterate over the list as the struct kbase_jd_context lock is held, + * this prevents items being removed when calling job_done_nolock in kbase_cancel_kds_wait_job. + */ + + list_for_each(entry, &kctx->waiting_kds_resource) { + katom = list_entry(entry, struct kbase_jd_atom, node); + + kbase_cancel_kds_wait_job(katom); + } +#endif + +#ifdef CONFIG_MALI_DMA_FENCE + kbase_dma_fence_cancel_all_atoms(kctx); +#endif + + mutex_unlock(&kctx->jctx.lock); + +#ifdef CONFIG_MALI_DMA_FENCE + /* Flush dma-fence workqueue to ensure that any callbacks that may have + * been queued are done before continuing. + */ + flush_workqueue(kctx->dma_fence.wq); +#endif + + kbase_jm_wait_for_zero_jobs(kctx); +} + +KBASE_EXPORT_TEST_API(kbase_jd_zap_context); + +int kbase_jd_init(struct kbase_context *kctx) +{ + int i; + int mali_err = 0; +#ifdef CONFIG_KDS + int err; +#endif /* CONFIG_KDS */ + + KBASE_DEBUG_ASSERT(kctx); + + kctx->jctx.job_done_wq = alloc_workqueue("mali_jd", + WQ_HIGHPRI | WQ_UNBOUND, 1); + if (NULL == kctx->jctx.job_done_wq) { + mali_err = -ENOMEM; + goto out1; + } + + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) { + init_waitqueue_head(&kctx->jctx.atoms[i].completed); + + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[0]); + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[1]); + + /* Catch userspace attempting to use an atom which doesn't exist as a pre-dependency */ + kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; + kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; + +#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) + kctx->jctx.atoms[i].dma_fence.context = + dma_fence_context_alloc(1); + atomic_set(&kctx->jctx.atoms[i].dma_fence.seqno, 0); + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dma_fence.callbacks); +#endif + } + + mutex_init(&kctx->jctx.lock); + + init_waitqueue_head(&kctx->jctx.zero_jobs_wait); + + spin_lock_init(&kctx->jctx.tb_lock); + +#ifdef CONFIG_KDS + err = kds_callback_init(&kctx->jctx.kds_cb, 0, kds_dep_clear); + if (0 != err) { + mali_err = -EINVAL; + goto out2; + } +#endif /* CONFIG_KDS */ + + kctx->jctx.job_nr = 0; + INIT_LIST_HEAD(&kctx->completed_jobs); + atomic_set(&kctx->work_count, 0); + + return 0; + +#ifdef CONFIG_KDS + out2: + destroy_workqueue(kctx->jctx.job_done_wq); +#endif /* CONFIG_KDS */ + out1: + return mali_err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_init); + +void kbase_jd_exit(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + +#ifdef CONFIG_KDS + kds_callback_term(&kctx->jctx.kds_cb); +#endif /* CONFIG_KDS */ + /* Work queue is emptied by this */ + destroy_workqueue(kctx->jctx.job_done_wq); +} + +KBASE_EXPORT_TEST_API(kbase_jd_exit); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c new file mode 100644 index 000000000000..c8b37c4e3291 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c @@ -0,0 +1,235 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifdef CONFIG_DEBUG_FS + +#include +#include +#include +#include +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#include +#endif + +struct kbase_jd_debugfs_depinfo { + u8 id; + char type; +}; + +static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, + struct seq_file *sfile) +{ +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + struct kbase_sync_fence_info info; + int res; + + switch (atom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + res = kbase_sync_fence_out_info_get(atom, &info); + if (0 == res) { + seq_printf(sfile, "Sa([%p]%d) ", + info.fence, info.status); + break; + } + case BASE_JD_REQ_SOFT_FENCE_WAIT: + res = kbase_sync_fence_in_info_get(atom, &info); + if (0 == res) { + seq_printf(sfile, "Wa([%p]%d) ", + info.fence, info.status); + break; + } + default: + break; + } +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + +#ifdef CONFIG_MALI_DMA_FENCE + if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + struct kbase_fence_cb *cb; + + if (atom->dma_fence.fence) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence = atom->dma_fence.fence; +#else + struct dma_fence *fence = atom->dma_fence.fence; +#endif + + seq_printf(sfile, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) + "Sd(%u#%u: %s) ", +#else + "Sd(%llu#%u: %s) ", +#endif + fence->context, + fence->seqno, + dma_fence_is_signaled(fence) ? + "signaled" : "active"); + } + + list_for_each_entry(cb, &atom->dma_fence.callbacks, + node) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence = cb->fence; +#else + struct dma_fence *fence = cb->fence; +#endif + + seq_printf(sfile, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) + "Wd(%u#%u: %s) ", +#else + "Wd(%llu#%u: %s) ", +#endif + fence->context, + fence->seqno, + dma_fence_is_signaled(fence) ? + "signaled" : "active"); + } + } +#endif /* CONFIG_MALI_DMA_FENCE */ + +} + +static void kbasep_jd_debugfs_atom_deps( + struct kbase_jd_debugfs_depinfo *deps, + struct kbase_jd_atom *atom) +{ + struct kbase_context *kctx = atom->kctx; + int i; + + for (i = 0; i < 2; i++) { + deps[i].id = (unsigned)(atom->dep[i].atom ? + kbase_jd_atom_id(kctx, atom->dep[i].atom) : 0); + + switch (atom->dep[i].dep_type) { + case BASE_JD_DEP_TYPE_INVALID: + deps[i].type = ' '; + break; + case BASE_JD_DEP_TYPE_DATA: + deps[i].type = 'D'; + break; + case BASE_JD_DEP_TYPE_ORDER: + deps[i].type = '>'; + break; + default: + deps[i].type = '?'; + break; + } + } +} +/** + * kbasep_jd_debugfs_atoms_show - Show callback for the JD atoms debugfs file. + * @sfile: The debugfs entry + * @data: Data associated with the entry + * + * This function is called to get the contents of the JD atoms debugfs file. + * This is a report of all atoms managed by kbase_jd_context.atoms + * + * Return: 0 if successfully prints data in debugfs entry file, failure + * otherwise + */ +static int kbasep_jd_debugfs_atoms_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + struct kbase_jd_atom *atoms; + unsigned long irq_flags; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Print version */ + seq_printf(sfile, "v%u\n", MALI_JD_DEBUGFS_VERSION); + + /* Print U/K API version */ + seq_printf(sfile, "ukv%u.%u\n", BASE_UK_VERSION_MAJOR, + BASE_UK_VERSION_MINOR); + + /* Print table heading */ + seq_puts(sfile, " ID, Core req, St, CR, Predeps, Start time, Additional info...\n"); + + atoms = kctx->jctx.atoms; + /* General atom states */ + mutex_lock(&kctx->jctx.lock); + /* JS-related states */ + spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags); + for (i = 0; i != BASE_JD_ATOM_COUNT; ++i) { + struct kbase_jd_atom *atom = &atoms[i]; + s64 start_timestamp = 0; + struct kbase_jd_debugfs_depinfo deps[2]; + + if (atom->status == KBASE_JD_ATOM_STATE_UNUSED) + continue; + + /* start_timestamp is cleared as soon as the atom leaves UNUSED state + * and set before a job is submitted to the h/w, a non-zero value means + * it is valid */ + if (ktime_to_ns(atom->start_timestamp)) + start_timestamp = ktime_to_ns( + ktime_sub(ktime_get(), atom->start_timestamp)); + + kbasep_jd_debugfs_atom_deps(deps, atom); + + seq_printf(sfile, + "%3u, %8x, %2u, %2u, %c%3u %c%3u, %20lld, ", + i, atom->core_req, atom->status, + atom->coreref_state, + deps[0].type, deps[0].id, + deps[1].type, deps[1].id, + start_timestamp); + + + kbase_jd_debugfs_fence_info(atom, sfile); + + seq_puts(sfile, "\n"); + } + spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags); + mutex_unlock(&kctx->jctx.lock); + + return 0; +} + + +/** + * kbasep_jd_debugfs_atoms_open - open operation for atom debugfs file + * @in: &struct inode pointer + * @file: &struct file pointer + * + * Return: file descriptor + */ +static int kbasep_jd_debugfs_atoms_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_jd_debugfs_atoms_show, in->i_private); +} + +static const struct file_operations kbasep_jd_debugfs_atoms_fops = { + .open = kbasep_jd_debugfs_atoms_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Expose all atoms */ + debugfs_create_file("atoms", S_IRUGO, kctx->kctx_dentry, kctx, + &kbasep_jd_debugfs_atoms_fops); + +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.h new file mode 100644 index 000000000000..fae32919b22f --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_jd_debugfs.h + * Header file for job dispatcher-related entries in debugfs + */ + +#ifndef _KBASE_JD_DEBUGFS_H +#define _KBASE_JD_DEBUGFS_H + +#include + +#define MALI_JD_DEBUGFS_VERSION 2 + +/* Forward declarations */ +struct kbase_context; + +/** + * kbasep_jd_debugfs_ctx_init() - Add debugfs entries for JD system + * + * @kctx Pointer to kbase_context + */ +void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx); + +#endif /*_KBASE_JD_DEBUGFS_H*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jm.c b/drivers/gpu/arm/bifrost/mali_kbase_jm.c new file mode 100644 index 000000000000..0c5c6a6f78cb --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_jm.c @@ -0,0 +1,131 @@ +/* + * + * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * HW access job manager common APIs + */ + +#include +#include "mali_kbase_hwaccess_jm.h" +#include "mali_kbase_jm.h" + +/** + * kbase_jm_next_job() - Attempt to run the next @nr_jobs_to_submit jobs on slot + * @js on the active context. + * @kbdev: Device pointer + * @js: Job slot to run on + * @nr_jobs_to_submit: Number of jobs to attempt to submit + * + * Return: true if slot can still be submitted on, false if slot is now full. + */ +static bool kbase_jm_next_job(struct kbase_device *kbdev, int js, + int nr_jobs_to_submit) +{ + struct kbase_context *kctx; + int i; + + kctx = kbdev->hwaccess.active_kctx; + + if (!kctx) + return true; + + for (i = 0; i < nr_jobs_to_submit; i++) { + struct kbase_jd_atom *katom = kbase_js_pull(kctx, js); + + if (!katom) + return true; /* Context has no jobs on this slot */ + + kbase_backend_run_atom(kbdev, katom); + } + + return false; /* Slot ringbuffer should now be full */ +} + +u32 kbase_jm_kick(struct kbase_device *kbdev, u32 js_mask) +{ + u32 ret_mask = 0; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + while (js_mask) { + int js = ffs(js_mask) - 1; + int nr_jobs_to_submit = kbase_backend_slot_free(kbdev, js); + + if (kbase_jm_next_job(kbdev, js, nr_jobs_to_submit)) + ret_mask |= (1 << js); + + js_mask &= ~(1 << js); + } + + return ret_mask; +} + +void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!down_trylock(&js_devdata->schedule_sem)) { + kbase_jm_kick(kbdev, js_mask); + up(&js_devdata->schedule_sem); + } +} + +void kbase_jm_try_kick_all(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!down_trylock(&js_devdata->schedule_sem)) { + kbase_jm_kick_all(kbdev); + up(&js_devdata->schedule_sem); + } +} + +void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->hwaccess.active_kctx == kctx) + kbdev->hwaccess.active_kctx = NULL; +} + +struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (katom->event_code != BASE_JD_EVENT_STOPPED && + katom->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT) { + return kbase_js_complete_atom(katom, NULL); + } else { + kbase_js_unpull(katom->kctx, katom); + return NULL; + } +} + +struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, ktime_t *end_timestamp) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + return kbase_js_complete_atom(katom, end_timestamp); +} + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jm.h b/drivers/gpu/arm/bifrost/mali_kbase_jm.h new file mode 100644 index 000000000000..a74ee24c8058 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_jm.h @@ -0,0 +1,110 @@ +/* + * + * (C) COPYRIGHT 2014, 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/* + * Job manager common APIs + */ + +#ifndef _KBASE_JM_H_ +#define _KBASE_JM_H_ + +/** + * kbase_jm_kick() - Indicate that there are jobs ready to run. + * @kbdev: Device pointer + * @js_mask: Mask of the job slots that can be pulled from. + * + * Caller must hold the hwaccess_lock and schedule_sem semaphore + * + * Return: Mask of the job slots that can still be submitted to. + */ +u32 kbase_jm_kick(struct kbase_device *kbdev, u32 js_mask); + +/** + * kbase_jm_kick_all() - Indicate that there are jobs ready to run on all job + * slots. + * @kbdev: Device pointer + * + * Caller must hold the hwaccess_lock and schedule_sem semaphore + * + * Return: Mask of the job slots that can still be submitted to. + */ +static inline u32 kbase_jm_kick_all(struct kbase_device *kbdev) +{ + return kbase_jm_kick(kbdev, (1 << kbdev->gpu_props.num_job_slots) - 1); +} + +/** + * kbase_jm_try_kick - Attempt to call kbase_jm_kick + * @kbdev: Device pointer + * @js_mask: Mask of the job slots that can be pulled from + * Context: Caller must hold hwaccess_lock + * + * If schedule_sem can be immediately obtained then this function will call + * kbase_jm_kick() otherwise it will do nothing. + */ +void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask); + +/** + * kbase_jm_try_kick_all() - Attempt to call kbase_jm_kick_all + * @kbdev: Device pointer + * Context: Caller must hold hwaccess_lock + * + * If schedule_sem can be immediately obtained then this function will call + * kbase_jm_kick_all() otherwise it will do nothing. + */ +void kbase_jm_try_kick_all(struct kbase_device *kbdev); + +/** + * kbase_jm_idle_ctx() - Mark a context as idle. + * @kbdev: Device pointer + * @kctx: Context to mark as idle + * + * No more atoms will be pulled from this context until it is marked as active + * by kbase_js_use_ctx(). + * + * The context should have no atoms currently pulled from it + * (kctx->atoms_pulled == 0). + * + * Caller must hold the hwaccess_lock + */ +void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * kbase_jm_return_atom_to_js() - Return an atom to the job scheduler that has + * been soft-stopped or will fail due to a + * dependency + * @kbdev: Device pointer + * @katom: Atom that has been stopped or will be failed + * + * Return: Atom that has now been unblocked and can now be run, or NULL if none + */ +struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +/** + * kbase_jm_complete() - Complete an atom + * @kbdev: Device pointer + * @katom: Atom that has completed + * @end_timestamp: Timestamp of atom completion + * + * Return: Atom that has now been unblocked and can now be run, or NULL if none + */ +struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev, + struct kbase_jd_atom *katom, ktime_t *end_timestamp); + +#endif /* _KBASE_JM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.c b/drivers/gpu/arm/bifrost/mali_kbase_js.c new file mode 100644 index 000000000000..219e8c80146c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.c @@ -0,0 +1,2798 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Scheduler Implementation + */ +#include +#include +#if defined(CONFIG_MALI_GATOR_SUPPORT) +#include +#endif +#include +#include +#include + +#include +#include + +#include "mali_kbase_jm.h" +#include "mali_kbase_hwaccess_jm.h" + +/* + * Private types + */ + +/* Bitpattern indicating the result of releasing a context */ +enum { + /* The context was descheduled - caller should try scheduling in a new + * one to keep the runpool full */ + KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0), + /* Ctx attributes were changed - caller should try scheduling all + * contexts */ + KBASEP_JS_RELEASE_RESULT_SCHED_ALL = (1u << 1) +}; + +typedef u32 kbasep_js_release_result; + +const int kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS] = { + KBASE_JS_ATOM_SCHED_PRIO_MED, /* BASE_JD_PRIO_MEDIUM */ + KBASE_JS_ATOM_SCHED_PRIO_HIGH, /* BASE_JD_PRIO_HIGH */ + KBASE_JS_ATOM_SCHED_PRIO_LOW /* BASE_JD_PRIO_LOW */ +}; + +const base_jd_prio +kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT] = { + BASE_JD_PRIO_HIGH, /* KBASE_JS_ATOM_SCHED_PRIO_HIGH */ + BASE_JD_PRIO_MEDIUM, /* KBASE_JS_ATOM_SCHED_PRIO_MED */ + BASE_JD_PRIO_LOW /* KBASE_JS_ATOM_SCHED_PRIO_LOW */ +}; + + +/* + * Private function prototypes + */ +static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal( + struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbasep_js_atom_retained_state *katom_retained_state); + +static int kbase_js_get_slot(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +static void kbase_js_foreach_ctx_job(struct kbase_context *kctx, + kbasep_js_ctx_job_cb callback); + +/* Helper for trace subcodes */ +#if KBASE_TRACE_ENABLE +static int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + return atomic_read(&kctx->refcount); +} +#else /* KBASE_TRACE_ENABLE */ +static int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} +#endif /* KBASE_TRACE_ENABLE */ + +/* + * Private functions + */ + +/** + * core_reqs_from_jsn_features - Convert JSn_FEATURES to core requirements + * @features: JSn_FEATURE register value + * + * Given a JSn_FEATURE register value returns the core requirements that match + * + * Return: Core requirement bit mask + */ +static base_jd_core_req core_reqs_from_jsn_features(u16 features) +{ + base_jd_core_req core_req = 0u; + + if ((features & JS_FEATURE_SET_VALUE_JOB) != 0) + core_req |= BASE_JD_REQ_V; + + if ((features & JS_FEATURE_CACHE_FLUSH_JOB) != 0) + core_req |= BASE_JD_REQ_CF; + + if ((features & JS_FEATURE_COMPUTE_JOB) != 0) + core_req |= BASE_JD_REQ_CS; + + if ((features & JS_FEATURE_TILER_JOB) != 0) + core_req |= BASE_JD_REQ_T; + + if ((features & JS_FEATURE_FRAGMENT_JOB) != 0) + core_req |= BASE_JD_REQ_FS; + + return core_req; +} + +static void kbase_js_sync_timers(struct kbase_device *kbdev) +{ + mutex_lock(&kbdev->js_data.runpool_mutex); + kbase_backend_ctx_count_changed(kbdev); + mutex_unlock(&kbdev->js_data.runpool_mutex); +} + +/* Hold the mmu_hw_mutex and hwaccess_lock for this */ +bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + bool result = false; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + as_nr = kctx->as_nr; + if (atomic_read(&kctx->refcount) > 0) { + KBASE_DEBUG_ASSERT(as_nr >= 0); + + kbase_ctx_sched_retain_ctx_refcount(kctx); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RETAIN_CTX_NOLOCK, kctx, + NULL, 0u, atomic_read(&kctx->refcount)); + result = true; + } + + return result; +} + +/** + * jsctx_rb_none_to_pull_prio(): - Check if there are no pullable atoms + * @kctx: Pointer to kbase context with ring buffer. + * @js: Job slot id to check. + * @prio: Priority to check. + * + * Return true if there are no atoms to pull. There may be running atoms in the + * ring buffer even if there are no atoms to pull. It is also possible for the + * ring buffer to be full (with running atoms) when this functions returns + * true. + * + * Return: true if there are no atoms to pull, false otherwise. + */ +static inline bool +jsctx_rb_none_to_pull_prio(struct kbase_context *kctx, int js, int prio) +{ + struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + return RB_EMPTY_ROOT(&rb->runnable_tree); +} + +/** + * jsctx_rb_none_to_pull(): - Check if all priority ring buffers have no + * pullable atoms + * @kctx: Pointer to kbase context with ring buffer. + * @js: Job slot id to check. + * + * Caller must hold hwaccess_lock + * + * Return: true if the ring buffers for all priorities have no pullable atoms, + * false otherwise. + */ +static inline bool +jsctx_rb_none_to_pull(struct kbase_context *kctx, int js) +{ + int prio; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) { + if (!jsctx_rb_none_to_pull_prio(kctx, js, prio)) + return false; + } + + return true; +} + +/** + * jsctx_queue_foreach_prio(): - Execute callback for each entry in the queue. + * @kctx: Pointer to kbase context with the queue. + * @js: Job slot id to iterate. + * @prio: Priority id to iterate. + * @callback: Function pointer to callback. + * + * Iterate over a queue and invoke @callback for each entry in the queue, and + * remove the entry from the queue. + * + * If entries are added to the queue while this is running those entries may, or + * may not be covered. To ensure that all entries in the buffer have been + * enumerated when this function returns jsctx->lock must be held when calling + * this function. + * + * The HW access lock must always be held when calling this function. + */ +static void +jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio, + kbasep_js_ctx_job_cb callback) +{ + struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + while (!RB_EMPTY_ROOT(&queue->runnable_tree)) { + struct rb_node *node = rb_first(&queue->runnable_tree); + struct kbase_jd_atom *entry = rb_entry(node, + struct kbase_jd_atom, runnable_tree_node); + + rb_erase(node, &queue->runnable_tree); + callback(kctx->kbdev, entry); + } + + while (!list_empty(&queue->x_dep_head)) { + struct kbase_jd_atom *entry = list_entry(queue->x_dep_head.next, + struct kbase_jd_atom, queue); + + list_del(queue->x_dep_head.next); + + callback(kctx->kbdev, entry); + } +} + +/** + * jsctx_queue_foreach(): - Execute callback for each entry in every queue + * @kctx: Pointer to kbase context with queue. + * @js: Job slot id to iterate. + * @callback: Function pointer to callback. + * + * Iterate over all the different priorities, and for each call + * jsctx_queue_foreach_prio() to iterate over the queue and invoke @callback + * for each entry, and remove the entry from the queue. + */ +static inline void +jsctx_queue_foreach(struct kbase_context *kctx, int js, + kbasep_js_ctx_job_cb callback) +{ + int prio; + + for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) + jsctx_queue_foreach_prio(kctx, js, prio, callback); +} + +/** + * jsctx_rb_peek_prio(): - Check buffer and get next atom + * @kctx: Pointer to kbase context with ring buffer. + * @js: Job slot id to check. + * @prio: Priority id to check. + * + * Check the ring buffer for the specified @js and @prio and return a pointer to + * the next atom, unless the ring buffer is empty. + * + * Return: Pointer to next atom in buffer, or NULL if there is no atom. + */ +static inline struct kbase_jd_atom * +jsctx_rb_peek_prio(struct kbase_context *kctx, int js, int prio) +{ + struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; + struct rb_node *node; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + node = rb_first(&rb->runnable_tree); + if (!node) + return NULL; + + return rb_entry(node, struct kbase_jd_atom, runnable_tree_node); +} + +/** + * jsctx_rb_peek(): - Check all priority buffers and get next atom + * @kctx: Pointer to kbase context with ring buffer. + * @js: Job slot id to check. + * + * Check the ring buffers for all priorities, starting from + * KBASE_JS_ATOM_SCHED_PRIO_HIGH, for the specified @js and @prio and return a + * pointer to the next atom, unless all the priority's ring buffers are empty. + * + * Caller must hold the hwaccess_lock. + * + * Return: Pointer to next atom in buffer, or NULL if there is no atom. + */ +static inline struct kbase_jd_atom * +jsctx_rb_peek(struct kbase_context *kctx, int js) +{ + int prio; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) { + struct kbase_jd_atom *katom; + + katom = jsctx_rb_peek_prio(kctx, js, prio); + if (katom) + return katom; + } + + return NULL; +} + +/** + * jsctx_rb_pull(): - Mark atom in list as running + * @kctx: Pointer to kbase context with ring buffer. + * @katom: Pointer to katom to pull. + * + * Mark an atom previously obtained from jsctx_rb_peek() as running. + * + * @katom must currently be at the head of the ring buffer. + */ +static inline void +jsctx_rb_pull(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + int prio = katom->sched_priority; + int js = katom->slot_nr; + struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + /* Atoms must be pulled in the correct order. */ + WARN_ON(katom != jsctx_rb_peek_prio(kctx, js, prio)); + + rb_erase(&katom->runnable_tree_node, &rb->runnable_tree); +} + +#define LESS_THAN_WRAP(a, b) ((s32)(a - b) < 0) + +static void +jsctx_tree_add(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + int prio = katom->sched_priority; + int js = katom->slot_nr; + struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; + struct rb_node **new = &(queue->runnable_tree.rb_node), *parent = NULL; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + while (*new) { + struct kbase_jd_atom *entry = container_of(*new, + struct kbase_jd_atom, runnable_tree_node); + + parent = *new; + if (LESS_THAN_WRAP(katom->age, entry->age)) + new = &((*new)->rb_left); + else + new = &((*new)->rb_right); + } + + /* Add new node and rebalance tree. */ + rb_link_node(&katom->runnable_tree_node, parent, new); + rb_insert_color(&katom->runnable_tree_node, &queue->runnable_tree); +} + +/** + * jsctx_rb_unpull(): - Undo marking of atom in list as running + * @kctx: Pointer to kbase context with ring buffer. + * @katom: Pointer to katom to unpull. + * + * Undo jsctx_rb_pull() and put @katom back in the queue. + * + * jsctx_rb_unpull() must be called on atoms in the same order the atoms were + * pulled. + */ +static inline void +jsctx_rb_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + jsctx_tree_add(kctx, katom); +} + +static bool kbase_js_ctx_pullable(struct kbase_context *kctx, + int js, + bool is_scheduled); +static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js); +static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js); + +/* + * Functions private to KBase ('Protected' functions) + */ +int kbasep_js_devdata_init(struct kbase_device * const kbdev) +{ + struct kbasep_js_device_data *jsdd; + int i; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + jsdd = &kbdev->js_data; + +#ifdef CONFIG_MALI_DEBUG + /* Soft-stop will be disabled on a single context by default unless + * softstop_always is set */ + jsdd->softstop_always = false; +#endif /* CONFIG_MALI_DEBUG */ + jsdd->nr_all_contexts_running = 0; + jsdd->nr_user_contexts_running = 0; + jsdd->nr_contexts_pullable = 0; + atomic_set(&jsdd->nr_contexts_runnable, 0); + /* No ctx allowed to submit */ + jsdd->runpool_irq.submit_allowed = 0u; + memset(jsdd->runpool_irq.ctx_attr_ref_count, 0, + sizeof(jsdd->runpool_irq.ctx_attr_ref_count)); + memset(jsdd->runpool_irq.slot_affinities, 0, + sizeof(jsdd->runpool_irq.slot_affinities)); + memset(jsdd->runpool_irq.slot_affinity_refcount, 0, + sizeof(jsdd->runpool_irq.slot_affinity_refcount)); + INIT_LIST_HEAD(&jsdd->suspended_soft_jobs_list); + + /* Config attributes */ + jsdd->scheduling_period_ns = DEFAULT_JS_SCHEDULING_PERIOD_NS; + jsdd->soft_stop_ticks = DEFAULT_JS_SOFT_STOP_TICKS; + jsdd->soft_stop_ticks_cl = DEFAULT_JS_SOFT_STOP_TICKS_CL; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + jsdd->hard_stop_ticks_ss = DEFAULT_JS_HARD_STOP_TICKS_SS_8408; + else + jsdd->hard_stop_ticks_ss = DEFAULT_JS_HARD_STOP_TICKS_SS; + jsdd->hard_stop_ticks_cl = DEFAULT_JS_HARD_STOP_TICKS_CL; + jsdd->hard_stop_ticks_dumping = DEFAULT_JS_HARD_STOP_TICKS_DUMPING; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + jsdd->gpu_reset_ticks_ss = DEFAULT_JS_RESET_TICKS_SS_8408; + else + jsdd->gpu_reset_ticks_ss = DEFAULT_JS_RESET_TICKS_SS; + jsdd->gpu_reset_ticks_cl = DEFAULT_JS_RESET_TICKS_CL; + jsdd->gpu_reset_ticks_dumping = DEFAULT_JS_RESET_TICKS_DUMPING; + jsdd->ctx_timeslice_ns = DEFAULT_JS_CTX_TIMESLICE_NS; + atomic_set(&jsdd->soft_job_timeout_ms, DEFAULT_JS_SOFT_JOB_TIMEOUT); + + dev_dbg(kbdev->dev, "JS Config Attribs: "); + dev_dbg(kbdev->dev, "\tscheduling_period_ns:%u", + jsdd->scheduling_period_ns); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks:%u", + jsdd->soft_stop_ticks); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks_cl:%u", + jsdd->soft_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_ss:%u", + jsdd->hard_stop_ticks_ss); + dev_dbg(kbdev->dev, "\thard_stop_ticks_cl:%u", + jsdd->hard_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_dumping:%u", + jsdd->hard_stop_ticks_dumping); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_ss:%u", + jsdd->gpu_reset_ticks_ss); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_cl:%u", + jsdd->gpu_reset_ticks_cl); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_dumping:%u", + jsdd->gpu_reset_ticks_dumping); + dev_dbg(kbdev->dev, "\tctx_timeslice_ns:%u", + jsdd->ctx_timeslice_ns); + dev_dbg(kbdev->dev, "\tsoft_job_timeout:%i", + atomic_read(&jsdd->soft_job_timeout_ms)); + + if (!(jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_ss && + jsdd->hard_stop_ticks_ss < jsdd->gpu_reset_ticks_ss && + jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_dumping && + jsdd->hard_stop_ticks_dumping < + jsdd->gpu_reset_ticks_dumping)) { + dev_err(kbdev->dev, "Job scheduler timeouts invalid; soft/hard/reset tick counts should be in increasing order\n"); + return -EINVAL; + } + +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.", + jsdd->soft_stop_ticks, + jsdd->scheduling_period_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_dumping==%u at %uns per tick. Other hard-stops may still occur.", + jsdd->hard_stop_ticks_ss, + jsdd->hard_stop_ticks_dumping, + jsdd->scheduling_period_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS && KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Note: The JS tick timer (if coded) will still be run, but do nothing."); +#endif + + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) + jsdd->js_reqs[i] = core_reqs_from_jsn_features( + kbdev->gpu_props.props.raw_props.js_features[i]); + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + + mutex_init(&jsdd->runpool_mutex); + mutex_init(&jsdd->queue_mutex); + spin_lock_init(&kbdev->hwaccess_lock); + sema_init(&jsdd->schedule_sem, 1); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) { + INIT_LIST_HEAD(&jsdd->ctx_list_pullable[i]); + INIT_LIST_HEAD(&jsdd->ctx_list_unpullable[i]); + } + + return 0; +} + +void kbasep_js_devdata_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbasep_js_devdata_term(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, }; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + /* The caller must de-register all contexts before calling this + */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0); + KBASE_DEBUG_ASSERT(memcmp( + js_devdata->runpool_irq.ctx_attr_ref_count, + zero_ctx_attr_ref_count, + sizeof(zero_ctx_attr_ref_count)) == 0); + CSTD_UNUSED(zero_ctx_attr_ref_count); +} + +int kbasep_js_kctx_init(struct kbase_context * const kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + int i, j; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) + INIT_LIST_HEAD(&kctx->jctx.sched_info.ctx.ctx_list_entry[i]); + + js_kctx_info = &kctx->jctx.sched_info; + + js_kctx_info->ctx.nr_jobs = 0; + kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); + kbase_ctx_flag_clear(kctx, KCTX_DYING); + memset(js_kctx_info->ctx.ctx_attr_ref_count, 0, + sizeof(js_kctx_info->ctx.ctx_attr_ref_count)); + + /* Initially, the context is disabled from submission until the create + * flags are set */ + kbase_ctx_flag_set(kctx, KCTX_SUBMIT_DISABLED); + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + mutex_init(&js_kctx_info->ctx.jsctx_mutex); + + init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait); + + for (i = 0; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) { + for (j = 0; j < BASE_JM_MAX_NR_SLOTS; j++) { + INIT_LIST_HEAD(&kctx->jsctx_queue[i][j].x_dep_head); + kctx->jsctx_queue[i][j].runnable_tree = RB_ROOT; + } + } + + return 0; +} + +void kbasep_js_kctx_term(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + int js; + bool update_ctx_count = false; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_kctx_info = &kctx->jctx.sched_info; + + /* The caller must de-register all jobs before calling this */ + KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0); + + mutex_lock(&kbdev->js_data.queue_mutex); + mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) + list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + + if (kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)) { + WARN_ON(atomic_read(&kbdev->js_data.nr_contexts_runnable) <= 0); + atomic_dec(&kbdev->js_data.nr_contexts_runnable); + update_ctx_count = true; + kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); + } + + mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kbdev->js_data.queue_mutex); + + if (update_ctx_count) { + mutex_lock(&kbdev->js_data.runpool_mutex); + kbase_backend_ctx_count_changed(kbdev); + mutex_unlock(&kbdev->js_data.runpool_mutex); + } +} + +/** + * kbase_js_ctx_list_add_pullable_nolock - Variant of + * kbase_jd_ctx_list_add_pullable() + * where the caller must hold + * hwaccess_lock + * @kbdev: Device pointer + * @kctx: Context to add to queue + * @js: Job slot to use + * + * Caller must hold hwaccess_lock + * + * Return: true if caller should call kbase_backend_ctx_count_changed() + */ +static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js) +{ + bool ret = false; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])) + list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + + list_add_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], + &kbdev->js_data.ctx_list_pullable[js]); + + if (!kctx->slots_pullable) { + kbdev->js_data.nr_contexts_pullable++; + ret = true; + if (!atomic_read(&kctx->atoms_pulled)) { + WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); + atomic_inc(&kbdev->js_data.nr_contexts_runnable); + } + } + kctx->slots_pullable |= (1 << js); + + return ret; +} + +/** + * kbase_js_ctx_list_add_pullable_head_nolock - Variant of + * kbase_js_ctx_list_add_pullable_head() + * where the caller must hold + * hwaccess_lock + * @kbdev: Device pointer + * @kctx: Context to add to queue + * @js: Job slot to use + * + * Caller must hold hwaccess_lock + * + * Return: true if caller should call kbase_backend_ctx_count_changed() + */ +static bool kbase_js_ctx_list_add_pullable_head_nolock( + struct kbase_device *kbdev, struct kbase_context *kctx, int js) +{ + bool ret = false; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])) + list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + + list_add(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], + &kbdev->js_data.ctx_list_pullable[js]); + + if (!kctx->slots_pullable) { + kbdev->js_data.nr_contexts_pullable++; + ret = true; + if (!atomic_read(&kctx->atoms_pulled)) { + WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); + atomic_inc(&kbdev->js_data.nr_contexts_runnable); + } + } + kctx->slots_pullable |= (1 << js); + + return ret; +} + +/** + * kbase_js_ctx_list_add_pullable_head - Add context to the head of the + * per-slot pullable context queue + * @kbdev: Device pointer + * @kctx: Context to add to queue + * @js: Job slot to use + * + * If the context is on either the pullable or unpullable queues, then it is + * removed before being added to the head. + * + * This function should be used when a context has been scheduled, but no jobs + * can currently be pulled from it. + * + * Return: true if caller should call kbase_backend_ctx_count_changed() + */ +static bool kbase_js_ctx_list_add_pullable_head(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js) +{ + bool ret; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + ret = kbase_js_ctx_list_add_pullable_head_nolock(kbdev, kctx, js); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return ret; +} + +/** + * kbase_js_ctx_list_add_unpullable_nolock - Add context to the tail of the + * per-slot unpullable context queue + * @kbdev: Device pointer + * @kctx: Context to add to queue + * @js: Job slot to use + * + * The context must already be on the per-slot pullable queue. It will be + * removed from the pullable queue before being added to the unpullable queue. + * + * This function should be used when a context has been pulled from, and there + * are no jobs remaining on the specified slot. + * + * Caller must hold hwaccess_lock + * + * Return: true if caller should call kbase_backend_ctx_count_changed() + */ +static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js) +{ + bool ret = false; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + list_move_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], + &kbdev->js_data.ctx_list_unpullable[js]); + + if (kctx->slots_pullable == (1 << js)) { + kbdev->js_data.nr_contexts_pullable--; + ret = true; + if (!atomic_read(&kctx->atoms_pulled)) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); + atomic_dec(&kbdev->js_data.nr_contexts_runnable); + } + } + kctx->slots_pullable &= ~(1 << js); + + return ret; +} + +/** + * kbase_js_ctx_list_remove_nolock - Remove context from the per-slot pullable + * or unpullable context queues + * @kbdev: Device pointer + * @kctx: Context to remove from queue + * @js: Job slot to use + * + * The context must already be on one of the queues. + * + * This function should be used when a context has no jobs on the GPU, and no + * jobs remaining for the specified slot. + * + * Caller must hold hwaccess_lock + * + * Return: true if caller should call kbase_backend_ctx_count_changed() + */ +static bool kbase_js_ctx_list_remove_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx, + int js) +{ + bool ret = false; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + WARN_ON(list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])); + + list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + + if (kctx->slots_pullable == (1 << js)) { + kbdev->js_data.nr_contexts_pullable--; + ret = true; + if (!atomic_read(&kctx->atoms_pulled)) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); + atomic_dec(&kbdev->js_data.nr_contexts_runnable); + } + } + kctx->slots_pullable &= ~(1 << js); + + return ret; +} + +/** + * kbase_js_ctx_list_pop_head_nolock - Variant of kbase_js_ctx_list_pop_head() + * where the caller must hold + * hwaccess_lock + * @kbdev: Device pointer + * @js: Job slot to use + * + * Caller must hold hwaccess_lock + * + * Return: Context to use for specified slot. + * NULL if no contexts present for specified slot + */ +static struct kbase_context *kbase_js_ctx_list_pop_head_nolock( + struct kbase_device *kbdev, + int js) +{ + struct kbase_context *kctx; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (list_empty(&kbdev->js_data.ctx_list_pullable[js])) + return NULL; + + kctx = list_entry(kbdev->js_data.ctx_list_pullable[js].next, + struct kbase_context, + jctx.sched_info.ctx.ctx_list_entry[js]); + + list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + + return kctx; +} + +/** + * kbase_js_ctx_list_pop_head - Pop the head context off the per-slot pullable + * queue. + * @kbdev: Device pointer + * @js: Job slot to use + * + * Return: Context to use for specified slot. + * NULL if no contexts present for specified slot + */ +static struct kbase_context *kbase_js_ctx_list_pop_head( + struct kbase_device *kbdev, int js) +{ + struct kbase_context *kctx; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kctx = kbase_js_ctx_list_pop_head_nolock(kbdev, js); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return kctx; +} + +/** + * kbase_js_ctx_pullable - Return if a context can be pulled from on the + * specified slot + * @kctx: Context pointer + * @js: Job slot to use + * @is_scheduled: true if the context is currently scheduled + * + * Caller must hold hwaccess_lock + * + * Return: true if context can be pulled from on specified slot + * false otherwise + */ +static bool kbase_js_ctx_pullable(struct kbase_context *kctx, int js, + bool is_scheduled) +{ + struct kbasep_js_device_data *js_devdata; + struct kbase_jd_atom *katom; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + js_devdata = &kctx->kbdev->js_data; + + if (is_scheduled) { + if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) + return false; + } + katom = jsctx_rb_peek(kctx, js); + if (!katom) + return false; /* No pullable atoms */ + if (kctx->blocked_js[js][katom->sched_priority]) + return false; + if (atomic_read(&katom->blocked)) + return false; /* next atom blocked */ + if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) { + if (katom->x_pre_dep->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB || + katom->x_pre_dep->will_fail_event_code) + return false; + if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) && + kbase_backend_nr_atoms_on_slot(kctx->kbdev, js)) + return false; + } + + return true; +} + +static bool kbase_js_dep_validate(struct kbase_context *kctx, + struct kbase_jd_atom *katom) +{ + struct kbase_device *kbdev = kctx->kbdev; + bool ret = true; + bool has_dep = false, has_x_dep = false; + int js = kbase_js_get_slot(kbdev, katom); + int prio = katom->sched_priority; + int i; + + for (i = 0; i < 2; i++) { + struct kbase_jd_atom *dep_atom = katom->dep[i].atom; + + if (dep_atom) { + int dep_js = kbase_js_get_slot(kbdev, dep_atom); + int dep_prio = dep_atom->sched_priority; + + /* Dependent atom must already have been submitted */ + if (!(dep_atom->atom_flags & + KBASE_KATOM_FLAG_JSCTX_IN_TREE)) { + ret = false; + break; + } + + /* Dependencies with different priorities can't + be represented in the ringbuffer */ + if (prio != dep_prio) { + ret = false; + break; + } + + if (js == dep_js) { + /* Only one same-slot dependency can be + * represented in the ringbuffer */ + if (has_dep) { + ret = false; + break; + } + /* Each dependee atom can only have one + * same-slot dependency */ + if (dep_atom->post_dep) { + ret = false; + break; + } + has_dep = true; + } else { + /* Only one cross-slot dependency can be + * represented in the ringbuffer */ + if (has_x_dep) { + ret = false; + break; + } + /* Each dependee atom can only have one + * cross-slot dependency */ + if (dep_atom->x_post_dep) { + ret = false; + break; + } + /* The dependee atom can not already be in the + * HW access ringbuffer */ + if (dep_atom->gpu_rb_state != + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { + ret = false; + break; + } + /* The dependee atom can not already have + * completed */ + if (dep_atom->status != + KBASE_JD_ATOM_STATE_IN_JS) { + ret = false; + break; + } + /* Cross-slot dependencies must not violate + * PRLAM-8987 affinity restrictions */ + if (kbase_hw_has_issue(kbdev, + BASE_HW_ISSUE_8987) && + (js == 2 || dep_js == 2)) { + ret = false; + break; + } + has_x_dep = true; + } + + /* Dependency can be represented in ringbuffers */ + } + } + + /* If dependencies can be represented by ringbuffer then clear them from + * atom structure */ + if (ret) { + for (i = 0; i < 2; i++) { + struct kbase_jd_atom *dep_atom = katom->dep[i].atom; + + if (dep_atom) { + int dep_js = kbase_js_get_slot(kbdev, dep_atom); + + if ((js != dep_js) && + (dep_atom->status != + KBASE_JD_ATOM_STATE_COMPLETED) + && (dep_atom->status != + KBASE_JD_ATOM_STATE_HW_COMPLETED) + && (dep_atom->status != + KBASE_JD_ATOM_STATE_UNUSED)) { + + katom->atom_flags |= + KBASE_KATOM_FLAG_X_DEP_BLOCKED; + katom->x_pre_dep = dep_atom; + dep_atom->x_post_dep = katom; + if (kbase_jd_katom_dep_type( + &katom->dep[i]) == + BASE_JD_DEP_TYPE_DATA) + katom->atom_flags |= + KBASE_KATOM_FLAG_FAIL_BLOCKER; + } + if ((kbase_jd_katom_dep_type(&katom->dep[i]) + == BASE_JD_DEP_TYPE_DATA) && + (js == dep_js)) { + katom->pre_dep = dep_atom; + dep_atom->post_dep = katom; + } + + list_del(&katom->dep_item[i]); + kbase_jd_katom_dep_clear(&katom->dep[i]); + } + } + } + + return ret; +} + +bool kbasep_js_add_job(struct kbase_context *kctx, + struct kbase_jd_atom *atom) +{ + unsigned long flags; + struct kbasep_js_kctx_info *js_kctx_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + + bool enqueue_required = false; + bool timer_sync = false; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + lockdep_assert_held(&kctx->jctx.lock); + + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* + * Begin Runpool transaction + */ + mutex_lock(&js_devdata->runpool_mutex); + + /* Refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX); + ++(js_kctx_info->ctx.nr_jobs); + + /* Setup any scheduling information */ + kbasep_js_clear_job_retry_submit(atom); + + /* Lock for state available during IRQ */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + if (!kbase_js_dep_validate(kctx, atom)) { + /* Dependencies could not be represented */ + --(js_kctx_info->ctx.nr_jobs); + + /* Setting atom status back to queued as it still has unresolved + * dependencies */ + atom->status = KBASE_JD_ATOM_STATE_QUEUED; + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + + goto out_unlock; + } + + KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(atom, TL_ATOM_STATE_READY); + KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, atom)); + + enqueue_required = kbase_js_dep_resolved_submit(kctx, atom); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc, + kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* Context Attribute Refcounting */ + kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom); + + if (enqueue_required) { + if (kbase_js_ctx_pullable(kctx, atom->slot_nr, false)) + timer_sync = kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, atom->slot_nr); + else + timer_sync = kbase_js_ctx_list_add_unpullable_nolock( + kbdev, kctx, atom->slot_nr); + } + /* If this context is active and the atom is the first on its slot, + * kick the job manager to attempt to fast-start the atom */ + if (enqueue_required && kctx == kbdev->hwaccess.active_kctx) + kbase_jm_try_kick(kbdev, 1 << atom->slot_nr); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + if (timer_sync) + kbase_backend_ctx_count_changed(kbdev); + mutex_unlock(&js_devdata->runpool_mutex); + /* End runpool transaction */ + + if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) { + if (kbase_ctx_flag(kctx, KCTX_DYING)) { + /* A job got added while/after kbase_job_zap_context() + * was called on a non-scheduled context (e.g. KDS + * dependency resolved). Kill that job by killing the + * context. */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, + false); + } else if (js_kctx_info->ctx.nr_jobs == 1) { + /* Handle Refcount going from 0 to 1: schedule the + * context on the Queue */ + KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + dev_dbg(kbdev->dev, "JS: Enqueue Context %p", kctx); + + /* Queue was updated - caller must try to + * schedule the head context */ + WARN_ON(!enqueue_required); + } + } +out_unlock: + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + mutex_unlock(&js_devdata->queue_mutex); + + return enqueue_required; +} + +void kbasep_js_remove_job(struct kbase_device *kbdev, + struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc, + kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* De-refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0); + --(js_kctx_info->ctx.nr_jobs); +} + +bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, + struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + unsigned long flags; + struct kbasep_js_atom_retained_state katom_retained_state; + struct kbasep_js_device_data *js_devdata; + bool attr_state_changed; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + js_devdata = &kbdev->js_data; + + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + kbasep_js_remove_job(kbdev, kctx, katom); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* The atom has 'finished' (will not be re-run), so no need to call + * kbasep_js_has_atom_finished(). + * + * This is because it returns false for soft-stopped atoms, but we + * want to override that, because we're cancelling an atom regardless of + * whether it was soft-stopped or not */ + attr_state_changed = kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, + &katom_retained_state); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return attr_state_changed; +} + +bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + bool result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + return result; +} + +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, + int as_nr) +{ + unsigned long flags; + struct kbase_context *found_kctx = NULL; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + found_kctx = kbdev->as_to_kctx[as_nr]; + + if (found_kctx != NULL) + kbase_ctx_sched_retain_ctx_refcount(found_kctx); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return found_kctx; +} + +/** + * kbasep_js_release_result - Try running more jobs after releasing a context + * and/or atom + * + * @kbdev: The kbase_device to operate on + * @kctx: The kbase_context to operate on + * @katom_retained_state: Retained state from the atom + * @runpool_ctx_attr_change: True if the runpool context attributes have changed + * + * This collates a set of actions that must happen whilst hwaccess_lock is held. + * + * This includes running more jobs when: + * - The previously released kctx caused a ctx attribute change, + * - The released atom caused a ctx attribute change, + * - Slots were previously blocked due to affinity restrictions, + * - Submission during IRQ handling failed. + * + * Return: %KBASEP_JS_RELEASE_RESULT_SCHED_ALL if context attributes were + * changed. The caller should try scheduling all contexts + */ +static kbasep_js_release_result kbasep_js_run_jobs_after_ctx_and_atom_release( + struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbasep_js_atom_retained_state *katom_retained_state, + bool runpool_ctx_attr_change) +{ + struct kbasep_js_device_data *js_devdata; + kbasep_js_release_result result = 0; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom_retained_state != NULL); + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (js_devdata->nr_user_contexts_running != 0) { + bool retry_submit = false; + int retry_jobslot = 0; + + if (katom_retained_state) + retry_submit = kbasep_js_get_atom_retry_submit_slot( + katom_retained_state, &retry_jobslot); + + if (runpool_ctx_attr_change || retry_submit) { + /* A change in runpool ctx attributes might mean we can + * run more jobs than before */ + result = KBASEP_JS_RELEASE_RESULT_SCHED_ALL; + + KBASE_TRACE_ADD_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB, + kctx, NULL, 0u, retry_jobslot); + } + } + return result; +} + +/* + * Internal function to release the reference on a ctx and an atom's "retained + * state", only taking the runpool and as transaction mutexes + * + * This also starts more jobs running in the case of an ctx-attribute state + * change + * + * This does none of the followup actions for scheduling: + * - It does not schedule in a new context + * - It does not requeue or handle dying contexts + * + * For those tasks, just call kbasep_js_runpool_release_ctx() instead + * + * Requires: + * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr + * - Context has a non-zero refcount + * - Caller holds js_kctx_info->ctx.jsctx_mutex + * - Caller holds js_devdata->runpool_mutex + */ +static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal( + struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbasep_js_atom_retained_state *katom_retained_state) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + kbasep_js_release_result release_result = 0u; + bool runpool_ctx_attr_change = false; + int kctx_as_nr; + int new_ref_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + kctx_as_nr = kctx->as_nr; + KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0); + + /* + * Transaction begins on AS and runpool_irq + * + * Assert about out calling contract + */ + mutex_lock(&kbdev->pm.lock); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr); + KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0); + + /* Update refcount */ + kbase_ctx_sched_release_ctx(kctx); + new_ref_count = atomic_read(&kctx->refcount); + + /* Release the atom if it finished (i.e. wasn't soft-stopped) */ + if (kbasep_js_has_atom_finished(katom_retained_state)) + runpool_ctx_attr_change |= kbasep_js_ctx_attr_ctx_release_atom( + kbdev, kctx, katom_retained_state); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RELEASE_CTX, kctx, NULL, 0u, + new_ref_count); + + if (new_ref_count == 2 && kbase_ctx_flag(kctx, KCTX_PRIVILEGED) && + !kbase_pm_is_suspending(kbdev)) { + /* Context is kept scheduled into an address space even when + * there are no jobs, in this case we have to handle the + * situation where all jobs have been evicted from the GPU and + * submission is disabled. + * + * At this point we re-enable submission to allow further jobs + * to be executed + */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + } + + /* Make a set of checks to see if the context should be scheduled out. + * Note that there'll always be at least 1 reference to the context + * which was previously acquired by kbasep_js_schedule_ctx(). */ + if (new_ref_count == 1 && + (!kbasep_js_is_submit_allowed(js_devdata, kctx) || + kbdev->pm.suspending)) { + int num_slots = kbdev->gpu_props.num_job_slots; + int slot; + + /* Last reference, and we've been told to remove this context + * from the Run Pool */ + dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p because refcount=%d, jobs=%d, allowed=%d", + kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, + kbasep_js_is_submit_allowed(js_devdata, kctx)); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_mmu_as_released(kctx->as_nr); +#endif + KBASE_TLSTREAM_TL_NRET_AS_CTX(&kbdev->as[kctx->as_nr], kctx); + + kbase_backend_release_ctx_irq(kbdev, kctx); + + if (kbdev->hwaccess.active_kctx == kctx) + kbdev->hwaccess.active_kctx = NULL; + + /* Ctx Attribute handling + * + * Releasing atoms attributes must either happen before this, or + * after the KCTX_SHEDULED flag is changed, otherwise we + * double-decount the attributes + */ + runpool_ctx_attr_change |= + kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx); + + /* Releasing the context and katom retained state can allow + * more jobs to run */ + release_result |= + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, + kctx, katom_retained_state, + runpool_ctx_attr_change); + + /* + * Transaction ends on AS and runpool_irq: + * + * By this point, the AS-related data is now clear and ready + * for re-use. + * + * Since releases only occur once for each previous successful + * retain, and no more retains are allowed on this context, no + * other thread will be operating in this + * code whilst we are + */ + + /* Recalculate pullable status for all slots */ + for (slot = 0; slot < num_slots; slot++) { + if (kbase_js_ctx_pullable(kctx, slot, false)) + kbase_js_ctx_list_add_pullable_nolock(kbdev, + kctx, slot); + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + kbase_backend_release_ctx_noirq(kbdev, kctx); + + mutex_unlock(&kbdev->pm.lock); + + /* Note: Don't reuse kctx_as_nr now */ + + /* Synchronize with any timers */ + kbase_backend_ctx_count_changed(kbdev); + + /* update book-keeping info */ + kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); + /* Signal any waiter that the context is not scheduled, so is + * safe for termination - once the jsctx_mutex is also dropped, + * and jobs have finished. */ + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Queue an action to occur after we've dropped the lock */ + release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED | + KBASEP_JS_RELEASE_RESULT_SCHED_ALL; + } else { + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, + katom_retained_state, runpool_ctx_attr_change); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->pm.lock); + } + + return release_result; +} + +void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_atom_retained_state katom_retained_state; + + /* Setup a dummy katom_retained_state */ + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + kbasep_js_runpool_release_ctx_internal(kbdev, kctx, + &katom_retained_state); +} + +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx, bool has_pm_ref) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* This is called if and only if you've you've detached the context from + * the Runpool Queue, and not added it back to the Runpool + */ + KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + if (kbase_ctx_flag(kctx, KCTX_DYING)) { + /* Dying: don't requeue, but kill all jobs on the context. This + * happens asynchronously */ + dev_dbg(kbdev->dev, + "JS: ** Killing Context %p on RunPool Remove **", kctx); + kbase_js_foreach_ctx_job(kctx, &kbase_jd_cancel); + } +} + +void kbasep_js_runpool_release_ctx_and_katom_retained_state( + struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbasep_js_atom_retained_state *katom_retained_state) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, + katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + + if (release_result & KBASEP_JS_RELEASE_RESULT_SCHED_ALL) + kbase_js_sched_all(kbdev); +} + +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_atom_retained_state katom_retained_state; + + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, + &katom_retained_state); +} + +/* Variant of kbasep_js_runpool_release_ctx() that doesn't call into + * kbase_js_sched_all() */ +static void kbasep_js_runpool_release_ctx_no_schedule( + struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + struct kbasep_js_atom_retained_state katom_retained_state_struct; + struct kbasep_js_atom_retained_state *katom_retained_state = + &katom_retained_state_struct; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + kbasep_js_atom_retained_state_init_invalid(katom_retained_state); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, + katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* NOTE: could return release_result if the caller would like to know + * whether it should schedule a new context, but currently no callers do + */ +} + +void kbase_js_set_timeouts(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + kbase_backend_timeouts_changed(kbdev); +} + +static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + unsigned long flags; + bool kctx_suspended = false; + int as_nr; + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* Pick available address space for this context */ + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + as_nr = kbase_ctx_sched_retain_ctx(kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + if (as_nr == KBASEP_AS_NR_INVALID) { + as_nr = kbase_backend_find_and_release_free_address_space( + kbdev, kctx); + if (as_nr != KBASEP_AS_NR_INVALID) { + /* Attempt to retain the context again, this should + * succeed */ + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + as_nr = kbase_ctx_sched_retain_ctx(kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + WARN_ON(as_nr == KBASEP_AS_NR_INVALID); + } + } + if (as_nr == KBASEP_AS_NR_INVALID) + return false; /* No address spaces currently available */ + + /* + * Atomic transaction on the Context and Run Pool begins + */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Check to see if context is dying due to kbase_job_zap_context() */ + if (kbase_ctx_flag(kctx, KCTX_DYING)) { + /* Roll back the transaction so far and return */ + kbase_ctx_sched_release_ctx(kctx); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + return false; + } + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, kctx, NULL, + 0u, + kbasep_js_trace_get_refcnt(kbdev, kctx)); + + kbase_ctx_flag_set(kctx, KCTX_SCHEDULED); + + /* Assign context to previously chosen address space */ + if (!kbase_backend_use_ctx(kbdev, kctx, as_nr)) { + /* Roll back the transaction so far and return */ + kbase_ctx_sched_release_ctx(kctx); + kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + return false; + } + + kbdev->hwaccess.active_kctx = kctx; + +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_mmu_as_in_use(kctx->as_nr); +#endif + KBASE_TLSTREAM_TL_RET_AS_CTX(&kbdev->as[kctx->as_nr], kctx); + + /* Cause any future waiter-on-termination to wait until the context is + * descheduled */ + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Re-check for suspending: a suspend could've occurred, and all the + * contexts could've been removed from the runpool before we took this + * lock. In this case, we don't want to allow this context to run jobs, + * we just want it out immediately. + * + * The DMB required to read the suspend flag was issued recently as part + * of the hwaccess_lock locking. If a suspend occurs *after* that lock + * was taken (i.e. this condition doesn't execute), then the + * kbasep_js_suspend() code will cleanup this context instead (by virtue + * of it being called strictly after the suspend flag is set, and will + * wait for this lock to drop) */ + if (kbase_pm_is_suspending(kbdev)) { + /* Cause it to leave at some later point */ + bool retained; + + retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + KBASE_DEBUG_ASSERT(retained); + + kbasep_js_clear_submit_allowed(js_devdata, kctx); + kctx_suspended = true; + } + + /* Transaction complete */ + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + + /* Synchronize with any timers */ + kbase_backend_ctx_count_changed(kbdev); + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* Note: after this point, the context could potentially get scheduled + * out immediately */ + + if (kctx_suspended) { + /* Finishing forcing out the context due to a suspend. Use a + * variant of kbasep_js_runpool_release_ctx() that doesn't + * schedule a new context, to prevent a risk of recursion back + * into this function */ + kbasep_js_runpool_release_ctx_no_schedule(kbdev, kctx); + return false; + } + return true; +} + +static bool kbase_js_use_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && + kbase_backend_use_ctx_sched(kbdev, kctx)) { + /* Context already has ASID - mark as active */ + kbdev->hwaccess.active_kctx = kctx; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + return true; /* Context already scheduled */ + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return kbasep_js_schedule_ctx(kbdev, kctx); +} + +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + bool is_scheduled; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* This must never be attempted whilst suspending - i.e. it should only + * happen in response to a syscall from a user-space thread */ + BUG_ON(kbase_pm_is_suspending(kbdev)); + + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* Mark the context as privileged */ + kbase_ctx_flag_set(kctx, KCTX_PRIVILEGED); + + is_scheduled = kbase_ctx_flag(kctx, KCTX_SCHEDULED); + if (!is_scheduled) { + /* Add the context to the pullable list */ + if (kbase_js_ctx_list_add_pullable_head(kbdev, kctx, 0)) + kbase_js_sync_timers(kbdev); + + /* Fast-starting requires the jsctx_mutex to be dropped, + * because it works on multiple ctxs */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + + /* Try to schedule the context in */ + kbase_js_sched_all(kbdev); + + /* Wait for the context to be scheduled in */ + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, + kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + } else { + /* Already scheduled in - We need to retain it to keep the + * corresponding address space */ + kbasep_js_runpool_retain_ctx(kbdev, kctx); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + } +} +KBASE_EXPORT_TEST_API(kbasep_js_schedule_privileged_ctx); + +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + + /* We don't need to use the address space anymore */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + kbase_ctx_flag_clear(kctx, KCTX_PRIVILEGED); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* Release the context - it will be scheduled out */ + kbasep_js_runpool_release_ctx(kbdev, kctx); + + kbase_js_sched_all(kbdev); +} +KBASE_EXPORT_TEST_API(kbasep_js_release_privileged_ctx); + +void kbasep_js_suspend(struct kbase_device *kbdev) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int i; + u16 retained = 0u; + int nr_privileged_ctx = 0; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev)); + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Prevent all contexts from submitting */ + js_devdata->runpool_irq.submit_allowed = 0; + + /* Retain each of the contexts, so we can cause it to leave even if it + * had no refcount to begin with */ + for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) { + struct kbase_context *kctx = kbdev->as_to_kctx[i]; + + retained = retained << 1; + + if (kctx) { + kbase_ctx_sched_retain_ctx_refcount(kctx); + retained |= 1u; + /* We can only cope with up to 1 privileged context - + * the instrumented context. It'll be suspended by + * disabling instrumentation */ + if (kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) { + ++nr_privileged_ctx; + WARN_ON(nr_privileged_ctx != 1); + } + } + } + CSTD_UNUSED(nr_privileged_ctx); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + /* De-ref the previous retain to ensure each context gets pulled out + * sometime later. */ + for (i = 0; + i < BASE_MAX_NR_AS; + ++i, retained = retained >> 1) { + struct kbase_context *kctx = kbdev->as_to_kctx[i]; + + if (retained & 1u) + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + + /* Caller must wait for all Power Manager active references to be + * dropped */ +} + +void kbasep_js_resume(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int js; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + mutex_lock(&js_devdata->queue_mutex); + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + struct kbase_context *kctx, *n; + + list_for_each_entry_safe(kctx, n, + &kbdev->js_data.ctx_list_unpullable[js], + jctx.sched_info.ctx.ctx_list_entry[js]) { + struct kbasep_js_kctx_info *js_kctx_info; + unsigned long flags; + bool timer_sync = false; + + js_kctx_info = &kctx->jctx.sched_info; + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) && + kbase_js_ctx_pullable(kctx, js, false)) + timer_sync = + kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, js); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + if (timer_sync) + kbase_backend_ctx_count_changed(kbdev); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } + } + mutex_unlock(&js_devdata->queue_mutex); + + /* Restart atom processing */ + kbase_js_sched_all(kbdev); + + /* JS Resume complete */ +} + +bool kbase_js_is_atom_valid(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + if ((katom->core_req & BASE_JD_REQ_FS) && + (katom->core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | + BASE_JD_REQ_T))) + return false; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987) && + (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) && + (katom->core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_T))) + return false; + + return true; +} + +static int kbase_js_get_slot(struct kbase_device *kbdev, + struct kbase_jd_atom *katom) +{ + if (katom->core_req & BASE_JD_REQ_FS) + return 0; + + if (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { + if (katom->device_nr == 1 && + kbdev->gpu_props.num_core_groups == 2) + return 2; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + return 2; + } + + return 1; +} + +bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, + struct kbase_jd_atom *katom) +{ + bool enqueue_required; + + katom->slot_nr = kbase_js_get_slot(kctx->kbdev, katom); + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + lockdep_assert_held(&kctx->jctx.lock); + + /* If slot will transition from unpullable to pullable then add to + * pullable list */ + if (jsctx_rb_none_to_pull(kctx, katom->slot_nr)) { + enqueue_required = true; + } else { + enqueue_required = false; + } + if ((katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) || + (katom->pre_dep && (katom->pre_dep->atom_flags & + KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) { + int prio = katom->sched_priority; + int js = katom->slot_nr; + struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; + + list_add_tail(&katom->queue, &queue->x_dep_head); + katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST; + enqueue_required = false; + } else { + /* Check if there are lower priority jobs to soft stop */ + kbase_job_slot_ctx_priority_check_locked(kctx, katom); + + /* Add atom to ring buffer. */ + jsctx_tree_add(kctx, katom); + katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE; + } + + return enqueue_required; +} + +/** + * kbase_js_move_to_tree - Move atom (and any dependent atoms) to the + * runnable_tree, ready for execution + * @katom: Atom to submit + * + * It is assumed that @katom does not have KBASE_KATOM_FLAG_X_DEP_BLOCKED set, + * but is still present in the x_dep list. If @katom has a same-slot dependent + * atom then that atom (and any dependents) will also be moved. + */ +static void kbase_js_move_to_tree(struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&katom->kctx->kbdev->hwaccess_lock); + + while (katom) { + WARN_ON(!(katom->atom_flags & + KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST)); + + if (!(katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) { + list_del(&katom->queue); + katom->atom_flags &= + ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST; + jsctx_tree_add(katom->kctx, katom); + katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE; + } else { + break; + } + + katom = katom->post_dep; + } +} + + +/** + * kbase_js_evict_deps - Evict dependencies of a failed atom. + * @kctx: Context pointer + * @katom: Pointer to the atom that has failed. + * @js: The job slot the katom was run on. + * @prio: Priority of the katom. + * + * Remove all post dependencies of an atom from the context ringbuffers. + * + * The original atom's event_code will be propogated to all dependent atoms. + * + * Context: Caller must hold the HW access lock + */ +static void kbase_js_evict_deps(struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, int prio) +{ + struct kbase_jd_atom *x_dep = katom->x_post_dep; + struct kbase_jd_atom *next_katom = katom->post_dep; + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + if (next_katom) { + KBASE_DEBUG_ASSERT(next_katom->status != + KBASE_JD_ATOM_STATE_HW_COMPLETED); + next_katom->will_fail_event_code = katom->event_code; + + } + + /* Has cross slot depenency. */ + if (x_dep && (x_dep->atom_flags & (KBASE_KATOM_FLAG_JSCTX_IN_TREE | + KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) { + /* Remove dependency.*/ + x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED; + + /* Fail if it had a data dependency. */ + if (x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) { + x_dep->will_fail_event_code = katom->event_code; + } + if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST) + kbase_js_move_to_tree(x_dep); + } +} + +struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js) +{ + struct kbase_jd_atom *katom; + struct kbasep_js_device_data *js_devdata; + struct kbase_device *kbdev; + int pulled; + + KBASE_DEBUG_ASSERT(kctx); + + kbdev = kctx->kbdev; + + js_devdata = &kbdev->js_data; + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) + return NULL; + if (kbase_pm_is_suspending(kbdev)) + return NULL; + + katom = jsctx_rb_peek(kctx, js); + if (!katom) + return NULL; + if (kctx->blocked_js[js][katom->sched_priority]) + return NULL; + if (atomic_read(&katom->blocked)) + return NULL; + + /* Due to ordering restrictions when unpulling atoms on failure, we do + * not allow multiple runs of fail-dep atoms from the same context to be + * present on the same slot */ + if (katom->pre_dep && atomic_read(&kctx->atoms_pulled_slot[js])) { + struct kbase_jd_atom *prev_atom = + kbase_backend_inspect_tail(kbdev, js); + + if (prev_atom && prev_atom->kctx != kctx) + return NULL; + } + + if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) { + if (katom->x_pre_dep->gpu_rb_state == + KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB || + katom->x_pre_dep->will_fail_event_code) + return NULL; + if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) && + kbase_backend_nr_atoms_on_slot(kbdev, js)) + return NULL; + } + + kbase_ctx_flag_set(kctx, KCTX_PULLED); + + pulled = atomic_inc_return(&kctx->atoms_pulled); + if (pulled == 1 && !kctx->slots_pullable) { + WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); + atomic_inc(&kbdev->js_data.nr_contexts_runnable); + } + atomic_inc(&kctx->atoms_pulled_slot[katom->slot_nr]); + kctx->atoms_pulled_slot_pri[katom->slot_nr][katom->sched_priority]++; + jsctx_rb_pull(kctx, katom); + + kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + + katom->atom_flags |= KBASE_KATOM_FLAG_HOLDING_CTX_REF; + + katom->ticks = 0; + + return katom; +} + + +static void js_return_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, + work); + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; + struct kbasep_js_atom_retained_state retained_state; + int js = katom->slot_nr; + int prio = katom->sched_priority; + bool timer_sync = false; + bool context_idle = false; + unsigned long flags; + base_jd_core_req core_req = katom->core_req; + u64 affinity = katom->affinity; + enum kbase_atom_coreref_state coreref_state = katom->coreref_state; + + KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(katom); + + kbase_backend_complete_wq(kbdev, katom); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + kbase_as_poking_timer_release_atom(kbdev, kctx, katom); + + kbasep_js_atom_retained_state_copy(&retained_state, katom); + + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + atomic_dec(&kctx->atoms_pulled); + atomic_dec(&kctx->atoms_pulled_slot[js]); + + atomic_dec(&katom->blocked); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kctx->atoms_pulled_slot_pri[js][katom->sched_priority]--; + + if (!atomic_read(&kctx->atoms_pulled_slot[js]) && + jsctx_rb_none_to_pull(kctx, js)) + timer_sync |= kbase_js_ctx_list_remove_nolock(kbdev, kctx, js); + + /* If this slot has been blocked due to soft-stopped atoms, and all + * atoms have now been processed, then unblock the slot */ + if (!kctx->atoms_pulled_slot_pri[js][prio] && + kctx->blocked_js[js][prio]) { + kctx->blocked_js[js][prio] = false; + + /* Only mark the slot as pullable if the context is not idle - + * that case is handled below */ + if (atomic_read(&kctx->atoms_pulled) && + kbase_js_ctx_pullable(kctx, js, true)) + timer_sync |= kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, js); + } + + if (!atomic_read(&kctx->atoms_pulled)) { + if (!kctx->slots_pullable) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); + atomic_dec(&kbdev->js_data.nr_contexts_runnable); + timer_sync = true; + } + + if (kctx->as_nr != KBASEP_AS_NR_INVALID && + !kbase_ctx_flag(kctx, KCTX_DYING)) { + int num_slots = kbdev->gpu_props.num_job_slots; + int slot; + + if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) + kbasep_js_set_submit_allowed(js_devdata, kctx); + + for (slot = 0; slot < num_slots; slot++) { + if (kbase_js_ctx_pullable(kctx, slot, true)) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, slot); + } + } + + kbase_jm_idle_ctx(kbdev, kctx); + + context_idle = true; + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + if (context_idle) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); + kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); + kbase_pm_context_idle(kbdev); + } + + if (timer_sync) + kbase_js_sync_timers(kbdev); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + + katom->atom_flags &= ~KBASE_KATOM_FLAG_HOLDING_CTX_REF; + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, + &retained_state); + + kbase_js_sched_all(kbdev); + + kbase_backend_complete_wq_post_sched(kbdev, core_req, affinity, + coreref_state); +} + +void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + jsctx_rb_unpull(kctx, katom); + + WARN_ON(work_pending(&katom->work)); + + /* Block re-submission until workqueue has run */ + atomic_inc(&katom->blocked); + + kbase_job_check_leave_disjoint(kctx->kbdev, katom); + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, js_return_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +bool kbase_js_complete_atom_wq(struct kbase_context *kctx, + struct kbase_jd_atom *katom) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + struct kbase_device *kbdev; + unsigned long flags; + bool timer_sync = false; + int atom_slot; + bool context_idle = false; + int prio = katom->sched_priority; + + kbdev = kctx->kbdev; + atom_slot = katom->slot_nr; + + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + + mutex_lock(&js_devdata->runpool_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + if (katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) { + context_idle = !atomic_dec_return(&kctx->atoms_pulled); + atomic_dec(&kctx->atoms_pulled_slot[atom_slot]); + kctx->atoms_pulled_slot_pri[atom_slot][prio]--; + + if (!atomic_read(&kctx->atoms_pulled) && + !kctx->slots_pullable) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); + kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); + atomic_dec(&kbdev->js_data.nr_contexts_runnable); + timer_sync = true; + } + + /* If this slot has been blocked due to soft-stopped atoms, and + * all atoms have now been processed, then unblock the slot */ + if (!kctx->atoms_pulled_slot_pri[atom_slot][prio] + && kctx->blocked_js[atom_slot][prio]) { + kctx->blocked_js[atom_slot][prio] = false; + if (kbase_js_ctx_pullable(kctx, atom_slot, true)) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, atom_slot); + } + } + WARN_ON(!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE)); + + if (!atomic_read(&kctx->atoms_pulled_slot[atom_slot]) && + jsctx_rb_none_to_pull(kctx, atom_slot)) { + if (!list_empty( + &kctx->jctx.sched_info.ctx.ctx_list_entry[atom_slot])) + timer_sync |= kbase_js_ctx_list_remove_nolock( + kctx->kbdev, kctx, atom_slot); + } + + /* + * If submission is disabled on this context (most likely due to an + * atom failure) and there are now no atoms left in the system then + * re-enable submission so that context can be scheduled again. + */ + if (!kbasep_js_is_submit_allowed(js_devdata, kctx) && + !atomic_read(&kctx->atoms_pulled) && + !kbase_ctx_flag(kctx, KCTX_DYING)) { + int js; + + kbasep_js_set_submit_allowed(js_devdata, kctx); + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + if (kbase_js_ctx_pullable(kctx, js, true)) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, js); + } + } else if (katom->x_post_dep && + kbasep_js_is_submit_allowed(js_devdata, kctx)) { + int js; + + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + if (kbase_js_ctx_pullable(kctx, js, true)) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kbdev, kctx, js); + } + } + + /* Mark context as inactive. The pm reference will be dropped later in + * jd_done_worker(). + */ + if (context_idle) + kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + if (timer_sync) + kbase_backend_ctx_count_changed(kbdev); + mutex_unlock(&js_devdata->runpool_mutex); + + return context_idle; +} + +struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, + ktime_t *end_timestamp) +{ + struct kbase_device *kbdev; + struct kbase_context *kctx = katom->kctx; + struct kbase_jd_atom *x_dep = katom->x_post_dep; + + kbdev = kctx->kbdev; + + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + if (katom->will_fail_event_code) + katom->event_code = katom->will_fail_event_code; + + katom->status = KBASE_JD_ATOM_STATE_HW_COMPLETED; + + if (katom->event_code != BASE_JD_EVENT_DONE) { + kbase_js_evict_deps(kctx, katom, katom->slot_nr, + katom->sched_priority); + } + +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP, + katom->slot_nr), NULL, 0); +#endif + + kbase_jd_done(katom, katom->slot_nr, end_timestamp, 0); + + /* Unblock cross dependency if present */ + if (x_dep && (katom->event_code == BASE_JD_EVENT_DONE || + !(x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER)) && + (x_dep->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) { + bool was_pullable = kbase_js_ctx_pullable(kctx, x_dep->slot_nr, + false); + x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED; + kbase_js_move_to_tree(x_dep); + if (!was_pullable && kbase_js_ctx_pullable(kctx, x_dep->slot_nr, + false)) + kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, + x_dep->slot_nr); + + if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) + return x_dep; + } + + return NULL; +} + +void kbase_js_sched(struct kbase_device *kbdev, int js_mask) +{ + struct kbasep_js_device_data *js_devdata; + struct kbase_context *last_active; + bool timer_sync = false; + bool ctx_waiting = false; + + js_devdata = &kbdev->js_data; + + down(&js_devdata->schedule_sem); + mutex_lock(&js_devdata->queue_mutex); + + last_active = kbdev->hwaccess.active_kctx; + + while (js_mask) { + int js; + + js = ffs(js_mask) - 1; + + while (1) { + struct kbase_context *kctx; + unsigned long flags; + bool context_idle = false; + + kctx = kbase_js_ctx_list_pop_head(kbdev, js); + + if (!kctx) { + js_mask &= ~(1 << js); + break; /* No contexts on pullable list */ + } + + if (!kbase_ctx_flag(kctx, KCTX_ACTIVE)) { + context_idle = true; + + if (kbase_pm_context_active_handle_suspend( + kbdev, + KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) { + /* Suspend pending - return context to + * queue and stop scheduling */ + mutex_lock( + &kctx->jctx.sched_info.ctx.jsctx_mutex); + if (kbase_js_ctx_list_add_pullable_head( + kctx->kbdev, kctx, js)) + kbase_js_sync_timers(kbdev); + mutex_unlock( + &kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + up(&js_devdata->schedule_sem); + return; + } + kbase_ctx_flag_set(kctx, KCTX_ACTIVE); + } + + if (!kbase_js_use_ctx(kbdev, kctx)) { + mutex_lock( + &kctx->jctx.sched_info.ctx.jsctx_mutex); + /* Context can not be used at this time */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (kbase_js_ctx_pullable(kctx, js, false) + || kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) + timer_sync |= + kbase_js_ctx_list_add_pullable_head_nolock( + kctx->kbdev, kctx, js); + else + timer_sync |= + kbase_js_ctx_list_add_unpullable_nolock( + kctx->kbdev, kctx, js); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, + flags); + mutex_unlock( + &kctx->jctx.sched_info.ctx.jsctx_mutex); + if (context_idle) { + WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); + kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); + kbase_pm_context_idle(kbdev); + } + + /* No more jobs can be submitted on this slot */ + js_mask &= ~(1 << js); + break; + } + mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbase_ctx_flag_clear(kctx, KCTX_PULLED); + + if (!kbase_jm_kick(kbdev, 1 << js)) + /* No more jobs can be submitted on this slot */ + js_mask &= ~(1 << js); + + if (!kbase_ctx_flag(kctx, KCTX_PULLED)) { + bool pullable = kbase_js_ctx_pullable(kctx, js, + true); + + /* Failed to pull jobs - push to head of list. + * Unless this context is already 'active', in + * which case it's effectively already scheduled + * so push it to the back of the list. */ + if (pullable && kctx == last_active) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kctx->kbdev, + kctx, js); + else if (pullable) + timer_sync |= + kbase_js_ctx_list_add_pullable_head_nolock( + kctx->kbdev, + kctx, js); + else + timer_sync |= + kbase_js_ctx_list_add_unpullable_nolock( + kctx->kbdev, + kctx, js); + + /* If this context is not the active context, + * but the active context is pullable on this + * slot, then we need to remove the active + * marker to prevent it from submitting atoms in + * the IRQ handler, which would prevent this + * context from making progress. */ + if (last_active && kctx != last_active && + kbase_js_ctx_pullable( + last_active, js, true)) + ctx_waiting = true; + + if (context_idle) { + kbase_jm_idle_ctx(kbdev, kctx); + spin_unlock_irqrestore( + &kbdev->hwaccess_lock, + flags); + WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); + kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); + kbase_pm_context_idle(kbdev); + } else { + spin_unlock_irqrestore( + &kbdev->hwaccess_lock, + flags); + } + mutex_unlock( + &kctx->jctx.sched_info.ctx.jsctx_mutex); + + js_mask &= ~(1 << js); + break; /* Could not run atoms on this slot */ + } + + /* Push to back of list */ + if (kbase_js_ctx_pullable(kctx, js, true)) + timer_sync |= + kbase_js_ctx_list_add_pullable_nolock( + kctx->kbdev, kctx, js); + else + timer_sync |= + kbase_js_ctx_list_add_unpullable_nolock( + kctx->kbdev, kctx, js); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + } + } + + if (timer_sync) + kbase_js_sync_timers(kbdev); + + if (kbdev->hwaccess.active_kctx == last_active && ctx_waiting) + kbdev->hwaccess.active_kctx = NULL; + + mutex_unlock(&js_devdata->queue_mutex); + up(&js_devdata->schedule_sem); +} + +void kbase_js_zap_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev = kctx->kbdev; + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; + int js; + + /* + * Critical assumption: No more submission is possible outside of the + * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs) + * whilst the struct kbase_context is terminating. + */ + + /* First, atomically do the following: + * - mark the context as dying + * - try to evict it from the queue */ + mutex_lock(&kctx->jctx.lock); + mutex_lock(&js_devdata->queue_mutex); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + kbase_ctx_flag_set(kctx, KCTX_DYING); + + dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %p", kctx); + + /* + * At this point we know: + * - If eviction succeeded, it was in the queue, but now no + * longer is + * - We must cancel the jobs here. No Power Manager active reference to + * release. + * - This happens asynchronously - kbase_jd_zap_context() will wait for + * those jobs to be killed. + * - If eviction failed, then it wasn't in the queue. It is one + * of the following: + * - a. it didn't have any jobs, and so is not in the Queue or + * the Run Pool (not scheduled) + * - Hence, no more work required to cancel jobs. No Power Manager + * active reference to release. + * - b. it was in the middle of a scheduling transaction (and thus must + * have at least 1 job). This can happen from a syscall or a + * kernel thread. We still hold the jsctx_mutex, and so the thread + * must be waiting inside kbasep_js_try_schedule_head_ctx(), + * before checking whether the runpool is full. That thread will + * continue after we drop the mutex, and will notice the context + * is dying. It will rollback the transaction, killing all jobs at + * the same time. kbase_jd_zap_context() will wait for those jobs + * to be killed. + * - Hence, no more work required to cancel jobs, or to release the + * Power Manager active reference. + * - c. it is scheduled, and may or may not be running jobs + * - We must cause it to leave the runpool by stopping it from + * submitting any more jobs. When it finally does leave, + * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs + * (because it is dying), release the Power Manager active reference, + * and will not requeue the context in the queue. + * kbase_jd_zap_context() will wait for those jobs to be killed. + * - Hence, work required just to make it leave the runpool. Cancelling + * jobs and releasing the Power manager active reference will be + * handled when it leaves the runpool. + */ + if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) { + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + if (!list_empty( + &kctx->jctx.sched_info.ctx.ctx_list_entry[js])) + list_del_init( + &kctx->jctx.sched_info.ctx.ctx_list_entry[js]); + } + + /* The following events require us to kill off remaining jobs + * and update PM book-keeping: + * - we evicted it correctly (it must have jobs to be in the + * Queue) + * + * These events need no action, but take this path anyway: + * - Case a: it didn't have any jobs, and was never in the Queue + * - Case b: scheduling transaction will be partially rolled- + * back (this already cancels the jobs) + */ + + KBASE_TRACE_ADD(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, + kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + dev_dbg(kbdev->dev, "Zap: Ctx %p scheduled=0", kctx); + + /* Only cancel jobs when we evicted from the + * queue. No Power Manager active reference was held. + * + * Having is_dying set ensures that this kills, and + * doesn't requeue */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, false); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + mutex_unlock(&kctx->jctx.lock); + } else { + unsigned long flags; + bool was_retained; + + /* Case c: didn't evict, but it is scheduled - it's in the Run + * Pool */ + KBASE_TRACE_ADD(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, + kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + dev_dbg(kbdev->dev, "Zap: Ctx %p is in RunPool", kctx); + + /* Disable the ctx from submitting any more jobs */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + /* Retain and (later) release the context whilst it is is now + * disallowed from submitting jobs - ensures that someone + * somewhere will be removing the context later on */ + was_retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + + /* Since it's scheduled and we have the jsctx_mutex, it must be + * retained successfully */ + KBASE_DEBUG_ASSERT(was_retained); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Kill Any Running jobs", kctx); + + /* Cancel any remaining running jobs for this kctx - if any. + * Submit is disallowed which takes effect immediately, so no + * more new jobs will appear after we do this. */ + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) + kbase_job_slot_hardstop(kctx, js, NULL); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + mutex_unlock(&js_devdata->queue_mutex); + mutex_unlock(&kctx->jctx.lock); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Release (may or may not schedule out immediately)", + kctx); + + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + + KBASE_TRACE_ADD(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u); + + /* After this, you must wait on both the + * kbase_jd_context::zero_jobs_wait and the + * kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the jobs + * to be destroyed, and the context to be de-scheduled (if it was on the + * runpool). + * + * kbase_jd_zap_context() will do this. */ +} + +static inline int trace_get_refcnt(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + return atomic_read(&kctx->refcount); +} + +/** + * kbase_js_foreach_ctx_job(): - Call a function on all jobs in context + * @kctx: Pointer to context. + * @callback: Pointer to function to call for each job. + * + * Call a function on all jobs belonging to a non-queued, non-running + * context, and detach the jobs from the context as it goes. + * + * Due to the locks that might be held at the time of the call, the callback + * may need to defer work on a workqueue to complete its actions (e.g. when + * cancelling jobs) + * + * Atoms will be removed from the queue, so this must only be called when + * cancelling jobs (which occurs as part of context destruction). + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + */ +static void kbase_js_foreach_ctx_job(struct kbase_context *kctx, + kbasep_js_ctx_job_cb callback) +{ + struct kbase_device *kbdev; + unsigned long flags; + u32 js; + + kbdev = kctx->kbdev; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_FOREACH_CTX_JOBS, kctx, NULL, + 0u, trace_get_refcnt(kbdev, kctx)); + + /* Invoke callback on jobs on each slot in turn */ + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) + jsctx_queue_foreach(kctx, js, callback); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.h b/drivers/gpu/arm/bifrost/mali_kbase_js.h new file mode 100644 index 000000000000..ddada8e468a1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.h @@ -0,0 +1,925 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler APIs. + */ + +#ifndef _KBASE_JS_H_ +#define _KBASE_JS_H_ + +#include "mali_kbase_js_defs.h" +#include "mali_kbase_context.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_debug.h" + +#include "mali_kbase_js_ctx_attr.h" + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js Job Scheduler Internal APIs + * @{ + * + * These APIs are Internal to KBase. + */ + +/** + * @brief Initialize the Job Scheduler + * + * The struct kbasep_js_device_data sub-structure of \a kbdev must be zero + * initialized before passing to the kbasep_js_devdata_init() function. This is + * to give efficient error path code. + */ +int kbasep_js_devdata_init(struct kbase_device * const kbdev); + +/** + * @brief Halt the Job Scheduler. + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + * + */ +void kbasep_js_devdata_halt(struct kbase_device *kbdev); + +/** + * @brief Terminate the Job Scheduler + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + */ +void kbasep_js_devdata_term(struct kbase_device *kbdev); + +/** + * @brief Initialize the Scheduling Component of a struct kbase_context on the Job Scheduler. + * + * This effectively registers a struct kbase_context with a Job Scheduler. + * + * It does not register any jobs owned by the struct kbase_context with the scheduler. + * Those must be separately registered by kbasep_js_add_job(). + * + * The struct kbase_context must be zero intitialized before passing to the + * kbase_js_init() function. This is to give efficient error path code. + */ +int kbasep_js_kctx_init(struct kbase_context * const kctx); + +/** + * @brief Terminate the Scheduling Component of a struct kbase_context on the Job Scheduler + * + * This effectively de-registers a struct kbase_context from its Job Scheduler + * + * It is safe to call this on a struct kbase_context that has never had or failed + * initialization of its jctx.sched_info member, to give efficient error-path + * code. + * + * For this to work, the struct kbase_context must be zero intitialized before passing + * to the kbase_js_init() function. + * + * It is a Programming Error to call this whilst there are still jobs + * registered with this context. + */ +void kbasep_js_kctx_term(struct kbase_context *kctx); + +/** + * @brief Add a job chain to the Job Scheduler, and take necessary actions to + * schedule the context/run the job. + * + * This atomically does the following: + * - Update the numbers of jobs information + * - Add the job to the run pool if necessary (part of init_job) + * + * Once this is done, then an appropriate action is taken: + * - If the ctx is scheduled, it attempts to start the next job (which might be + * this added job) + * - Otherwise, and if this is the first job on the context, it enqueues it on + * the Policy Queue + * + * The Policy's Queue can be updated by this in the following ways: + * - In the above case that this is the first job on the context + * - If the context is high priority and the context is not scheduled, then it + * could cause the Policy to schedule out a low-priority context, allowing + * this context to be scheduled in. + * + * If the context is already scheduled on the RunPool, then adding a job to it + * is guarenteed not to update the Policy Queue. And so, the caller is + * guarenteed to not need to try scheduling a context from the Run Pool - it + * can safely assert that the result is false. + * + * It is a programming error to have more than U32_MAX jobs in flight at a time. + * + * The following locking conditions are made on the caller: + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold hwaccess_lock (as this will be obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * + * @return true indicates that the Policy Queue was updated, and so the + * caller will need to try scheduling a context onto the Run Pool. + * @return false indicates that no updates were made to the Policy Queue, + * so no further action is required from the caller. This is \b always returned + * when the context is currently scheduled. + */ +bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Remove a job chain from the Job Scheduler, except for its 'retained state'. + * + * Completely removing a job requires several calls: + * - kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of + * the atom + * - kbasep_js_remove_job(), to partially remove the atom from the Job Scheduler + * - kbasep_js_runpool_release_ctx_and_katom_retained_state(), to release the + * remaining state held as part of the job having been run. + * + * In the common case of atoms completing normally, this set of actions is more optimal for spinlock purposes than having kbasep_js_remove_job() handle all of the actions. + * + * In the case of cancelling atoms, it is easier to call kbasep_js_remove_cancelled_job(), which handles all the necessary actions. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool + * + * Do not use this for removing jobs being killed by kbase_jd_cancel() - use + * kbasep_js_remove_cancelled_job() instead. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * + */ +void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Completely remove a job chain from the Job Scheduler, in the case + * where the job chain was cancelled. + * + * This is a variant of kbasep_js_remove_job() that takes care of removing all + * of the retained state too. This is generally useful for cancelled atoms, + * which need not be handled in an optimal way. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool: + * - it is not being killed with kbasep_jd_cancel() + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold the hwaccess_lock, (as this will be obtained + * internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this could be + * obtained internally) + * + * @return true indicates that ctx attributes have changed and the caller + * should call kbase_js_sched_all() to try to run more jobs + * @return false otherwise + */ +bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, + struct kbase_context *kctx, + struct kbase_jd_atom *katom); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold mmu_hw_mutex and hwaccess_lock, because they will be + * used internally. + * + * @return value != false if the retain succeeded, and the context will not be scheduled out. + * @return false if the retain failed (because the context is being/has been scheduled out). + */ +bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locks must be held by the caller: + * - mmu_hw_mutex, hwaccess_lock + * + * @return value != false if the retain succeeded, and the context will not be scheduled out. + * @return false if the retain failed (because the context is being/has been scheduled out). + */ +bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Lookup a context in the Run Pool based upon its current address space + * and ensure that is stays scheduled in. + * + * The context is refcounted as being busy to prevent it from scheduling + * out. It must be released with kbasep_js_runpool_release_ctx() when it is no + * longer required to stay scheduled in. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the hwaccess_lock, because it will be used internally. + * If the hwaccess_lock is already held, then the caller should use + * kbasep_js_runpool_lookup_ctx_nolock() instead. + * + * @return a valid struct kbase_context on success, which has been refcounted as being busy. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr); + +/** + * @brief Handling the requeuing/killing of a context that was evicted from the + * policy queue or runpool. + * + * This should be used whenever handing off a context that has been evicted + * from the policy queue or the runpool: + * - If the context is not dying and has jobs, it gets re-added to the policy + * queue + * - Otherwise, it is not added + * + * In addition, if the context is dying the jobs are killed asynchronously. + * + * In all cases, the Power Manager active reference is released + * (kbase_pm_context_idle()) whenever the has_pm_ref parameter is true. \a + * has_pm_ref must be set to false whenever the context was not previously in + * the runpool and does not hold a Power Manager active refcount. Note that + * contexts in a rollback of kbasep_js_try_schedule_head_ctx() might have an + * active refcount even though they weren't in the runpool. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + */ +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, bool has_pm_ref); + +/** + * @brief Release a refcount of a context being busy, allowing it to be + * scheduled out. + * + * When the refcount reaches zero and the context \em might be scheduled out + * (depending on whether the Scheudling Policy has deemed it so, or if it has run + * out of jobs). + * + * If the context does get scheduled out, then The following actions will be + * taken as part of deschduling a context: + * - For the context being descheduled: + * - If the context is in the processing of dying (all the jobs are being + * removed from it), then descheduling also kills off any jobs remaining in the + * context. + * - If the context is not dying, and any jobs remain after descheduling the + * context then it is re-enqueued to the Policy's Queue. + * - Otherwise, the context is still known to the scheduler, but remains absent + * from the Policy Queue until a job is next added to it. + * - In all descheduling cases, the Power Manager active reference (obtained + * during kbasep_js_try_schedule_head_ctx()) is released (kbase_pm_context_idle()). + * + * Whilst the context is being descheduled, this also handles actions that + * cause more atoms to be run: + * - Attempt submitting atoms when the Context Attributes on the Runpool have + * changed. This is because the context being scheduled out could mean that + * there are more opportunities to run atoms. + * - Attempt submitting to a slot that was previously blocked due to affinity + * restrictions. This is usually only necessary when releasing a context + * happens as part of completing a previous job, but is harmless nonetheless. + * - Attempt scheduling in a new context (if one is available), and if necessary, + * running a job from that new context. + * + * Unlike retaining a context in the runpool, this function \b cannot be called + * from IRQ context. + * + * It is a programming error to call this on a \a kctx that is not currently + * scheduled, or that already has a zero refcount. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the hwaccess_lock, because it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + * + */ +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Variant of kbasep_js_runpool_release_ctx() that handles additional + * actions from completing an atom. + * + * This is usually called as part of completing an atom and releasing the + * refcount on the context held by the atom. + * + * Therefore, the extra actions carried out are part of handling actions queued + * on a completed atom, namely: + * - Releasing the atom's context attributes + * - Retrying the submission on a particular slot, because we couldn't submit + * on that slot from an IRQ handler. + * + * The locking conditions of this function are the same as those for + * kbasep_js_runpool_release_ctx() + */ +void kbasep_js_runpool_release_ctx_and_katom_retained_state(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * @brief Variant of kbase_js_runpool_release_ctx() that assumes that + * kbasep_js_device_data::runpool_mutex and + * kbasep_js_kctx_info::ctx::jsctx_mutex are held by the caller, and does not + * attempt to schedule new contexts. + */ +void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, + struct kbase_context *kctx); + +/** + * @brief Schedule in a privileged context + * + * This schedules a context in regardless of the context priority. + * If the runpool is full, a context will be forced out of the runpool and the function will wait + * for the new context to be scheduled in. + * The context will be kept scheduled in (and the corresponding address space reserved) until + * kbasep_js_release_privileged_ctx is called). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the hwaccess_lock, because it will be used internally. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will + * be used internally. + * + */ +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Release a privileged context, allowing it to be scheduled out. + * + * See kbasep_js_runpool_release_ctx for potential side effects. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the hwaccess_lock, because it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be + * obtained internally) + * + */ +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Try to submit the next job on each slot + * + * The following locks may be used: + * - kbasep_js_device_data::runpool_mutex + * - hwaccess_lock + */ +void kbase_js_try_run_jobs(struct kbase_device *kbdev); + +/** + * @brief Suspend the job scheduler during a Power Management Suspend event. + * + * Causes all contexts to be removed from the runpool, and prevents any + * contexts from (re)entering the runpool. + * + * This does not handle suspending the one privileged context: the caller must + * instead do this by by suspending the GPU HW Counter Instrumentation. + * + * This will eventually cause all Power Management active references held by + * contexts on the runpool to be released, without running any more atoms. + * + * The caller must then wait for all Power Mangement active refcount to become + * zero before completing the suspend. + * + * The emptying mechanism may take some time to complete, since it can wait for + * jobs to complete naturally instead of forcing them to end quickly. However, + * this is bounded by the Job Scheduler's Job Timeouts. Hence, this + * function is guaranteed to complete in a finite time. + */ +void kbasep_js_suspend(struct kbase_device *kbdev); + +/** + * @brief Resume the Job Scheduler after a Power Management Resume event. + * + * This restores the actions from kbasep_js_suspend(): + * - Schedules contexts back into the runpool + * - Resumes running atoms on the GPU + */ +void kbasep_js_resume(struct kbase_device *kbdev); + +/** + * @brief Submit an atom to the job scheduler. + * + * The atom is enqueued on the context's ringbuffer. The caller must have + * ensured that all dependencies can be represented in the ringbuffer. + * + * Caller must hold jctx->lock + * + * @param[in] kctx Context pointer + * @param[in] atom Pointer to the atom to submit + * + * @return Whether the context requires to be enqueued. */ +bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, + struct kbase_jd_atom *katom); + +/** + * jsctx_ll_flush_to_rb() - Pushes atoms from the linked list to ringbuffer. + * @kctx: Context Pointer + * @prio: Priority (specifies the queue together with js). + * @js: Job slot (specifies the queue together with prio). + * + * Pushes all possible atoms from the linked list to the ringbuffer. + * Number of atoms are limited to free space in the ringbuffer and + * number of available atoms in the linked list. + * + */ +void jsctx_ll_flush_to_rb(struct kbase_context *kctx, int prio, int js); +/** + * @brief Pull an atom from a context in the job scheduler for execution. + * + * The atom will not be removed from the ringbuffer at this stage. + * + * The HW access lock must be held when calling this function. + * + * @param[in] kctx Context to pull from + * @param[in] js Job slot to pull from + * @return Pointer to an atom, or NULL if there are no atoms for this + * slot that can be currently run. + */ +struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js); + +/** + * @brief Return an atom to the job scheduler ringbuffer. + * + * An atom is 'unpulled' if execution is stopped but intended to be returned to + * later. The most common reason for this is that the atom has been + * soft-stopped. + * + * Note that if multiple atoms are to be 'unpulled', they must be returned in + * the reverse order to which they were originally pulled. It is a programming + * error to return atoms in any other order. + * + * The HW access lock must be held when calling this function. + * + * @param[in] kctx Context pointer + * @param[in] atom Pointer to the atom to unpull + */ +void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Complete an atom from jd_done_worker(), removing it from the job + * scheduler ringbuffer. + * + * If the atom failed then all dependee atoms marked for failure propagation + * will also fail. + * + * @param[in] kctx Context pointer + * @param[in] katom Pointer to the atom to complete + * @return true if the context is now idle (no jobs pulled) + * false otherwise + */ +bool kbase_js_complete_atom_wq(struct kbase_context *kctx, + struct kbase_jd_atom *katom); + +/** + * @brief Complete an atom. + * + * Most of the work required to complete an atom will be performed by + * jd_done_worker(). + * + * The HW access lock must be held when calling this function. + * + * @param[in] katom Pointer to the atom to complete + * @param[in] end_timestamp The time that the atom completed (may be NULL) + * + * Return: Atom that has now been unblocked and can now be run, or NULL if none + */ +struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, + ktime_t *end_timestamp); + +/** + * @brief Submit atoms from all available contexts. + * + * This will attempt to submit as many jobs as possible to the provided job + * slots. It will exit when either all job slots are full, or all contexts have + * been used. + * + * @param[in] kbdev Device pointer + * @param[in] js_mask Mask of job slots to submit to + */ +void kbase_js_sched(struct kbase_device *kbdev, int js_mask); + +/** + * kbase_jd_zap_context - Attempt to deschedule a context that is being + * destroyed + * @kctx: Context pointer + * + * This will attempt to remove a context from any internal job scheduler queues + * and perform any other actions to ensure a context will not be submitted + * from. + * + * If the context is currently scheduled, then the caller must wait for all + * pending jobs to complete before taking any further action. + */ +void kbase_js_zap_context(struct kbase_context *kctx); + +/** + * @brief Validate an atom + * + * This will determine whether the atom can be scheduled onto the GPU. Atoms + * with invalid combinations of core requirements will be rejected. + * + * @param[in] kbdev Device pointer + * @param[in] katom Atom to validate + * @return true if atom is valid + * false otherwise + */ +bool kbase_js_is_atom_valid(struct kbase_device *kbdev, + struct kbase_jd_atom *katom); + +/** + * kbase_js_set_timeouts - update all JS timeouts with user specified data + * @kbdev: Device pointer + * + * Timeouts are specified through the 'js_timeouts' sysfs file. If a timeout is + * set to a positive number then that becomes the new value used, if a timeout + * is negative then the default is set. + */ +void kbase_js_set_timeouts(struct kbase_device *kbdev); + +/* + * Helpers follow + */ + +/** + * @brief Check that a context is allowed to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * As with any bool, never test the return value with true. + * + * The caller must hold hwaccess_lock. + */ +static inline bool kbasep_js_is_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 test_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + test_bit = (u16) (1u << kctx->as_nr); + + return (bool) (js_devdata->runpool_irq.submit_allowed & test_bit); +} + +/** + * @brief Allow a context to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold hwaccess_lock. + */ +static inline void kbasep_js_set_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 set_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + set_bit = (u16) (1u << kctx->as_nr); + + dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed |= set_bit; +} + +/** + * @brief Prevent a context from submitting more jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold hwaccess_lock. + */ +static inline void kbasep_js_clear_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 clear_bit; + u16 clear_mask; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + clear_bit = (u16) (1u << kctx->as_nr); + clear_mask = ~clear_bit; + + dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed &= clear_mask; +} + +/** + * @brief Manage the 'retry_submit_on_slot' part of a kbase_jd_atom + */ +static inline void kbasep_js_clear_job_retry_submit(struct kbase_jd_atom *atom) +{ + atom->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Mark a slot as requiring resubmission by carrying that information on a + * completing atom. + * + * @note This can ASSERT in debug builds if the submit slot has been set to + * something other than the current value for @a js. This is because you might + * be unintentionally stopping more jobs being submitted on the old submit + * slot, and that might cause a scheduling-hang. + * + * @note If you can guarantee that the atoms for the original slot will be + * submitted on some other slot, then call kbasep_js_clear_job_retry_submit() + * first to silence the ASSERT. + */ +static inline void kbasep_js_set_job_retry_submit_slot(struct kbase_jd_atom *atom, int js) +{ + KBASE_DEBUG_ASSERT(0 <= js && js <= BASE_JM_MAX_NR_SLOTS); + KBASE_DEBUG_ASSERT((atom->retry_submit_on_slot == + KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID) + || (atom->retry_submit_on_slot == js)); + + atom->retry_submit_on_slot = js; +} + +/** + * Create an initial 'invalid' atom retained state, that requires no + * atom-related work to be done on releasing with + * kbasep_js_runpool_release_ctx_and_katom_retained_state() + */ +static inline void kbasep_js_atom_retained_state_init_invalid(struct kbasep_js_atom_retained_state *retained_state) +{ + retained_state->event_code = BASE_JD_EVENT_NOT_STARTED; + retained_state->core_req = KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID; + retained_state->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Copy atom state that can be made available after jd_done_nolock() is called + * on that atom. + */ +static inline void kbasep_js_atom_retained_state_copy(struct kbasep_js_atom_retained_state *retained_state, const struct kbase_jd_atom *katom) +{ + retained_state->event_code = katom->event_code; + retained_state->core_req = katom->core_req; + retained_state->retry_submit_on_slot = katom->retry_submit_on_slot; + retained_state->sched_priority = katom->sched_priority; + retained_state->device_nr = katom->device_nr; +} + +/** + * @brief Determine whether an atom has finished (given its retained state), + * and so should be given back to userspace/removed from the system. + * + * Reasons for an atom not finishing include: + * - Being soft-stopped (and so, the atom should be resubmitted sometime later) + * + * @param[in] katom_retained_state the retained state of the atom to check + * @return false if the atom has not finished + * @return !=false if the atom has finished + */ +static inline bool kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (bool) (katom_retained_state->event_code != BASE_JD_EVENT_STOPPED && katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT); +} + +/** + * @brief Determine whether a struct kbasep_js_atom_retained_state is valid + * + * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates that the + * code should just ignore it. + * + * @param[in] katom_retained_state the atom's retained state to check + * @return false if the retained state is invalid, and can be ignored + * @return !=false if the retained state is valid + */ +static inline bool kbasep_js_atom_retained_state_is_valid(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (bool) (katom_retained_state->core_req != KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID); +} + +static inline bool kbasep_js_get_atom_retry_submit_slot(const struct kbasep_js_atom_retained_state *katom_retained_state, int *res) +{ + int js = katom_retained_state->retry_submit_on_slot; + + *res = js; + return (bool) (js >= 0); +} + +/** + * @brief Variant of kbasep_js_runpool_lookup_ctx() that can be used when the + * context is guaranteed to be already previously retained. + * + * It is a programming error to supply the \a as_nr of a context that has not + * been previously retained/has a busy refcount of zero. The only exception is + * when there is no ctx in \a as_nr (NULL returned). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the hwaccess_lock, because it will be used internally. + * + * @return a valid struct kbase_context on success, with a refcount that is guaranteed + * to be non-zero and unmodified by this function. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +static inline struct kbase_context *kbasep_js_runpool_lookup_ctx_noretain(struct kbase_device *kbdev, int as_nr) +{ + struct kbase_context *found_kctx; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + + found_kctx = kbdev->as_to_kctx[as_nr]; + KBASE_DEBUG_ASSERT(found_kctx == NULL || + atomic_read(&found_kctx->refcount) > 0); + + return found_kctx; +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +static inline void kbase_js_runpool_inc_context_count( + struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* Track total contexts */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running < S8_MAX); + ++(js_devdata->nr_all_contexts_running); + + if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { + /* Track contexts that can submit jobs */ + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running < + S8_MAX); + ++(js_devdata->nr_user_contexts_running); + } +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +static inline void kbase_js_runpool_dec_context_count( + struct kbase_device *kbdev, + struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* Track total contexts */ + --(js_devdata->nr_all_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running >= 0); + + if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { + /* Track contexts that can submit jobs */ + --(js_devdata->nr_user_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running >= 0); + } +} + + +/** + * @brief Submit atoms from all available contexts to all job slots. + * + * This will attempt to submit as many jobs as possible. It will exit when + * either all job slots are full, or all contexts have been used. + * + * @param[in] kbdev Device pointer + */ +static inline void kbase_js_sched_all(struct kbase_device *kbdev) +{ + kbase_js_sched(kbdev, (1 << kbdev->gpu_props.num_job_slots) - 1); +} + +extern const int +kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS]; + +extern const base_jd_prio +kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; + +/** + * kbasep_js_atom_prio_to_sched_prio(): - Convert atom priority (base_jd_prio) + * to relative ordering + * @atom_prio: Priority ID to translate. + * + * Atom priority values for @ref base_jd_prio cannot be compared directly to + * find out which are higher or lower. + * + * This function will convert base_jd_prio values for successively lower + * priorities into a monotonically increasing sequence. That is, the lower the + * base_jd_prio priority, the higher the value produced by this function. This + * is in accordance with how the rest of the kernel treates priority. + * + * The mapping is 1:1 and the size of the valid input range is the same as the + * size of the valid output range, i.e. + * KBASE_JS_ATOM_SCHED_PRIO_COUNT == BASE_JD_NR_PRIO_LEVELS + * + * Note This must be kept in sync with BASE_JD_PRIO_<...> definitions + * + * Return: On success: a value in the inclusive range + * 0..KBASE_JS_ATOM_SCHED_PRIO_COUNT-1. On failure: + * KBASE_JS_ATOM_SCHED_PRIO_INVALID + */ +static inline int kbasep_js_atom_prio_to_sched_prio(base_jd_prio atom_prio) +{ + if (atom_prio >= BASE_JD_NR_PRIO_LEVELS) + return KBASE_JS_ATOM_SCHED_PRIO_INVALID; + + return kbasep_js_atom_priority_to_relative[atom_prio]; +} + +static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(int sched_prio) +{ + unsigned int prio_idx; + + KBASE_DEBUG_ASSERT(0 <= sched_prio + && sched_prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT); + + prio_idx = (unsigned int)sched_prio; + + return kbasep_js_relative_priority_to_atom[prio_idx]; +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.c b/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.c new file mode 100644 index 000000000000..321506ada835 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.c @@ -0,0 +1,301 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#include +#include + +/* + * Private functions follow + */ + +/** + * @brief Check whether a ctx has a certain attribute, and if so, retain that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return true indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return false indicates no change in ctx attributes state of the runpool. + */ +static bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + bool runpool_state_changed = false; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] < S8_MAX); + ++(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 1) { + /* First refcount indicates a state change */ + runpool_state_changed = true; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Check whether a ctx has a certain attribute, and if so, release that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return true indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return false indicates no change in ctx attributes state of the runpool. + */ +static bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + bool runpool_state_changed = false; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] > 0); + --(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 0) { + /* Last de-refcount indicates a state change */ + runpool_state_changed = true; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Retain a certain attribute on a ctx, also retaining it on the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return true indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return false indicates no change in ctx attributes state of the runpool. + */ +static bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + bool runpool_state_changed = false; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&kbdev->hwaccess_lock); + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] < U32_MAX); + + ++(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + /* Only ref-count the attribute on the runpool for the first time this contexts sees this attribute */ + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_CTX, kctx, NULL, 0u, attribute); + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, attribute); + } + + return runpool_state_changed; +} + +/* + * @brief Release a certain attribute on a ctx, also releasing it from the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return true indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return false indicates no change in ctx attributes state of the runpool. + */ +static bool kbasep_js_ctx_attr_ctx_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + bool runpool_state_changed = false; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] > 0); + + if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + lockdep_assert_held(&kbdev->hwaccess_lock); + /* Only de-ref-count the attribute on the runpool when this is the last ctx-reference to it */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, attribute); + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_CTX, kctx, NULL, 0u, attribute); + } + + /* De-ref must happen afterwards, because kbasep_js_ctx_attr_runpool_release() needs to check it too */ + --(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + return runpool_state_changed; +} + +/* + * More commonly used public functions + */ + +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + bool runpool_state_changed = false; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + if (kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { + /* This context never submits, so don't track any scheduling attributes */ + return; + } + + /* Transfer attributes held in the context flags for contexts that have submit enabled */ + + /* ... More attributes can be added here ... */ + + /* The context should not have been scheduled yet, so ASSERT if this caused + * runpool state changes (note that other threads *can't* affect the value + * of runpool_state_changed, due to how it's calculated) */ + KBASE_DEBUG_ASSERT(runpool_state_changed == false); + CSTD_UNUSED(runpool_state_changed); +} + +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + bool runpool_state_changed; + int i; + + /* Retain any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != false) { + /* The context is being scheduled in, so update the runpool with the new attributes */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + + /* We don't need to know about state changed, because retaining a + * context occurs on scheduling it, and that itself will also try + * to run new atoms */ + CSTD_UNUSED(runpool_state_changed); + } + } +} + +bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + bool runpool_state_changed = false; + int i; + + /* Release any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != false) { + /* The context is being scheduled out, so update the runpool on the removed attributes */ + runpool_state_changed |= kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + } + } + + return runpool_state_changed; +} + +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + bool runpool_state_changed = false; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom); + core_req = katom->core_req; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + else + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + /* We don't need to know about state changed, because retaining an + * atom occurs on adding it, and that itself will also try to run + * new atoms */ + CSTD_UNUSED(runpool_state_changed); +} + +bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + bool runpool_state_changed = false; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom_retained_state); + core_req = katom_retained_state->core_req; + + /* No-op for invalid atoms */ + if (kbasep_js_atom_retained_state_is_valid(katom_retained_state) == false) + return false; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + else + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + return runpool_state_changed; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.h b/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.h new file mode 100644 index 000000000000..ce9183326a57 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_js_ctx_attr.h @@ -0,0 +1,158 @@ +/* + * + * (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_ctx_attr.h + * Job Scheduler Context Attribute APIs + */ + +#ifndef _KBASE_JS_CTX_ATTR_H_ +#define _KBASE_JS_CTX_ATTR_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ + +/** + * Set the initial attributes of a context (when context create flags are set) + * + * Requires: + * - Hold the jsctx_mutex + */ +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of a context + * + * This occurs on scheduling in the context on the runpool (but after + * is_scheduled is set) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + */ +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Release all attributes of a context + * + * This occurs on scheduling out the context from the runpool (but before + * is_scheduled is cleared) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + * + * @return true indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return false indicates no change in ctx attributes state of the runpool. + */ +bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of an atom + * + * This occurs on adding an atom to a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + */ +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * Release all attributes of an atom, given its retained state. + * + * This occurs after (permanently) removing an atom from a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * This is a no-op when \a katom_retained_state is invalid. + * + * @return true indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return false indicates no change in ctx attributes state of the runpool. + */ +bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * Requires: + * - runpool_irq spinlock + */ +static inline s8 kbasep_js_ctx_attr_count_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + + return js_devdata->runpool_irq.ctx_attr_ref_count[attribute]; +} + +/** + * Requires: + * - runpool_irq spinlock + */ +static inline bool kbasep_js_ctx_attr_is_attr_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + /* In general, attributes are 'on' when they have a non-zero refcount (note: the refcount will never be < 0) */ + return (bool) kbasep_js_ctx_attr_count_on_runpool(kbdev, attribute); +} + +/** + * Requires: + * - jsctx mutex + */ +static inline bool kbasep_js_ctx_attr_is_attr_on_ctx(struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + /* In general, attributes are 'on' when they have a refcount (which should never be < 0) */ + return (bool) (js_kctx_info->ctx.ctx_attr_ref_count[attribute]); +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h new file mode 100644 index 000000000000..ba8b6441549b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h @@ -0,0 +1,386 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler Type Definitions + */ + +#ifndef _KBASE_JS_DEFS_H_ +#define _KBASE_JS_DEFS_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ +/* Forward decls */ +struct kbase_device; +struct kbase_jd_atom; + + +typedef u32 kbase_context_flags; + +struct kbasep_atom_req { + base_jd_core_req core_req; + kbase_context_flags ctx_req; + u32 device_nr; +}; + +/** Callback function run on all of a context's jobs registered with the Job + * Scheduler */ +typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +/** + * @brief Maximum number of jobs that can be submitted to a job slot whilst + * inside the IRQ handler. + * + * This is important because GPU NULL jobs can complete whilst the IRQ handler + * is running. Otherwise, it potentially allows an unlimited number of GPU NULL + * jobs to be submitted inside the IRQ handler, which increases IRQ latency. + */ +#define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2 + +/** + * @brief Context attributes + * + * Each context attribute can be thought of as a boolean value that caches some + * state information about either the runpool, or the context: + * - In the case of the runpool, it is a cache of "Do any contexts owned by + * the runpool have attribute X?" + * - In the case of a context, it is a cache of "Do any atoms owned by the + * context have attribute X?" + * + * The boolean value of the context attributes often affect scheduling + * decisions, such as affinities to use and job slots to use. + * + * To accomodate changes of state in the context, each attribute is refcounted + * in the context, and in the runpool for all running contexts. Specifically: + * - The runpool holds a refcount of how many contexts in the runpool have this + * attribute. + * - The context holds a refcount of how many atoms have this attribute. + */ +enum kbasep_js_ctx_attr { + /** Attribute indicating a context that contains Compute jobs. That is, + * the context has jobs of type @ref BASE_JD_REQ_ONLY_COMPUTE + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_COMPUTE, + + /** Attribute indicating a context that contains Non-Compute jobs. That is, + * the context has some jobs that are \b not of type @ref + * BASE_JD_REQ_ONLY_COMPUTE. + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_NON_COMPUTE, + + /** Attribute indicating that a context contains compute-job atoms that + * aren't restricted to a coherent group, and can run on all cores. + * + * Specifically, this is when the atom's \a core_req satisfy: + * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2 + * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups + * + * Such atoms could be blocked from running if one of the coherent groups + * is being used by another job slot, so tracking this context attribute + * allows us to prevent such situations. + * + * @note This doesn't take into account the 1-coregroup case, where all + * compute atoms would effectively be able to run on 'all cores', but + * contexts will still not always get marked with this attribute. Instead, + * it is the caller's responsibility to take into account the number of + * coregroups when interpreting this attribute. + * + * @note Whilst Tiler atoms are normally combined with + * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without + * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy + * enough to handle anyway. + */ + KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, + + /** Must be the last in the enum */ + KBASEP_JS_CTX_ATTR_COUNT +}; + +enum { + /** Bit indicating that new atom should be started because this atom completed */ + KBASE_JS_ATOM_DONE_START_NEW_ATOMS = (1u << 0), + /** Bit indicating that the atom was evicted from the JS_NEXT registers */ + KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT = (1u << 1) +}; + +/** Combination of KBASE_JS_ATOM_DONE_<...> bits */ +typedef u32 kbasep_js_atom_done_code; + +/** + * @brief KBase Device Data Job Scheduler sub-structure + * + * This encapsulates the current context of the Job Scheduler on a particular + * device. This context is global to the device, and is not tied to any + * particular struct kbase_context running on the device. + * + * nr_contexts_running and as_free are optimized for packing together (by making + * them smaller types than u32). The operations on them should rarely involve + * masking. The use of signed types for arithmetic indicates to the compiler that + * the value will not rollover (which would be undefined behavior), and so under + * the Total License model, it is free to make optimizations based on that (i.e. + * to remove masking). + */ +struct kbasep_js_device_data { + /* Sub-structure to collect together Job Scheduling data used in IRQ + * context. The hwaccess_lock must be held when accessing. */ + struct runpool_irq { + /** Bitvector indicating whether a currently scheduled context is allowed to submit jobs. + * When bit 'N' is set in this, it indicates whether the context bound to address space + * 'N' is allowed to submit jobs. + */ + u16 submit_allowed; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of contexts + * that can fit into the runpool. This is currently BASE_MAX_NR_AS + * + * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store + * the refcount. Hence, it's not worthwhile reducing this to + * bit-manipulation on u32s to save space (where in contrast, 4 bit + * sub-fields would be easy to do and would save space). + * + * Whilst this must not become negative, the sign bit is used for: + * - error detection in debug builds + * - Optimization: it is undefined for a signed int to overflow, and so + * the compiler can optimize for that never happening (thus, no masking + * is required on updating the variable) */ + s8 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + /* + * Affinity management and tracking + */ + /** Bitvector to aid affinity checking. Element 'n' bit 'i' indicates + * that slot 'n' is using core i (i.e. slot_affinity_refcount[n][i] > 0) */ + u64 slot_affinities[BASE_JM_MAX_NR_SLOTS]; + /** Refcount for each core owned by each slot. Used to generate the + * slot_affinities array of bitvectors + * + * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS, + * because it is refcounted only when a job is definitely about to be + * submitted to a slot, and is de-refcounted immediately after a job + * finishes */ + s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64]; + } runpool_irq; + + /** + * Run Pool mutex, for managing contexts within the runpool. + * Unless otherwise specified, you must hold this lock whilst accessing any + * members that follow + * + * In addition, this is used to access: + * - the kbasep_js_kctx_info::runpool substructure + */ + struct mutex runpool_mutex; + + /** + * Queue Lock, used to access the Policy's queue of contexts independently + * of the Run Pool. + * + * Of course, you don't need the Run Pool lock to access this. + */ + struct mutex queue_mutex; + + /** + * Scheduling semaphore. This must be held when calling + * kbase_jm_kick() + */ + struct semaphore schedule_sem; + + /** + * List of contexts that can currently be pulled from + */ + struct list_head ctx_list_pullable[BASE_JM_MAX_NR_SLOTS]; + /** + * List of contexts that can not currently be pulled from, but have + * jobs currently running. + */ + struct list_head ctx_list_unpullable[BASE_JM_MAX_NR_SLOTS]; + + /** Number of currently scheduled user contexts (excluding ones that are not submitting jobs) */ + s8 nr_user_contexts_running; + /** Number of currently scheduled contexts (including ones that are not submitting jobs) */ + s8 nr_all_contexts_running; + + /** Core Requirements to match up with base_js_atom's core_req memeber + * @note This is a write-once member, and so no locking is required to read */ + base_jd_core_req js_reqs[BASE_JM_MAX_NR_SLOTS]; + + u32 scheduling_period_ns; /*< Value for JS_SCHEDULING_PERIOD_NS */ + u32 soft_stop_ticks; /*< Value for JS_SOFT_STOP_TICKS */ + u32 soft_stop_ticks_cl; /*< Value for JS_SOFT_STOP_TICKS_CL */ + u32 hard_stop_ticks_ss; /*< Value for JS_HARD_STOP_TICKS_SS */ + u32 hard_stop_ticks_cl; /*< Value for JS_HARD_STOP_TICKS_CL */ + u32 hard_stop_ticks_dumping; /*< Value for JS_HARD_STOP_TICKS_DUMPING */ + u32 gpu_reset_ticks_ss; /*< Value for JS_RESET_TICKS_SS */ + u32 gpu_reset_ticks_cl; /*< Value for JS_RESET_TICKS_CL */ + u32 gpu_reset_ticks_dumping; /*< Value for JS_RESET_TICKS_DUMPING */ + u32 ctx_timeslice_ns; /**< Value for JS_CTX_TIMESLICE_NS */ + + /**< Value for JS_SOFT_JOB_TIMEOUT */ + atomic_t soft_job_timeout_ms; + + /** List of suspended soft jobs */ + struct list_head suspended_soft_jobs_list; + +#ifdef CONFIG_MALI_DEBUG + /* Support soft-stop on a single context */ + bool softstop_always; +#endif /* CONFIG_MALI_DEBUG */ + + /** The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths). + * @note This is a write-once member, and so no locking is required to read */ + int init_status; + + /* Number of contexts that can currently be pulled from */ + u32 nr_contexts_pullable; + + /* Number of contexts that can either be pulled from or are currently + * running */ + atomic_t nr_contexts_runnable; +}; + +/** + * @brief KBase Context Job Scheduling information structure + * + * This is a substructure in the struct kbase_context that encapsulates all the + * scheduling information. + */ +struct kbasep_js_kctx_info { + + /** + * Job Scheduler Context information sub-structure. These members are + * accessed regardless of whether the context is: + * - In the Policy's Run Pool + * - In the Policy's Queue + * - Not queued nor in the Run Pool. + * + * You must obtain the jsctx_mutex before accessing any other members of + * this substructure. + * + * You may not access any of these members from IRQ context. + */ + struct kbase_jsctx { + struct mutex jsctx_mutex; /**< Job Scheduler Context lock */ + + /** Number of jobs ready to run - does \em not include the jobs waiting in + * the dispatcher, and dependency-only jobs. See kbase_jd_context::job_nr + * for such jobs*/ + u32 nr_jobs; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of atoms on + * the context. **/ + u32 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + /** + * Wait queue to wait for KCTX_SHEDULED flag state changes. + * */ + wait_queue_head_t is_scheduled_wait; + + /** Link implementing JS queues. Context can be present on one + * list per job slot + */ + struct list_head ctx_list_entry[BASE_JM_MAX_NR_SLOTS]; + } ctx; + + /* The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths) */ + int init_status; +}; + +/** Subset of atom state that can be available after jd_done_nolock() is called + * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(), + * because the original atom could disappear. */ +struct kbasep_js_atom_retained_state { + /** Event code - to determine whether the atom has finished */ + enum base_jd_event_code event_code; + /** core requirements */ + base_jd_core_req core_req; + /* priority */ + int sched_priority; + /** Job Slot to retry submitting to if submission from IRQ handler failed */ + int retry_submit_on_slot; + /* Core group atom was executed on */ + u32 device_nr; + +}; + +/** + * Value signifying 'no retry on a slot required' for: + * - kbase_js_atom_retained_state::retry_submit_on_slot + * - kbase_jd_atom::retry_submit_on_slot + */ +#define KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID (-1) + +/** + * base_jd_core_req value signifying 'invalid' for a kbase_jd_atom_retained_state. + * + * @see kbase_atom_retained_state_is_valid() + */ +#define KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID BASE_JD_REQ_DEP + +/** + * @brief The JS timer resolution, in microseconds + * + * Any non-zero difference in time will be at least this size. + */ +#define KBASEP_JS_TICK_RESOLUTION_US 1 + +/* + * Internal atom priority defines for kbase_jd_atom::sched_prio + */ +enum { + KBASE_JS_ATOM_SCHED_PRIO_HIGH = 0, + KBASE_JS_ATOM_SCHED_PRIO_MED, + KBASE_JS_ATOM_SCHED_PRIO_LOW, + KBASE_JS_ATOM_SCHED_PRIO_COUNT, +}; + +/* Invalid priority for kbase_jd_atom::sched_prio */ +#define KBASE_JS_ATOM_SCHED_PRIO_INVALID -1 + +/* Default priority in the case of contexts with no atoms, or being lenient + * about invalid priorities from userspace */ +#define KBASE_JS_ATOM_SCHED_PRIO_DEFAULT KBASE_JS_ATOM_SCHED_PRIO_MED + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_linux.h b/drivers/gpu/arm/bifrost/mali_kbase_linux.h new file mode 100644 index 000000000000..6d1e61fd41e0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_linux.h @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_linux.h + * Base kernel APIs, Linux implementation. + */ + +#ifndef _KBASE_LINUX_H_ +#define _KBASE_LINUX_H_ + +/* All things that are needed for the Linux port. */ +#include +#include +#include +#include +#include + +#if (defined(MALI_KERNEL_TEST_API) && (1 == MALI_KERNEL_TEST_API)) + #define KBASE_EXPORT_TEST_API(func) EXPORT_SYMBOL(func) +#else + #define KBASE_EXPORT_TEST_API(func) +#endif + +#define KBASE_EXPORT_SYMBOL(func) EXPORT_SYMBOL(func) + +#endif /* _KBASE_LINUX_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.c b/drivers/gpu/arm/bifrost/mali_kbase_mem.c new file mode 100644 index 000000000000..34222cbddc78 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.c @@ -0,0 +1,2871 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* CONFIG_DMA_SHARED_BUFFER */ +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* This function finds out which RB tree the given GPU VA region belongs to + * based on the region zone */ +static struct rb_root *kbase_reg_flags_to_rbtree(struct kbase_context *kctx, + struct kbase_va_region *reg) +{ + struct rb_root *rbtree = NULL; + + switch (reg->flags & KBASE_REG_ZONE_MASK) { + case KBASE_REG_ZONE_CUSTOM_VA: + rbtree = &kctx->reg_rbtree_custom; + break; + case KBASE_REG_ZONE_EXEC: + rbtree = &kctx->reg_rbtree_exec; + break; + case KBASE_REG_ZONE_SAME_VA: + rbtree = &kctx->reg_rbtree_same; + /* fall through */ + default: + rbtree = &kctx->reg_rbtree_same; + break; + } + + return rbtree; +} + +/* This function finds out which RB tree the given pfn from the GPU VA belongs + * to based on the memory zone the pfn refers to */ +static struct rb_root *kbase_gpu_va_to_rbtree(struct kbase_context *kctx, + u64 gpu_pfn) +{ + struct rb_root *rbtree = NULL; + +#ifdef CONFIG_64BIT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) { +#endif /* CONFIG_64BIT */ + if (gpu_pfn >= KBASE_REG_ZONE_CUSTOM_VA_BASE) + rbtree = &kctx->reg_rbtree_custom; + else if (gpu_pfn >= KBASE_REG_ZONE_EXEC_BASE) + rbtree = &kctx->reg_rbtree_exec; + else + rbtree = &kctx->reg_rbtree_same; +#ifdef CONFIG_64BIT + } else { + if (gpu_pfn >= kctx->same_va_end) + rbtree = &kctx->reg_rbtree_custom; + else + rbtree = &kctx->reg_rbtree_same; + } +#endif /* CONFIG_64BIT */ + + return rbtree; +} + +/* This function inserts a region into the tree. */ +static void kbase_region_tracker_insert(struct kbase_context *kctx, + struct kbase_va_region *new_reg) +{ + u64 start_pfn = new_reg->start_pfn; + struct rb_node **link = NULL; + struct rb_node *parent = NULL; + struct rb_root *rbtree = NULL; + + rbtree = kbase_reg_flags_to_rbtree(kctx, new_reg); + + link = &(rbtree->rb_node); + /* Find the right place in the tree using tree search */ + while (*link) { + struct kbase_va_region *old_reg; + + parent = *link; + old_reg = rb_entry(parent, struct kbase_va_region, rblink); + + /* RBTree requires no duplicate entries. */ + KBASE_DEBUG_ASSERT(old_reg->start_pfn != start_pfn); + + if (old_reg->start_pfn > start_pfn) + link = &(*link)->rb_left; + else + link = &(*link)->rb_right; + } + + /* Put the new node there, and rebalance tree */ + rb_link_node(&(new_reg->rblink), parent, link); + + rb_insert_color(&(new_reg->rblink), rbtree); +} + +/* Find allocated region enclosing free range. */ +static struct kbase_va_region *kbase_region_tracker_find_region_enclosing_range_free( + struct kbase_context *kctx, u64 start_pfn, size_t nr_pages) +{ + struct rb_node *rbnode = NULL; + struct kbase_va_region *reg = NULL; + struct rb_root *rbtree = NULL; + + u64 end_pfn = start_pfn + nr_pages; + + rbtree = kbase_gpu_va_to_rbtree(kctx, start_pfn); + + rbnode = rbtree->rb_node; + + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (start_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (end_pfn > tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +/* Find region enclosing given address. */ +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, u64 gpu_addr) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + struct rb_root *rbtree = NULL; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbtree = kbase_gpu_va_to_rbtree(kctx, gpu_pfn); + + rbnode = rbtree->rb_node; + + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (gpu_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (gpu_pfn >= tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_enclosing_address); + +/* Find region with given base address */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, u64 gpu_addr) +{ + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + struct rb_node *rbnode = NULL; + struct kbase_va_region *reg = NULL; + struct rb_root *rbtree = NULL; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbtree = kbase_gpu_va_to_rbtree(kctx, gpu_pfn); + + rbnode = rbtree->rb_node; + + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if (reg->start_pfn > gpu_pfn) + rbnode = rbnode->rb_left; + else if (reg->start_pfn < gpu_pfn) + rbnode = rbnode->rb_right; + else + return reg; + + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_base_address); + +/* Find region meeting given requirements */ +static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(struct kbase_context *kctx, struct kbase_va_region *reg_reqs, size_t nr_pages, size_t align) +{ + struct rb_node *rbnode = NULL; + struct kbase_va_region *reg = NULL; + struct rb_root *rbtree = NULL; + + /* Note that this search is a linear search, as we do not have a target + address in mind, so does not benefit from the rbtree search */ + + rbtree = kbase_reg_flags_to_rbtree(kctx, reg_reqs); + + rbnode = rb_first(rbtree); + + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if ((reg->nr_pages >= nr_pages) && + (reg->flags & KBASE_REG_FREE)) { + /* Check alignment */ + u64 start_pfn = (reg->start_pfn + align - 1) & ~(align - 1); + + if ((start_pfn >= reg->start_pfn) && + (start_pfn <= (reg->start_pfn + reg->nr_pages - 1)) && + ((start_pfn + nr_pages - 1) <= (reg->start_pfn + reg->nr_pages - 1))) + return reg; + } + rbnode = rb_next(rbnode); + } + + return NULL; +} + +/** + * @brief Remove a region object from the global list. + * + * The region reg is removed, possibly by merging with other free and + * compatible adjacent regions. It must be called with the context + * region lock held. The associated memory is not released (see + * kbase_free_alloced_region). Internal use only. + */ +static int kbase_remove_va_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + struct rb_node *rbprev; + struct kbase_va_region *prev = NULL; + struct rb_node *rbnext; + struct kbase_va_region *next = NULL; + struct rb_root *reg_rbtree = NULL; + + int merged_front = 0; + int merged_back = 0; + int err = 0; + + reg_rbtree = kbase_reg_flags_to_rbtree(kctx, reg); + + /* Try to merge with the previous block first */ + rbprev = rb_prev(&(reg->rblink)); + if (rbprev) { + prev = rb_entry(rbprev, struct kbase_va_region, rblink); + if (prev->flags & KBASE_REG_FREE) { + /* We're compatible with the previous VMA, + * merge with it */ + WARN_ON((prev->flags & KBASE_REG_ZONE_MASK) != + (reg->flags & KBASE_REG_ZONE_MASK)); + prev->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), reg_rbtree); + reg = prev; + merged_front = 1; + } + } + + /* Try to merge with the next block second */ + /* Note we do the lookup here as the tree may have been rebalanced. */ + rbnext = rb_next(&(reg->rblink)); + if (rbnext) { + /* We're compatible with the next VMA, merge with it */ + next = rb_entry(rbnext, struct kbase_va_region, rblink); + if (next->flags & KBASE_REG_FREE) { + WARN_ON((next->flags & KBASE_REG_ZONE_MASK) != + (reg->flags & KBASE_REG_ZONE_MASK)); + next->start_pfn = reg->start_pfn; + next->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), reg_rbtree); + merged_back = 1; + if (merged_front) { + /* We already merged with prev, free it */ + kbase_free_alloced_region(reg); + } + } + } + + /* If we failed to merge then we need to add a new block */ + if (!(merged_front || merged_back)) { + /* + * We didn't merge anything. Add a new free + * placeholder and remove the original one. + */ + struct kbase_va_region *free_reg; + + free_reg = kbase_alloc_free_region(kctx, reg->start_pfn, reg->nr_pages, reg->flags & KBASE_REG_ZONE_MASK); + if (!free_reg) { + err = -ENOMEM; + goto out; + } + rb_replace_node(&(reg->rblink), &(free_reg->rblink), reg_rbtree); + } + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_remove_va_region); + +/** + * @brief Insert a VA region to the list, replacing the current at_reg. + */ +static int kbase_insert_va_region_nolock(struct kbase_context *kctx, struct kbase_va_region *new_reg, struct kbase_va_region *at_reg, u64 start_pfn, size_t nr_pages) +{ + struct rb_root *reg_rbtree = NULL; + int err = 0; + + reg_rbtree = kbase_reg_flags_to_rbtree(kctx, at_reg); + + /* Must be a free region */ + KBASE_DEBUG_ASSERT((at_reg->flags & KBASE_REG_FREE) != 0); + /* start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT((start_pfn >= at_reg->start_pfn) && (start_pfn < at_reg->start_pfn + at_reg->nr_pages)); + /* at least nr_pages from start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= at_reg->start_pfn + at_reg->nr_pages); + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + /* Regions are a whole use, so swap and delete old one. */ + if (at_reg->start_pfn == start_pfn && at_reg->nr_pages == nr_pages) { + rb_replace_node(&(at_reg->rblink), &(new_reg->rblink), + reg_rbtree); + kbase_free_alloced_region(at_reg); + } + /* New region replaces the start of the old one, so insert before. */ + else if (at_reg->start_pfn == start_pfn) { + at_reg->start_pfn += nr_pages; + KBASE_DEBUG_ASSERT(at_reg->nr_pages >= nr_pages); + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region replaces the end of the old one, so insert after. */ + else if ((at_reg->start_pfn + at_reg->nr_pages) == (start_pfn + nr_pages)) { + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region splits the old one, so insert and create new */ + else { + struct kbase_va_region *new_front_reg; + + new_front_reg = kbase_alloc_free_region(kctx, + at_reg->start_pfn, + start_pfn - at_reg->start_pfn, + at_reg->flags & KBASE_REG_ZONE_MASK); + + if (new_front_reg) { + at_reg->nr_pages -= nr_pages + new_front_reg->nr_pages; + at_reg->start_pfn = start_pfn + nr_pages; + + kbase_region_tracker_insert(kctx, new_front_reg); + kbase_region_tracker_insert(kctx, new_reg); + } else { + err = -ENOMEM; + } + } + + return err; +} + +/** + * @brief Add a VA region to the list. + */ +int kbase_add_va_region(struct kbase_context *kctx, + struct kbase_va_region *reg, u64 addr, + size_t nr_pages, size_t align) +{ + struct kbase_va_region *tmp; + u64 gpu_pfn = addr >> PAGE_SHIFT; + int err = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + lockdep_assert_held(&kctx->reg_lock); + + if (!align) + align = 1; + + /* must be a power of 2 */ + KBASE_DEBUG_ASSERT((align & (align - 1)) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + + /* Path 1: Map a specific address. Find the enclosing region, which *must* be free. */ + if (gpu_pfn) { + struct device *dev = kctx->kbdev->dev; + + KBASE_DEBUG_ASSERT(!(gpu_pfn & (align - 1))); + + tmp = kbase_region_tracker_find_region_enclosing_range_free(kctx, gpu_pfn, nr_pages); + if (!tmp) { + dev_warn(dev, "Enclosing region not found: 0x%08llx gpu_pfn, %zu nr_pages", gpu_pfn, nr_pages); + err = -ENOMEM; + goto exit; + } + if (!(tmp->flags & KBASE_REG_FREE)) { + dev_warn(dev, "Zone mismatch: %lu != %lu", tmp->flags & KBASE_REG_ZONE_MASK, reg->flags & KBASE_REG_ZONE_MASK); + dev_warn(dev, "!(tmp->flags & KBASE_REG_FREE): tmp->start_pfn=0x%llx tmp->flags=0x%lx tmp->nr_pages=0x%zx gpu_pfn=0x%llx nr_pages=0x%zx\n", tmp->start_pfn, tmp->flags, tmp->nr_pages, gpu_pfn, nr_pages); + dev_warn(dev, "in function %s (%p, %p, 0x%llx, 0x%zx, 0x%zx)\n", __func__, kctx, reg, addr, nr_pages, align); + err = -ENOMEM; + goto exit; + } + + err = kbase_insert_va_region_nolock(kctx, reg, tmp, gpu_pfn, nr_pages); + if (err) { + dev_warn(dev, "Failed to insert va region"); + err = -ENOMEM; + goto exit; + } + + goto exit; + } + + /* Path 2: Map any free address which meets the requirements. */ + { + u64 start_pfn; + + /* + * Depending on the zone the allocation request is for + * we might need to retry it. + */ + do { + tmp = kbase_region_tracker_find_region_meeting_reqs( + kctx, reg, nr_pages, align); + if (tmp) { + start_pfn = (tmp->start_pfn + align - 1) & + ~(align - 1); + err = kbase_insert_va_region_nolock(kctx, reg, + tmp, start_pfn, nr_pages); + break; + } + + /* + * If the allocation is not from the same zone as JIT + * then don't retry, we're out of VA and there is + * nothing which can be done about it. + */ + if ((reg->flags & KBASE_REG_ZONE_MASK) != + KBASE_REG_ZONE_CUSTOM_VA) + break; + } while (kbase_jit_evict(kctx)); + + if (!tmp) + err = -ENOMEM; + } + + exit: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_add_va_region); + +/** + * @brief Initialize the internal region tracker data structure. + */ +static void kbase_region_tracker_ds_init(struct kbase_context *kctx, + struct kbase_va_region *same_va_reg, + struct kbase_va_region *exec_reg, + struct kbase_va_region *custom_va_reg) +{ + kctx->reg_rbtree_same = RB_ROOT; + kbase_region_tracker_insert(kctx, same_va_reg); + + /* Although exec and custom_va_reg don't always exist, + * initialize unconditionally because of the mem_view debugfs + * implementation which relies on these being empty */ + kctx->reg_rbtree_exec = RB_ROOT; + kctx->reg_rbtree_custom = RB_ROOT; + + if (exec_reg) + kbase_region_tracker_insert(kctx, exec_reg); + if (custom_va_reg) + kbase_region_tracker_insert(kctx, custom_va_reg); +} + +static void kbase_region_tracker_erase_rbtree(struct rb_root *rbtree) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + do { + rbnode = rb_first(rbtree); + if (rbnode) { + rb_erase(rbnode, rbtree); + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + kbase_free_alloced_region(reg); + } + } while (rbnode); +} + +void kbase_region_tracker_term(struct kbase_context *kctx) +{ + kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_same); + kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_exec); + kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_custom); +} + +/** + * Initialize the region tracker data structure. + */ +int kbase_region_tracker_init(struct kbase_context *kctx) +{ + struct kbase_va_region *same_va_reg; + struct kbase_va_region *exec_reg = NULL; + struct kbase_va_region *custom_va_reg = NULL; + size_t same_va_bits = sizeof(void *) * BITS_PER_BYTE; + u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE; + u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT; + u64 same_va_pages; + int err; + + /* Take the lock as kbase_free_alloced_region requires it */ + kbase_gpu_vm_lock(kctx); + +#if defined(CONFIG_ARM64) + same_va_bits = VA_BITS; +#elif defined(CONFIG_X86_64) + same_va_bits = 47; +#elif defined(CONFIG_64BIT) +#error Unsupported 64-bit architecture +#endif + +#ifdef CONFIG_64BIT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + same_va_bits = 32; + else if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) + same_va_bits = 33; +#endif + + if (kctx->kbdev->gpu_props.mmu.va_bits < same_va_bits) { + err = -EINVAL; + goto fail_unlock; + } + + same_va_pages = (1ULL << (same_va_bits - PAGE_SHIFT)) - 1; + /* all have SAME_VA */ + same_va_reg = kbase_alloc_free_region(kctx, 1, + same_va_pages, + KBASE_REG_ZONE_SAME_VA); + + if (!same_va_reg) { + err = -ENOMEM; + goto fail_unlock; + } + +#ifdef CONFIG_64BIT + /* 32-bit clients have exec and custom VA zones */ + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) { +#endif + if (gpu_va_limit <= KBASE_REG_ZONE_CUSTOM_VA_BASE) { + err = -EINVAL; + goto fail_free_same_va; + } + /* If the current size of TMEM is out of range of the + * virtual address space addressable by the MMU then + * we should shrink it to fit + */ + if ((KBASE_REG_ZONE_CUSTOM_VA_BASE + KBASE_REG_ZONE_CUSTOM_VA_SIZE) >= gpu_va_limit) + custom_va_size = gpu_va_limit - KBASE_REG_ZONE_CUSTOM_VA_BASE; + + exec_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_EXEC_BASE, + KBASE_REG_ZONE_EXEC_SIZE, + KBASE_REG_ZONE_EXEC); + + if (!exec_reg) { + err = -ENOMEM; + goto fail_free_same_va; + } + + custom_va_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_CUSTOM_VA_BASE, + custom_va_size, KBASE_REG_ZONE_CUSTOM_VA); + + if (!custom_va_reg) { + err = -ENOMEM; + goto fail_free_exec; + } +#ifdef CONFIG_64BIT + } +#endif + + kbase_region_tracker_ds_init(kctx, same_va_reg, exec_reg, custom_va_reg); + + kctx->same_va_end = same_va_pages + 1; + + kbase_gpu_vm_unlock(kctx); + return 0; + +fail_free_exec: + kbase_free_alloced_region(exec_reg); +fail_free_same_va: + kbase_free_alloced_region(same_va_reg); +fail_unlock: + kbase_gpu_vm_unlock(kctx); + return err; +} + +int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages) +{ +#ifdef CONFIG_64BIT + struct kbase_va_region *same_va; + struct kbase_va_region *custom_va_reg; + u64 same_va_bits; + u64 total_va_size; + int err; + + /* + * Nothing to do for 32-bit clients, JIT uses the existing + * custom VA zone. + */ + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + return 0; + +#if defined(CONFIG_ARM64) + same_va_bits = VA_BITS; +#elif defined(CONFIG_X86_64) + same_va_bits = 47; +#elif defined(CONFIG_64BIT) +#error Unsupported 64-bit architecture +#endif + + if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) + same_va_bits = 33; + + total_va_size = (1ULL << (same_va_bits - PAGE_SHIFT)) - 1; + + kbase_gpu_vm_lock(kctx); + + /* + * Modify the same VA free region after creation. Be careful to ensure + * that allocations haven't been made as they could cause an overlap + * to happen with existing same VA allocations and the custom VA zone. + */ + same_va = kbase_region_tracker_find_region_base_address(kctx, + PAGE_SIZE); + if (!same_va) { + err = -ENOMEM; + goto fail_unlock; + } + + /* The region flag or region size has changed since creation so bail. */ + if ((!(same_va->flags & KBASE_REG_FREE)) || + (same_va->nr_pages != total_va_size)) { + err = -ENOMEM; + goto fail_unlock; + } + + if (same_va->nr_pages < jit_va_pages || + kctx->same_va_end < jit_va_pages) { + err = -ENOMEM; + goto fail_unlock; + } + + /* It's safe to adjust the same VA zone now */ + same_va->nr_pages -= jit_va_pages; + kctx->same_va_end -= jit_va_pages; + + /* + * Create a custom VA zone at the end of the VA for allocations which + * JIT can use so it doesn't have to allocate VA from the kernel. + */ + custom_va_reg = kbase_alloc_free_region(kctx, + kctx->same_va_end, + jit_va_pages, + KBASE_REG_ZONE_CUSTOM_VA); + + if (!custom_va_reg) { + /* + * The context will be destroyed if we fail here so no point + * reverting the change we made to same_va. + */ + err = -ENOMEM; + goto fail_unlock; + } + + kbase_region_tracker_insert(kctx, custom_va_reg); + + kbase_gpu_vm_unlock(kctx); + return 0; + +fail_unlock: + kbase_gpu_vm_unlock(kctx); + return err; +#else + return 0; +#endif +} + +int kbase_mem_init(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + int ret; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + kbdev->mem_pool_max_size_default = KBASE_MEM_POOL_MAX_SIZE_KCTX; + + /* Initialize memory usage */ + atomic_set(&memdev->used_pages, 0); + + ret = kbase_mem_pool_init(&kbdev->mem_pool, + KBASE_MEM_POOL_MAX_SIZE_KBDEV, + KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER, + kbdev, + NULL); + if (ret) + return ret; + + ret = kbase_mem_pool_init(&kbdev->lp_mem_pool, + (KBASE_MEM_POOL_MAX_SIZE_KBDEV >> 9), + KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, + kbdev, + NULL); + if (ret) + kbase_mem_pool_term(&kbdev->mem_pool); + + return ret; +} + +void kbase_mem_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_mem_term(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + int pages; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + + pages = atomic_read(&memdev->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); + + kbase_mem_pool_term(&kbdev->mem_pool); + kbase_mem_pool_term(&kbdev->lp_mem_pool); +} + +KBASE_EXPORT_TEST_API(kbase_mem_term); + + + + +/** + * @brief Allocate a free region object. + * + * The allocated object is not part of any list yet, and is flagged as + * KBASE_REG_FREE. No mapping is allocated yet. + * + * zone is KBASE_REG_ZONE_CUSTOM_VA, KBASE_REG_ZONE_SAME_VA, or KBASE_REG_ZONE_EXEC + * + */ +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone) +{ + struct kbase_va_region *new_reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* zone argument should only contain zone related region flags */ + KBASE_DEBUG_ASSERT((zone & ~KBASE_REG_ZONE_MASK) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= (U64_MAX / PAGE_SIZE)); + + new_reg = kzalloc(sizeof(*new_reg), GFP_KERNEL); + + if (!new_reg) + return NULL; + + new_reg->cpu_alloc = NULL; /* no alloc bound yet */ + new_reg->gpu_alloc = NULL; /* no alloc bound yet */ + new_reg->kctx = kctx; + new_reg->flags = zone | KBASE_REG_FREE; + + new_reg->flags |= KBASE_REG_GROWABLE; + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + return new_reg; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_free_region); + +/** + * @brief Free a region object. + * + * The described region must be freed of any mapping. + * + * If the region is not flagged as KBASE_REG_FREE, the region's + * alloc object will be released. + * It is a bug if no alloc object exists for non-free regions. + * + */ +void kbase_free_alloced_region(struct kbase_va_region *reg) +{ + if (!(reg->flags & KBASE_REG_FREE)) { + /* + * The physical allocation should have been removed from the + * eviction list before this function is called. However, in the + * case of abnormal process termination or the app leaking the + * memory kbase_mem_free_region is not called so it can still be + * on the list at termination time of the region tracker. + */ + if (!list_empty(®->gpu_alloc->evict_node)) { + /* + * Unlink the physical allocation before unmaking it + * evictable so that the allocation isn't grown back to + * its last backed size as we're going to unmap it + * anyway. + */ + reg->cpu_alloc->reg = NULL; + if (reg->cpu_alloc != reg->gpu_alloc) + reg->gpu_alloc->reg = NULL; + + /* + * If a region has been made evictable then we must + * unmake it before trying to free it. + * If the memory hasn't been reclaimed it will be + * unmapped and freed below, if it has been reclaimed + * then the operations below are no-ops. + */ + if (reg->flags & KBASE_REG_DONT_NEED) { + KBASE_DEBUG_ASSERT(reg->cpu_alloc->type == + KBASE_MEM_TYPE_NATIVE); + kbase_mem_evictable_unmake(reg->gpu_alloc); + } + } + + /* + * Remove the region from the sticky resource metadata + * list should it be there. + */ + kbase_sticky_resource_release(reg->kctx, NULL, + reg->start_pfn << PAGE_SHIFT); + + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); + /* To detect use-after-free in debug builds */ + KBASE_DEBUG_CODE(reg->flags |= KBASE_REG_FREE); + } + kfree(reg); +} + +KBASE_EXPORT_TEST_API(kbase_free_alloced_region); + +int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64 addr, size_t nr_pages, size_t align) +{ + int err; + size_t i = 0; + unsigned long attr; + unsigned long mask = ~KBASE_REG_MEMATTR_MASK; + + if ((kctx->kbdev->system_coherency == COHERENCY_ACE) && + (reg->flags & KBASE_REG_SHARE_BOTH)) + attr = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_OUTER_WA); + else + attr = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_WRITE_ALLOC); + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + err = kbase_add_va_region(kctx, reg, addr, nr_pages, align); + if (err) + return err; + + if (reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + struct kbase_mem_phy_alloc *alloc; + + alloc = reg->gpu_alloc; + stride = alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(alloc->imported.alias.aliased); + for (i = 0; i < alloc->imported.alias.nents; i++) { + if (alloc->imported.alias.aliased[i].alloc) { + err = kbase_mmu_insert_pages(kctx, + reg->start_pfn + (i * stride), + alloc->imported.alias.aliased[i].alloc->pages + alloc->imported.alias.aliased[i].offset, + alloc->imported.alias.aliased[i].length, + reg->flags); + if (err) + goto bad_insert; + + kbase_mem_phy_alloc_gpu_mapped(alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_insert_single_page(kctx, + reg->start_pfn + i * stride, + kctx->aliasing_sink_page, + alloc->imported.alias.aliased[i].length, + (reg->flags & mask) | attr); + + if (err) + goto bad_insert; + } + } + } else { + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, + kbase_get_gpu_phy_pages(reg), + kbase_reg_current_backed_size(reg), + reg->flags); + if (err) + goto bad_insert; + kbase_mem_phy_alloc_gpu_mapped(reg->gpu_alloc); + } + + return err; + +bad_insert: + if (reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + + stride = reg->gpu_alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(reg->gpu_alloc->imported.alias.aliased); + while (i--) + if (reg->gpu_alloc->imported.alias.aliased[i].alloc) { + kbase_mmu_teardown_pages(kctx, reg->start_pfn + (i * stride), reg->gpu_alloc->imported.alias.aliased[i].length); + kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc->imported.alias.aliased[i].alloc); + } + } + + kbase_remove_va_region(kctx, reg); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_gpu_mmap); + +static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, + struct kbase_mem_phy_alloc *alloc, bool writeable); + +int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + int err; + + if (reg->start_pfn == 0) + return 0; + + if (reg->gpu_alloc && reg->gpu_alloc->type == KBASE_MEM_TYPE_ALIAS) { + size_t i; + + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, reg->nr_pages); + KBASE_DEBUG_ASSERT(reg->gpu_alloc->imported.alias.aliased); + for (i = 0; i < reg->gpu_alloc->imported.alias.nents; i++) + if (reg->gpu_alloc->imported.alias.aliased[i].alloc) + kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, kbase_reg_current_backed_size(reg)); + kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc); + } + + if (reg->gpu_alloc && reg->gpu_alloc->type == + KBASE_MEM_TYPE_IMPORTED_USER_BUF) { + struct kbase_alloc_import_user_buf *user_buf = + ®->gpu_alloc->imported.user_buf; + + if (user_buf->current_mapping_usage_count & PINNED_ON_IMPORT) { + user_buf->current_mapping_usage_count &= + ~PINNED_ON_IMPORT; + + kbase_jd_user_buf_unmap(kctx, reg->gpu_alloc, + (reg->flags & KBASE_REG_GPU_WR)); + } + } + + if (err) + return err; + + err = kbase_remove_va_region(kctx, reg); + return err; +} + +static struct kbase_cpu_mapping *kbasep_find_enclosing_cpu_mapping( + struct kbase_context *kctx, + unsigned long uaddr, size_t size, u64 *offset) +{ + struct vm_area_struct *vma; + struct kbase_cpu_mapping *map; + unsigned long vm_pgoff_in_region; + unsigned long vm_off_in_region; + unsigned long map_start; + size_t map_size; + + lockdep_assert_held(¤t->mm->mmap_sem); + + if ((uintptr_t) uaddr + size < (uintptr_t) uaddr) /* overflow check */ + return NULL; + + vma = find_vma_intersection(current->mm, uaddr, uaddr+size); + + if (!vma || vma->vm_start > uaddr) + return NULL; + if (vma->vm_ops != &kbase_vm_ops) + /* Not ours! */ + return NULL; + + map = vma->vm_private_data; + + if (map->kctx != kctx) + /* Not from this context! */ + return NULL; + + vm_pgoff_in_region = vma->vm_pgoff - map->region->start_pfn; + vm_off_in_region = vm_pgoff_in_region << PAGE_SHIFT; + map_start = vma->vm_start - vm_off_in_region; + map_size = map->region->nr_pages << PAGE_SHIFT; + + if ((uaddr + size) > (map_start + map_size)) + /* Not within the CPU mapping */ + return NULL; + + *offset = (uaddr - vma->vm_start) + vm_off_in_region; + + return map; +} + +int kbasep_find_enclosing_cpu_mapping_offset( + struct kbase_context *kctx, + unsigned long uaddr, size_t size, u64 *offset) +{ + struct kbase_cpu_mapping *map; + + kbase_os_mem_map_lock(kctx); + + map = kbasep_find_enclosing_cpu_mapping(kctx, uaddr, size, offset); + + kbase_os_mem_map_unlock(kctx); + + if (!map) + return -EINVAL; + + return 0; +} + +KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_offset); + +void kbase_sync_single(struct kbase_context *kctx, + struct tagged_addr t_cpu_pa, struct tagged_addr t_gpu_pa, + off_t offset, size_t size, enum kbase_sync_type sync_fn) +{ + struct page *cpu_page; + phys_addr_t cpu_pa = as_phys_addr_t(t_cpu_pa); + phys_addr_t gpu_pa = as_phys_addr_t(t_gpu_pa); + + cpu_page = pfn_to_page(PFN_DOWN(cpu_pa)); + + if (likely(cpu_pa == gpu_pa)) { + dma_addr_t dma_addr; + + BUG_ON(!cpu_page); + BUG_ON(offset + size > PAGE_SIZE); + + dma_addr = kbase_dma_addr(cpu_page) + offset; + if (sync_fn == KBASE_SYNC_TO_CPU) + dma_sync_single_for_cpu(kctx->kbdev->dev, dma_addr, + size, DMA_BIDIRECTIONAL); + else if (sync_fn == KBASE_SYNC_TO_DEVICE) + dma_sync_single_for_device(kctx->kbdev->dev, dma_addr, + size, DMA_BIDIRECTIONAL); + } else { + void *src = NULL; + void *dst = NULL; + struct page *gpu_page; + + if (WARN(!gpu_pa, "No GPU PA found for infinite cache op")) + return; + + gpu_page = pfn_to_page(PFN_DOWN(gpu_pa)); + + if (sync_fn == KBASE_SYNC_TO_DEVICE) { + src = ((unsigned char *)kmap(cpu_page)) + offset; + dst = ((unsigned char *)kmap(gpu_page)) + offset; + } else if (sync_fn == KBASE_SYNC_TO_CPU) { + dma_sync_single_for_cpu(kctx->kbdev->dev, + kbase_dma_addr(gpu_page) + offset, + size, DMA_BIDIRECTIONAL); + src = ((unsigned char *)kmap(gpu_page)) + offset; + dst = ((unsigned char *)kmap(cpu_page)) + offset; + } + memcpy(dst, src, size); + kunmap(gpu_page); + kunmap(cpu_page); + if (sync_fn == KBASE_SYNC_TO_DEVICE) + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(gpu_page) + offset, + size, DMA_BIDIRECTIONAL); + } +} + +static int kbase_do_syncset(struct kbase_context *kctx, + struct basep_syncset *sset, enum kbase_sync_type sync_fn) +{ + int err = 0; + struct kbase_va_region *reg; + struct kbase_cpu_mapping *map; + unsigned long start; + size_t size; + struct tagged_addr *cpu_pa; + struct tagged_addr *gpu_pa; + u64 page_off, page_count; + u64 i; + u64 offset; + + kbase_os_mem_map_lock(kctx); + kbase_gpu_vm_lock(kctx); + + /* find the region where the virtual address is contained */ + reg = kbase_region_tracker_find_region_enclosing_address(kctx, + sset->mem_handle.basep.handle); + if (!reg) { + dev_warn(kctx->kbdev->dev, "Can't find region at VA 0x%016llX", + sset->mem_handle.basep.handle); + err = -EINVAL; + goto out_unlock; + } + + if (!(reg->flags & KBASE_REG_CPU_CACHED) || + kbase_mem_is_imported(reg->gpu_alloc->type)) + goto out_unlock; + + start = (uintptr_t)sset->user_addr; + size = (size_t)sset->size; + + map = kbasep_find_enclosing_cpu_mapping(kctx, start, size, &offset); + if (!map) { + dev_warn(kctx->kbdev->dev, "Can't find CPU mapping 0x%016lX for VA 0x%016llX", + start, sset->mem_handle.basep.handle); + err = -EINVAL; + goto out_unlock; + } + + page_off = offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + page_count = (size + offset + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + cpu_pa = kbase_get_cpu_phy_pages(reg); + gpu_pa = kbase_get_gpu_phy_pages(reg); + + if (page_off > reg->nr_pages || + page_off + page_count > reg->nr_pages) { + /* Sync overflows the region */ + err = -EINVAL; + goto out_unlock; + } + + /* Sync first page */ + if (as_phys_addr_t(cpu_pa[page_off])) { + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + + kbase_sync_single(kctx, cpu_pa[page_off], gpu_pa[page_off], + offset, sz, sync_fn); + } + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + /* we grow upwards, so bail on first non-present page */ + if (!as_phys_addr_t(cpu_pa[page_off + i])) + break; + + kbase_sync_single(kctx, cpu_pa[page_off + i], + gpu_pa[page_off + i], 0, PAGE_SIZE, sync_fn); + } + + /* Sync last page (if any) */ + if (page_count > 1 && + as_phys_addr_t(cpu_pa[page_off + page_count - 1])) { + size_t sz = ((start + size - 1) & ~PAGE_MASK) + 1; + + kbase_sync_single(kctx, cpu_pa[page_off + page_count - 1], + gpu_pa[page_off + page_count - 1], 0, sz, + sync_fn); + } + +out_unlock: + kbase_gpu_vm_unlock(kctx); + kbase_os_mem_map_unlock(kctx); + return err; +} + +int kbase_sync_now(struct kbase_context *kctx, struct basep_syncset *sset) +{ + int err = -EINVAL; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(sset != NULL); + + if (sset->mem_handle.basep.handle & ~PAGE_MASK) { + dev_warn(kctx->kbdev->dev, + "mem_handle: passed parameter is invalid"); + return -EINVAL; + } + + switch (sset->type) { + case BASE_SYNCSET_OP_MSYNC: + err = kbase_do_syncset(kctx, sset, KBASE_SYNC_TO_DEVICE); + break; + + case BASE_SYNCSET_OP_CSYNC: + err = kbase_do_syncset(kctx, sset, KBASE_SYNC_TO_CPU); + break; + + default: + dev_warn(kctx->kbdev->dev, "Unknown msync op %d\n", sset->type); + break; + } + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_sync_now); + +/* vm lock must be held */ +int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + int err; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + lockdep_assert_held(&kctx->reg_lock); + + /* + * Unlink the physical allocation before unmaking it evictable so + * that the allocation isn't grown back to its last backed size + * as we're going to unmap it anyway. + */ + reg->cpu_alloc->reg = NULL; + if (reg->cpu_alloc != reg->gpu_alloc) + reg->gpu_alloc->reg = NULL; + + /* + * If a region has been made evictable then we must unmake it + * before trying to free it. + * If the memory hasn't been reclaimed it will be unmapped and freed + * below, if it has been reclaimed then the operations below are no-ops. + */ + if (reg->flags & KBASE_REG_DONT_NEED) { + KBASE_DEBUG_ASSERT(reg->cpu_alloc->type == + KBASE_MEM_TYPE_NATIVE); + kbase_mem_evictable_unmake(reg->gpu_alloc); + } + + err = kbase_gpu_munmap(kctx, reg); + if (err) { + dev_warn(reg->kctx->kbdev->dev, "Could not unmap from the GPU...\n"); + goto out; + } + + /* This will also free the physical pages */ + kbase_free_alloced_region(reg); + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free_region); + +/** + * @brief Free the region from the GPU and unregister it. + * + * This function implements the free operation on a memory segment. + * It will loudly fail if called with outstanding mappings. + */ +int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr) +{ + int err = 0; + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + if ((gpu_addr & ~PAGE_MASK) && (gpu_addr >= PAGE_SIZE)) { + dev_warn(kctx->kbdev->dev, "kbase_mem_free: gpu_addr parameter is invalid"); + return -EINVAL; + } + + if (0 == gpu_addr) { + dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n"); + return -EINVAL; + } + kbase_gpu_vm_lock(kctx); + + if (gpu_addr >= BASE_MEM_COOKIE_BASE && + gpu_addr < BASE_MEM_FIRST_FREE_ADDRESS) { + int cookie = PFN_DOWN(gpu_addr - BASE_MEM_COOKIE_BASE); + + reg = kctx->pending_regions[cookie]; + if (!reg) { + err = -EINVAL; + goto out_unlock; + } + + /* ask to unlink the cookie as we'll free it */ + + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + kbase_free_alloced_region(reg); + } else { + /* A real GPU va */ + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) { + dev_warn(kctx->kbdev->dev, "kbase_mem_free called with nonexistent gpu_addr 0x%llX", + gpu_addr); + err = -EINVAL; + goto out_unlock; + } + + if ((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA) { + /* SAME_VA must be freed through munmap */ + dev_warn(kctx->kbdev->dev, "%s called on SAME_VA memory 0x%llX", __func__, + gpu_addr); + err = -EINVAL; + goto out_unlock; + } + err = kbase_mem_free_region(kctx, reg); + } + + out_unlock: + kbase_gpu_vm_unlock(kctx); + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free); + +int kbase_update_region_flags(struct kbase_context *kctx, + struct kbase_va_region *reg, unsigned long flags) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT((flags & ~((1ul << BASE_MEM_FLAGS_NR_BITS) - 1)) == 0); + + reg->flags |= kbase_cache_enabled(flags, reg->nr_pages); + /* all memory is now growable */ + reg->flags |= KBASE_REG_GROWABLE; + + if (flags & BASE_MEM_GROW_ON_GPF) + reg->flags |= KBASE_REG_PF_GROW; + + if (flags & BASE_MEM_PROT_CPU_WR) + reg->flags |= KBASE_REG_CPU_WR; + + if (flags & BASE_MEM_PROT_CPU_RD) + reg->flags |= KBASE_REG_CPU_RD; + + if (flags & BASE_MEM_PROT_GPU_WR) + reg->flags |= KBASE_REG_GPU_WR; + + if (flags & BASE_MEM_PROT_GPU_RD) + reg->flags |= KBASE_REG_GPU_RD; + + if (0 == (flags & BASE_MEM_PROT_GPU_EX)) + reg->flags |= KBASE_REG_GPU_NX; + + if (!kbase_device_is_cpu_coherent(kctx->kbdev)) { + if (flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED) + return -EINVAL; + } else if (flags & (BASE_MEM_COHERENT_SYSTEM | + BASE_MEM_COHERENT_SYSTEM_REQUIRED)) { + reg->flags |= KBASE_REG_SHARE_BOTH; + } + + if (!(reg->flags & KBASE_REG_SHARE_BOTH) && + flags & BASE_MEM_COHERENT_LOCAL) { + reg->flags |= KBASE_REG_SHARE_IN; + } + + /* Set up default MEMATTR usage */ + if (kctx->kbdev->system_coherency == COHERENCY_ACE && + (reg->flags & KBASE_REG_SHARE_BOTH)) { + reg->flags |= + KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT_ACE); + } else { + reg->flags |= + KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT); + } + + return 0; +} + +int kbase_alloc_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_requested) +{ + int new_page_count __maybe_unused; + size_t old_page_count = alloc->nents; + size_t nr_left = nr_pages_requested; + int res; + struct kbase_context *kctx; + struct tagged_addr *tp; + + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + + kctx = alloc->imported.kctx; + + if (nr_pages_requested == 0) + goto done; /*nothing to do*/ + + new_page_count = kbase_atomic_add_pages( + nr_pages_requested, &kctx->used_pages); + kbase_atomic_add_pages(nr_pages_requested, + &kctx->kbdev->memdev.used_pages); + + /* Increase mm counters before we allocate pages so that this + * allocation is visible to the OOM killer */ + kbase_process_page_usage_inc(kctx, nr_pages_requested); + + tp = alloc->pages + old_page_count; + +#ifdef CONFIG_MALI_2MB_ALLOC + /* Check if we have enough pages requested so we can allocate a large + * page (512 * 4KB = 2MB ) + */ + if (nr_left >= (SZ_2M / SZ_4K)) { + int nr_lp = nr_left / (SZ_2M / SZ_4K); + + res = kbase_mem_pool_alloc_pages(&kctx->lp_mem_pool, + nr_lp * (SZ_2M / SZ_4K), + tp, + true); + + if (res > 0) { + nr_left -= res; + tp += res; + } + + if (nr_left) { + struct kbase_sub_alloc *sa, *temp_sa; + + mutex_lock(&kctx->mem_partials_lock); + + list_for_each_entry_safe(sa, temp_sa, + &kctx->mem_partials, link) { + int pidx = 0; + + while (nr_left) { + pidx = find_next_zero_bit(sa->sub_pages, + SZ_2M / SZ_4K, + pidx); + bitmap_set(sa->sub_pages, pidx, 1); + *tp++ = as_tagged_tag(page_to_phys(sa->page + + pidx), + FROM_PARTIAL); + nr_left--; + + if (bitmap_full(sa->sub_pages, SZ_2M / SZ_4K)) { + /* unlink from partial list when full */ + list_del_init(&sa->link); + break; + } + } + } + mutex_unlock(&kctx->mem_partials_lock); + } + + /* only if we actually have a chunk left <512. If more it indicates + * that we couldn't allocate a 2MB above, so no point to retry here. + */ + if (nr_left > 0 && nr_left < (SZ_2M / SZ_4K)) { + /* create a new partial and suballocate the rest from it */ + struct page *np = NULL; + + do { + int err; + + np = kbase_mem_pool_alloc(&kctx->lp_mem_pool); + if (np) + break; + err = kbase_mem_pool_grow(&kctx->lp_mem_pool, 1); + if (err) + break; + } while (1); + + if (np) { + int i; + struct kbase_sub_alloc *sa; + struct page *p; + + sa = kmalloc(sizeof(*sa), GFP_KERNEL); + if (!sa) { + kbase_mem_pool_free(&kctx->lp_mem_pool, np, false); + goto no_new_partial; + } + + /* store pointers back to the control struct */ + np->lru.next = (void *)sa; + for (p = np; p < np + SZ_2M / SZ_4K; p++) + p->lru.prev = (void *)np; + INIT_LIST_HEAD(&sa->link); + bitmap_zero(sa->sub_pages, SZ_2M / SZ_4K); + sa->page = np; + + for (i = 0; i < nr_left; i++) + *tp++ = as_tagged_tag(page_to_phys(np + i), FROM_PARTIAL); + + bitmap_set(sa->sub_pages, 0, nr_left); + nr_left = 0; + + /* expose for later use */ + mutex_lock(&kctx->mem_partials_lock); + list_add(&sa->link, &kctx->mem_partials); + mutex_unlock(&kctx->mem_partials_lock); + } + } + } +no_new_partial: +#endif + + if (nr_left) { + res = kbase_mem_pool_alloc_pages(&kctx->mem_pool, + nr_left, + tp, + false); + if (res <= 0) + goto alloc_failed; + } + + /* + * Request a zone cache update, this scans only the new pages an + * appends their information to the zone cache. if the update + * fails then clear the cache so we fall-back to doing things + * page by page. + */ + if (kbase_zone_cache_update(alloc, old_page_count) != 0) + kbase_zone_cache_clear(alloc); + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); + + alloc->nents += nr_pages_requested; +done: + return 0; + +alloc_failed: + /* rollback needed if got one or more 2MB but failed later */ + if (nr_left != nr_pages_requested) + kbase_mem_pool_free_pages(&kctx->lp_mem_pool, + nr_pages_requested - nr_left, + alloc->pages + old_page_count, + false, + false); + + kbase_process_page_usage_dec(kctx, nr_pages_requested); + kbase_atomic_sub_pages(nr_pages_requested, &kctx->used_pages); + kbase_atomic_sub_pages(nr_pages_requested, + &kctx->kbdev->memdev.used_pages); + + return -ENOMEM; +} + +static void free_partial(struct kbase_context *kctx, struct tagged_addr tp) +{ + struct page *p, *head_page; + struct kbase_sub_alloc *sa; + + p = phys_to_page(as_phys_addr_t(tp)); + head_page = (struct page *)p->lru.prev; + sa = (struct kbase_sub_alloc *)head_page->lru.next; + mutex_lock(&kctx->mem_partials_lock); + clear_bit(p - head_page, sa->sub_pages); + if (bitmap_empty(sa->sub_pages, SZ_2M / SZ_4K)) { + list_del(&sa->link); + kbase_mem_pool_free(&kctx->lp_mem_pool, head_page, true); + kfree(sa); + } else if (bitmap_weight(sa->sub_pages, SZ_2M / SZ_4K) == + SZ_2M / SZ_4K - 1) { + /* expose the partial again */ + list_add(&sa->link, &kctx->mem_partials); + } + mutex_unlock(&kctx->mem_partials_lock); +} + +int kbase_free_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_to_free) +{ + struct kbase_context *kctx = alloc->imported.kctx; + bool syncback; + bool reclaimed = (alloc->evicted != 0); + struct tagged_addr *start_free; + int new_page_count __maybe_unused; + size_t freed = 0; + + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + KBASE_DEBUG_ASSERT(alloc->nents >= nr_pages_to_free); + + /* early out if nothing to do */ + if (0 == nr_pages_to_free) + return 0; + + start_free = alloc->pages + alloc->nents - nr_pages_to_free; + + syncback = alloc->properties & KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED; + + /* pad start_free to a valid start location */ + while (nr_pages_to_free && is_huge(*start_free) && + !is_huge_head(*start_free)) { + nr_pages_to_free--; + start_free++; + } + + /* + * Clear the zone cache, we don't expect JIT allocations to be + * shrunk in parts so there is no point trying to optimize for that + * by scanning for the changes caused by freeing this memory and + * updating the existing cache entries. + */ + kbase_zone_cache_clear(alloc); + + + while (nr_pages_to_free) { + if (is_huge_head(*start_free)) { + /* This is a 2MB entry, so free all the 512 pages that + * it points to + */ + kbase_mem_pool_free_pages(&kctx->lp_mem_pool, + 512, + start_free, + syncback, + reclaimed); + nr_pages_to_free -= 512; + start_free += 512; + freed += 512; + } else if (is_partial(*start_free)) { + free_partial(kctx, *start_free); + nr_pages_to_free--; + start_free++; + freed++; + } else { + struct tagged_addr *local_end_free; + + local_end_free = start_free; + while (nr_pages_to_free && + !is_huge(*local_end_free) && + !is_partial(*local_end_free)) { + local_end_free++; + nr_pages_to_free--; + } + kbase_mem_pool_free_pages(&kctx->mem_pool, + local_end_free - start_free, + start_free, + syncback, + reclaimed); + freed += local_end_free - start_free; + start_free += local_end_free - start_free; + } + } + + alloc->nents -= freed; + + /* + * If the allocation was not evicted (i.e. evicted == 0) then + * the page accounting needs to be done. + */ + if (!reclaimed) { + kbase_process_page_usage_dec(kctx, freed); + new_page_count = kbase_atomic_sub_pages(freed, + &kctx->used_pages); + kbase_atomic_sub_pages(freed, + &kctx->kbdev->memdev.used_pages); + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); + } + + return 0; +} + +void kbase_mem_kref_free(struct kref *kref) +{ + struct kbase_mem_phy_alloc *alloc; + + alloc = container_of(kref, struct kbase_mem_phy_alloc, kref); + + switch (alloc->type) { + case KBASE_MEM_TYPE_NATIVE: { + WARN_ON(!alloc->imported.kctx); + /* + * The physical allocation must have been removed from the + * eviction list before trying to free it. + */ + WARN_ON(!list_empty(&alloc->evict_node)); + kbase_free_phy_pages_helper(alloc, alloc->nents); + break; + } + case KBASE_MEM_TYPE_ALIAS: { + /* just call put on the underlying phy allocs */ + size_t i; + struct kbase_aliased *aliased; + + aliased = alloc->imported.alias.aliased; + if (aliased) { + for (i = 0; i < alloc->imported.alias.nents; i++) + if (aliased[i].alloc) + kbase_mem_phy_alloc_put(aliased[i].alloc); + vfree(aliased); + } + break; + } + case KBASE_MEM_TYPE_RAW: + /* raw pages, external cleanup */ + break; + #ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ump_dd_release(alloc->imported.ump_handle); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + dma_buf_detach(alloc->imported.umm.dma_buf, + alloc->imported.umm.dma_attachment); + dma_buf_put(alloc->imported.umm.dma_buf); + break; +#endif + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: + if (alloc->imported.user_buf.mm) + mmdrop(alloc->imported.user_buf.mm); + kfree(alloc->imported.user_buf.pages); + break; + case KBASE_MEM_TYPE_TB:{ + void *tb; + + tb = alloc->imported.kctx->jctx.tb; + kbase_device_trace_buffer_uninstall(alloc->imported.kctx); + vfree(tb); + break; + } + default: + WARN(1, "Unexecpted free of type %d\n", alloc->type); + break; + } + + /* Free based on allocation type */ + if (alloc->properties & KBASE_MEM_PHY_ALLOC_LARGE) + vfree(alloc); + else + kfree(alloc); +} + +KBASE_EXPORT_TEST_API(kbase_mem_kref_free); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT(vsize > 0); + + /* validate user provided arguments */ + if (size > vsize || vsize > reg->nr_pages) + goto out_term; + + /* Prevent vsize*sizeof from wrapping around. + * For instance, if vsize is 2**29+1, we'll allocate 1 byte and the alloc won't fail. + */ + if ((size_t) vsize > ((size_t) -1 / sizeof(*reg->cpu_alloc->pages))) + goto out_term; + + KBASE_DEBUG_ASSERT(0 != vsize); + + if (kbase_alloc_phy_pages_helper(reg->cpu_alloc, size) != 0) + goto out_term; + + reg->cpu_alloc->reg = reg; + if (reg->cpu_alloc != reg->gpu_alloc) { + if (kbase_alloc_phy_pages_helper(reg->gpu_alloc, size) != 0) + goto out_rollback; + reg->gpu_alloc->reg = reg; + } + + return 0; + +out_rollback: + kbase_free_phy_pages_helper(reg->cpu_alloc, size); +out_term: + return -1; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages); + +bool kbase_check_alloc_flags(unsigned long flags) +{ + /* Only known input flags should be set. */ + if (flags & ~BASE_MEM_FLAGS_INPUT_MASK) + return false; + + /* At least one flag should be set */ + if (flags == 0) + return false; + + /* Either the GPU or CPU must be reading from the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD)) == 0) + return false; + + /* Either the GPU or CPU must be writing to the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR)) == 0) + return false; + + /* GPU cannot be writing to GPU executable memory and cannot grow the memory on page fault. */ + if ((flags & BASE_MEM_PROT_GPU_EX) && (flags & (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF))) + return false; + + /* GPU should have at least read or write access otherwise there is no + reason for allocating. */ + if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0) + return false; + + /* BASE_MEM_IMPORT_SHARED is only valid for imported memory */ + if ((flags & BASE_MEM_IMPORT_SHARED) == BASE_MEM_IMPORT_SHARED) + return false; + + return true; +} + +bool kbase_check_import_flags(unsigned long flags) +{ + /* Only known input flags should be set. */ + if (flags & ~BASE_MEM_FLAGS_INPUT_MASK) + return false; + + /* At least one flag should be set */ + if (flags == 0) + return false; + + /* Imported memory cannot be GPU executable */ + if (flags & BASE_MEM_PROT_GPU_EX) + return false; + + /* Imported memory cannot grow on page fault */ + if (flags & BASE_MEM_GROW_ON_GPF) + return false; + + /* GPU should have at least read or write access otherwise there is no + reason for importing. */ + if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0) + return false; + + /* Secure memory cannot be read by the CPU */ + if ((flags & BASE_MEM_SECURE) && (flags & BASE_MEM_PROT_CPU_RD)) + return false; + + return true; +} + +/** + * @brief Acquire the per-context region list lock + */ +void kbase_gpu_vm_lock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_lock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock); + +/** + * @brief Release the per-context region list lock + */ +void kbase_gpu_vm_unlock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_unlock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock); + +#ifdef CONFIG_DEBUG_FS +struct kbase_jit_debugfs_data { + int (*func)(struct kbase_jit_debugfs_data *); + struct mutex lock; + struct kbase_context *kctx; + u64 active_value; + u64 pool_value; + u64 destroy_value; + char buffer[50]; +}; + +static int kbase_jit_debugfs_common_open(struct inode *inode, + struct file *file, int (*func)(struct kbase_jit_debugfs_data *)) +{ + struct kbase_jit_debugfs_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->func = func; + mutex_init(&data->lock); + data->kctx = (struct kbase_context *) inode->i_private; + + file->private_data = data; + + return nonseekable_open(inode, file); +} + +static ssize_t kbase_jit_debugfs_common_read(struct file *file, + char __user *buf, size_t len, loff_t *ppos) +{ + struct kbase_jit_debugfs_data *data; + size_t size; + int ret; + + data = (struct kbase_jit_debugfs_data *) file->private_data; + mutex_lock(&data->lock); + + if (*ppos) { + size = strnlen(data->buffer, sizeof(data->buffer)); + } else { + if (!data->func) { + ret = -EACCES; + goto out_unlock; + } + + if (data->func(data)) { + ret = -EACCES; + goto out_unlock; + } + + size = scnprintf(data->buffer, sizeof(data->buffer), + "%llu,%llu,%llu", data->active_value, + data->pool_value, data->destroy_value); + } + + ret = simple_read_from_buffer(buf, len, ppos, data->buffer, size); + +out_unlock: + mutex_unlock(&data->lock); + return ret; +} + +static int kbase_jit_debugfs_common_release(struct inode *inode, + struct file *file) +{ + kfree(file->private_data); + return 0; +} + +#define KBASE_JIT_DEBUGFS_DECLARE(__fops, __func) \ +static int __fops ## _open(struct inode *inode, struct file *file) \ +{ \ + return kbase_jit_debugfs_common_open(inode, file, __func); \ +} \ +static const struct file_operations __fops = { \ + .owner = THIS_MODULE, \ + .open = __fops ## _open, \ + .release = kbase_jit_debugfs_common_release, \ + .read = kbase_jit_debugfs_common_read, \ + .write = NULL, \ + .llseek = generic_file_llseek, \ +} + +static int kbase_jit_debugfs_count_get(struct kbase_jit_debugfs_data *data) +{ + struct kbase_context *kctx = data->kctx; + struct list_head *tmp; + + mutex_lock(&kctx->jit_evict_lock); + list_for_each(tmp, &kctx->jit_active_head) { + data->active_value++; + } + + list_for_each(tmp, &kctx->jit_pool_head) { + data->pool_value++; + } + + list_for_each(tmp, &kctx->jit_destroy_head) { + data->destroy_value++; + } + mutex_unlock(&kctx->jit_evict_lock); + + return 0; +} +KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_count_fops, + kbase_jit_debugfs_count_get); + +static int kbase_jit_debugfs_vm_get(struct kbase_jit_debugfs_data *data) +{ + struct kbase_context *kctx = data->kctx; + struct kbase_va_region *reg; + + mutex_lock(&kctx->jit_evict_lock); + list_for_each_entry(reg, &kctx->jit_active_head, jit_node) { + data->active_value += reg->nr_pages; + } + + list_for_each_entry(reg, &kctx->jit_pool_head, jit_node) { + data->pool_value += reg->nr_pages; + } + + list_for_each_entry(reg, &kctx->jit_destroy_head, jit_node) { + data->destroy_value += reg->nr_pages; + } + mutex_unlock(&kctx->jit_evict_lock); + + return 0; +} +KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_vm_fops, + kbase_jit_debugfs_vm_get); + +static int kbase_jit_debugfs_phys_get(struct kbase_jit_debugfs_data *data) +{ + struct kbase_context *kctx = data->kctx; + struct kbase_va_region *reg; + + mutex_lock(&kctx->jit_evict_lock); + list_for_each_entry(reg, &kctx->jit_active_head, jit_node) { + data->active_value += reg->gpu_alloc->nents; + } + + list_for_each_entry(reg, &kctx->jit_pool_head, jit_node) { + data->pool_value += reg->gpu_alloc->nents; + } + + list_for_each_entry(reg, &kctx->jit_destroy_head, jit_node) { + data->destroy_value += reg->gpu_alloc->nents; + } + mutex_unlock(&kctx->jit_evict_lock); + + return 0; +} +KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_phys_fops, + kbase_jit_debugfs_phys_get); + +void kbase_jit_debugfs_init(struct kbase_context *kctx) +{ + /* Debugfs entry for getting the number of JIT allocations. */ + debugfs_create_file("mem_jit_count", S_IRUGO, kctx->kctx_dentry, + kctx, &kbase_jit_debugfs_count_fops); + + /* + * Debugfs entry for getting the total number of virtual pages + * used by JIT allocations. + */ + debugfs_create_file("mem_jit_vm", S_IRUGO, kctx->kctx_dentry, + kctx, &kbase_jit_debugfs_vm_fops); + + /* + * Debugfs entry for getting the number of physical pages used + * by JIT allocations. + */ + debugfs_create_file("mem_jit_phys", S_IRUGO, kctx->kctx_dentry, + kctx, &kbase_jit_debugfs_phys_fops); +} +#endif /* CONFIG_DEBUG_FS */ + +/** + * kbase_jit_destroy_worker - Deferred worker which frees JIT allocations + * @work: Work item + * + * This function does the work of freeing JIT allocations whose physical + * backing has been released. + */ +static void kbase_jit_destroy_worker(struct work_struct *work) +{ + struct kbase_context *kctx; + struct kbase_va_region *reg; + + kctx = container_of(work, struct kbase_context, jit_work); + do { + mutex_lock(&kctx->jit_evict_lock); + if (list_empty(&kctx->jit_destroy_head)) { + mutex_unlock(&kctx->jit_evict_lock); + break; + } + + reg = list_first_entry(&kctx->jit_destroy_head, + struct kbase_va_region, jit_node); + + list_del(®->jit_node); + mutex_unlock(&kctx->jit_evict_lock); + + kbase_gpu_vm_lock(kctx); + kbase_mem_free_region(kctx, reg); + kbase_gpu_vm_unlock(kctx); + } while (1); +} + +int kbase_jit_init(struct kbase_context *kctx) +{ + INIT_LIST_HEAD(&kctx->jit_active_head); + INIT_LIST_HEAD(&kctx->jit_pool_head); + INIT_LIST_HEAD(&kctx->jit_destroy_head); + INIT_WORK(&kctx->jit_work, kbase_jit_destroy_worker); + + INIT_LIST_HEAD(&kctx->jit_pending_alloc); + INIT_LIST_HEAD(&kctx->jit_atoms_head); + + return 0; +} + +struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, + struct base_jit_alloc_info *info) +{ + struct kbase_va_region *reg = NULL; + struct kbase_va_region *walker; + struct kbase_va_region *temp; + size_t current_diff = SIZE_MAX; + + int ret; + + mutex_lock(&kctx->jit_evict_lock); + /* + * Scan the pool for an existing allocation which meets our + * requirements and remove it. + */ + list_for_each_entry_safe(walker, temp, &kctx->jit_pool_head, jit_node) { + + if (walker->nr_pages >= info->va_pages) { + size_t min_size, max_size, diff; + + /* + * The JIT allocations VA requirements have been + * meet, it's suitable but other allocations + * might be a better fit. + */ + min_size = min_t(size_t, walker->gpu_alloc->nents, + info->commit_pages); + max_size = max_t(size_t, walker->gpu_alloc->nents, + info->commit_pages); + diff = max_size - min_size; + + if (current_diff > diff) { + current_diff = diff; + reg = walker; + } + + /* The allocation is an exact match, stop looking */ + if (current_diff == 0) + break; + } + } + + if (reg) { + /* + * Remove the found region from the pool and add it to the + * active list. + */ + list_move(®->jit_node, &kctx->jit_active_head); + + /* + * Remove the allocation from the eviction list as it's no + * longer eligible for eviction. This must be done before + * dropping the jit_evict_lock + */ + list_del_init(®->gpu_alloc->evict_node); + mutex_unlock(&kctx->jit_evict_lock); + + kbase_gpu_vm_lock(kctx); + + /* Make the physical backing no longer reclaimable */ + if (!kbase_mem_evictable_unmake(reg->gpu_alloc)) + goto update_failed; + + /* Grow the backing if required */ + if (reg->gpu_alloc->nents < info->commit_pages) { + size_t delta; + size_t old_size = reg->gpu_alloc->nents; + + /* Allocate some more pages */ + delta = info->commit_pages - reg->gpu_alloc->nents; + if (kbase_alloc_phy_pages_helper(reg->gpu_alloc, delta) + != 0) + goto update_failed; + + if (reg->cpu_alloc != reg->gpu_alloc) { + if (kbase_alloc_phy_pages_helper( + reg->cpu_alloc, delta) != 0) { + kbase_free_phy_pages_helper( + reg->gpu_alloc, delta); + goto update_failed; + } + } + + ret = kbase_mem_grow_gpu_mapping(kctx, reg, + info->commit_pages, old_size); + /* + * The grow failed so put the allocation back in the + * pool and return failure. + */ + if (ret) + goto update_failed; + } + kbase_gpu_vm_unlock(kctx); + } else { + /* No suitable JIT allocation was found so create a new one */ + u64 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | + BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF | + BASE_MEM_COHERENT_LOCAL; + u64 gpu_addr; + + mutex_unlock(&kctx->jit_evict_lock); + + reg = kbase_mem_alloc(kctx, info->va_pages, info->commit_pages, + info->extent, &flags, &gpu_addr); + if (!reg) + goto out_unlocked; + + mutex_lock(&kctx->jit_evict_lock); + list_add(®->jit_node, &kctx->jit_active_head); + mutex_unlock(&kctx->jit_evict_lock); + } + + return reg; + +update_failed: + /* + * An update to an allocation from the pool failed, chances + * are slim a new allocation would fair any better so return + * the allocation to the pool and return the function with failure. + */ + kbase_gpu_vm_unlock(kctx); + mutex_lock(&kctx->jit_evict_lock); + list_move(®->jit_node, &kctx->jit_pool_head); + mutex_unlock(&kctx->jit_evict_lock); +out_unlocked: + return NULL; +} + +void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + /* The physical backing of memory in the pool is always reclaimable */ + kbase_gpu_vm_lock(kctx); + kbase_mem_evictable_make(reg->gpu_alloc); + kbase_gpu_vm_unlock(kctx); + + mutex_lock(&kctx->jit_evict_lock); + list_move(®->jit_node, &kctx->jit_pool_head); + mutex_unlock(&kctx->jit_evict_lock); +} + +void kbase_jit_backing_lost(struct kbase_va_region *reg) +{ + struct kbase_context *kctx = reg->kctx; + + lockdep_assert_held(&kctx->jit_evict_lock); + + /* + * JIT allocations will always be on a list, if the region + * is not on a list then it's not a JIT allocation. + */ + if (list_empty(®->jit_node)) + return; + + /* + * Freeing the allocation requires locks we might not be able + * to take now, so move the allocation to the free list and kick + * the worker which will do the freeing. + */ + list_move(®->jit_node, &kctx->jit_destroy_head); + + schedule_work(&kctx->jit_work); +} + +bool kbase_jit_evict(struct kbase_context *kctx) +{ + struct kbase_va_region *reg = NULL; + + lockdep_assert_held(&kctx->reg_lock); + + /* Free the oldest allocation from the pool */ + mutex_lock(&kctx->jit_evict_lock); + if (!list_empty(&kctx->jit_pool_head)) { + reg = list_entry(kctx->jit_pool_head.prev, + struct kbase_va_region, jit_node); + list_del(®->jit_node); + } + mutex_unlock(&kctx->jit_evict_lock); + + if (reg) + kbase_mem_free_region(kctx, reg); + + return (reg != NULL); +} + +void kbase_jit_term(struct kbase_context *kctx) +{ + struct kbase_va_region *walker; + + /* Free all allocations for this context */ + + /* + * Flush the freeing of allocations whose backing has been freed + * (i.e. everything in jit_destroy_head). + */ + cancel_work_sync(&kctx->jit_work); + + kbase_gpu_vm_lock(kctx); + mutex_lock(&kctx->jit_evict_lock); + /* Free all allocations from the pool */ + while (!list_empty(&kctx->jit_pool_head)) { + walker = list_first_entry(&kctx->jit_pool_head, + struct kbase_va_region, jit_node); + list_del(&walker->jit_node); + mutex_unlock(&kctx->jit_evict_lock); + kbase_mem_free_region(kctx, walker); + mutex_lock(&kctx->jit_evict_lock); + } + + /* Free all allocations from active list */ + while (!list_empty(&kctx->jit_active_head)) { + walker = list_first_entry(&kctx->jit_active_head, + struct kbase_va_region, jit_node); + list_del(&walker->jit_node); + mutex_unlock(&kctx->jit_evict_lock); + kbase_mem_free_region(kctx, walker); + mutex_lock(&kctx->jit_evict_lock); + } + mutex_unlock(&kctx->jit_evict_lock); + kbase_gpu_vm_unlock(kctx); +} + +static int kbase_jd_user_buf_map(struct kbase_context *kctx, + struct kbase_va_region *reg) +{ + long pinned_pages; + struct kbase_mem_phy_alloc *alloc; + struct page **pages; + struct tagged_addr *pa; + long i; + int err = -ENOMEM; + unsigned long address; + struct mm_struct *mm; + struct device *dev; + unsigned long offset; + unsigned long local_size; + + alloc = reg->gpu_alloc; + pa = kbase_get_gpu_phy_pages(reg); + address = alloc->imported.user_buf.address; + mm = alloc->imported.user_buf.mm; + + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF); + + pages = alloc->imported.user_buf.pages; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) + pinned_pages = get_user_pages(NULL, mm, + address, + alloc->imported.user_buf.nr_pages, + reg->flags & KBASE_REG_GPU_WR, + 0, pages, NULL); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + pinned_pages = get_user_pages_remote(NULL, mm, + address, + alloc->imported.user_buf.nr_pages, + reg->flags & KBASE_REG_GPU_WR, + 0, pages, NULL); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) + pinned_pages = get_user_pages_remote(NULL, mm, + address, + alloc->imported.user_buf.nr_pages, + reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, + pages, NULL); +#else + pinned_pages = get_user_pages_remote(NULL, mm, + address, + alloc->imported.user_buf.nr_pages, + reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, + pages, NULL, NULL); +#endif + + if (pinned_pages <= 0) + return pinned_pages; + + if (pinned_pages != alloc->imported.user_buf.nr_pages) { + for (i = 0; i < pinned_pages; i++) + put_page(pages[i]); + return -ENOMEM; + } + + dev = kctx->kbdev->dev; + offset = address & ~PAGE_MASK; + local_size = alloc->imported.user_buf.size; + + for (i = 0; i < pinned_pages; i++) { + dma_addr_t dma_addr; + unsigned long min; + + min = MIN(PAGE_SIZE - offset, local_size); + dma_addr = dma_map_page(dev, pages[i], + offset, min, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) + goto unwind; + + alloc->imported.user_buf.dma_addrs[i] = dma_addr; + pa[i] = as_tagged(page_to_phys(pages[i])); + + local_size -= min; + offset = 0; + } + + alloc->nents = pinned_pages; + + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, pa, + kbase_reg_current_backed_size(reg), + reg->flags); + if (err == 0) + return 0; + + alloc->nents = 0; + /* fall down */ +unwind: + while (i--) { + dma_unmap_page(kctx->kbdev->dev, + alloc->imported.user_buf.dma_addrs[i], + PAGE_SIZE, DMA_BIDIRECTIONAL); + } + + while (++i < pinned_pages) { + put_page(pages[i]); + pages[i] = NULL; + } + + return err; +} + +static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, + struct kbase_mem_phy_alloc *alloc, bool writeable) +{ + long i; + struct page **pages; + unsigned long size = alloc->imported.user_buf.size; + + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF); + pages = alloc->imported.user_buf.pages; + for (i = 0; i < alloc->imported.user_buf.nr_pages; i++) { + unsigned long local_size; + dma_addr_t dma_addr = alloc->imported.user_buf.dma_addrs[i]; + + local_size = MIN(size, PAGE_SIZE - (dma_addr & ~PAGE_MASK)); + dma_unmap_page(kctx->kbdev->dev, dma_addr, local_size, + DMA_BIDIRECTIONAL); + if (writeable) + set_page_dirty_lock(pages[i]); + put_page(pages[i]); + pages[i] = NULL; + + size -= local_size; + } + alloc->nents = 0; +} + +#ifdef CONFIG_DMA_SHARED_BUFFER +static int kbase_jd_umm_map(struct kbase_context *kctx, + struct kbase_va_region *reg) +{ + struct sg_table *sgt; + struct scatterlist *s; + int i; + struct tagged_addr *pa; + int err; + size_t count = 0; + struct kbase_mem_phy_alloc *alloc; + + alloc = reg->gpu_alloc; + + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM); + KBASE_DEBUG_ASSERT(NULL == alloc->imported.umm.sgt); + sgt = dma_buf_map_attachment(alloc->imported.umm.dma_attachment, + DMA_BIDIRECTIONAL); + + if (IS_ERR_OR_NULL(sgt)) + return -EINVAL; + + /* save for later */ + alloc->imported.umm.sgt = sgt; + + pa = kbase_get_gpu_phy_pages(reg); + KBASE_DEBUG_ASSERT(pa); + + for_each_sg(sgt->sgl, s, sgt->nents, i) { + size_t j, pages = PFN_UP(sg_dma_len(s)); + + WARN_ONCE(sg_dma_len(s) & (PAGE_SIZE-1), + "sg_dma_len(s)=%u is not a multiple of PAGE_SIZE\n", + sg_dma_len(s)); + + WARN_ONCE(sg_dma_address(s) & (PAGE_SIZE-1), + "sg_dma_address(s)=%llx is not aligned to PAGE_SIZE\n", + (unsigned long long) sg_dma_address(s)); + + for (j = 0; (j < pages) && (count < reg->nr_pages); j++, + count++) + *pa++ = as_tagged(sg_dma_address(s) + + (j << PAGE_SHIFT)); + WARN_ONCE(j < pages, + "sg list from dma_buf_map_attachment > dma_buf->size=%zu\n", + alloc->imported.umm.dma_buf->size); + } + + if (!(reg->flags & KBASE_REG_IMPORT_PAD) && + WARN_ONCE(count < reg->nr_pages, + "sg list from dma_buf_map_attachment < dma_buf->size=%zu\n", + alloc->imported.umm.dma_buf->size)) { + err = -EINVAL; + goto err_unmap_attachment; + } + + /* Update nents as we now have pages to map */ + alloc->nents = reg->nr_pages; + + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, + kbase_get_gpu_phy_pages(reg), + count, + reg->flags | KBASE_REG_GPU_WR | KBASE_REG_GPU_RD); + if (err) + goto err_unmap_attachment; + + if (reg->flags & KBASE_REG_IMPORT_PAD) { + err = kbase_mmu_insert_single_page(kctx, + reg->start_pfn + count, + kctx->aliasing_sink_page, + reg->nr_pages - count, + (reg->flags | KBASE_REG_GPU_RD) & + ~KBASE_REG_GPU_WR); + if (err) + goto err_teardown_orig_pages; + } + + return 0; + +err_teardown_orig_pages: + kbase_mmu_teardown_pages(kctx, reg->start_pfn, count); +err_unmap_attachment: + dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment, + alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + alloc->imported.umm.sgt = NULL; + + return err; +} + +static void kbase_jd_umm_unmap(struct kbase_context *kctx, + struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->imported.umm.dma_attachment); + KBASE_DEBUG_ASSERT(alloc->imported.umm.sgt); + dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment, + alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + alloc->imported.umm.sgt = NULL; + alloc->nents = 0; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +#if (defined(CONFIG_KDS) && defined(CONFIG_UMP)) \ + || defined(CONFIG_DMA_SHARED_BUFFER_USES_KDS) +static void add_kds_resource(struct kds_resource *kds_res, + struct kds_resource **kds_resources, u32 *kds_res_count, + unsigned long *kds_access_bitmap, bool exclusive) +{ + u32 i; + + for (i = 0; i < *kds_res_count; i++) { + /* Duplicate resource, ignore */ + if (kds_resources[i] == kds_res) + return; + } + + kds_resources[*kds_res_count] = kds_res; + if (exclusive) + set_bit(*kds_res_count, kds_access_bitmap); + (*kds_res_count)++; +} +#endif + +struct kbase_mem_phy_alloc *kbase_map_external_resource( + struct kbase_context *kctx, struct kbase_va_region *reg, + struct mm_struct *locked_mm +#ifdef CONFIG_KDS + , u32 *kds_res_count, struct kds_resource **kds_resources, + unsigned long *kds_access_bitmap, bool exclusive +#endif + ) +{ + int err; + + /* decide what needs to happen for this resource */ + switch (reg->gpu_alloc->type) { + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { + if (reg->gpu_alloc->imported.user_buf.mm != locked_mm) + goto exit; + + reg->gpu_alloc->imported.user_buf.current_mapping_usage_count++; + if (1 == reg->gpu_alloc->imported.user_buf.current_mapping_usage_count) { + err = kbase_jd_user_buf_map(kctx, reg); + if (err) { + reg->gpu_alloc->imported.user_buf.current_mapping_usage_count--; + goto exit; + } + } + } + break; + case KBASE_MEM_TYPE_IMPORTED_UMP: { +#if defined(CONFIG_KDS) && defined(CONFIG_UMP) + if (kds_res_count) { + struct kds_resource *kds_res; + + kds_res = ump_dd_kds_resource_get( + reg->gpu_alloc->imported.ump_handle); + if (kds_res) + add_kds_resource(kds_res, kds_resources, + kds_res_count, + kds_access_bitmap, exclusive); + } +#endif /*defined(CONFIG_KDS) && defined(CONFIG_UMP) */ + break; + } +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: { +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + if (kds_res_count) { + struct kds_resource *kds_res; + + kds_res = get_dma_buf_kds_resource( + reg->gpu_alloc->imported.umm.dma_buf); + if (kds_res) + add_kds_resource(kds_res, kds_resources, + kds_res_count, + kds_access_bitmap, exclusive); + } +#endif + reg->gpu_alloc->imported.umm.current_mapping_usage_count++; + if (1 == reg->gpu_alloc->imported.umm.current_mapping_usage_count) { + err = kbase_jd_umm_map(kctx, reg); + if (err) { + reg->gpu_alloc->imported.umm.current_mapping_usage_count--; + goto exit; + } + } + break; + } +#endif + default: + goto exit; + } + + return kbase_mem_phy_alloc_get(reg->gpu_alloc); +exit: + return NULL; +} + +void kbase_unmap_external_resource(struct kbase_context *kctx, + struct kbase_va_region *reg, struct kbase_mem_phy_alloc *alloc) +{ + switch (alloc->type) { +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: { + alloc->imported.umm.current_mapping_usage_count--; + + if (0 == alloc->imported.umm.current_mapping_usage_count) { + if (reg && reg->gpu_alloc == alloc) { + int err; + + err = kbase_mmu_teardown_pages( + kctx, + reg->start_pfn, + alloc->nents); + WARN_ON(err); + } + + kbase_jd_umm_unmap(kctx, alloc); + } + } + break; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { + alloc->imported.user_buf.current_mapping_usage_count--; + + if (0 == alloc->imported.user_buf.current_mapping_usage_count) { + bool writeable = true; + + if (reg && reg->gpu_alloc == alloc) + kbase_mmu_teardown_pages( + kctx, + reg->start_pfn, + kbase_reg_current_backed_size(reg)); + + if (reg && ((reg->flags & KBASE_REG_GPU_WR) == 0)) + writeable = false; + + kbase_jd_user_buf_unmap(kctx, alloc, writeable); + } + } + break; + default: + break; + } + kbase_mem_phy_alloc_put(alloc); +} + +struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( + struct kbase_context *kctx, u64 gpu_addr) +{ + struct kbase_ctx_ext_res_meta *meta = NULL; + struct kbase_ctx_ext_res_meta *walker; + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Walk the per context external resource metadata list for the + * metadata which matches the region which is being acquired. + */ + list_for_each_entry(walker, &kctx->ext_res_meta_head, ext_res_node) { + if (walker->gpu_addr == gpu_addr) { + meta = walker; + break; + } + } + + /* No metadata exists so create one. */ + if (!meta) { + struct kbase_va_region *reg; + + /* Find the region */ + reg = kbase_region_tracker_find_region_enclosing_address( + kctx, gpu_addr); + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) + goto failed; + + /* Allocate the metadata object */ + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + goto failed; + + /* + * Fill in the metadata object and acquire a reference + * for the physical resource. + */ + meta->alloc = kbase_map_external_resource(kctx, reg, NULL +#ifdef CONFIG_KDS + , NULL, NULL, + NULL, false +#endif + ); + + if (!meta->alloc) + goto fail_map; + + meta->gpu_addr = reg->start_pfn << PAGE_SHIFT; + + list_add(&meta->ext_res_node, &kctx->ext_res_meta_head); + } + + return meta; + +fail_map: + kfree(meta); +failed: + return NULL; +} + +bool kbase_sticky_resource_release(struct kbase_context *kctx, + struct kbase_ctx_ext_res_meta *meta, u64 gpu_addr) +{ + struct kbase_ctx_ext_res_meta *walker; + struct kbase_va_region *reg; + + lockdep_assert_held(&kctx->reg_lock); + + /* Search of the metadata if one isn't provided. */ + if (!meta) { + /* + * Walk the per context external resource metadata list for the + * metadata which matches the region which is being released. + */ + list_for_each_entry(walker, &kctx->ext_res_meta_head, + ext_res_node) { + if (walker->gpu_addr == gpu_addr) { + meta = walker; + break; + } + } + } + + /* No metadata so just return. */ + if (!meta) + return false; + + /* Drop the physical memory reference and free the metadata. */ + reg = kbase_region_tracker_find_region_enclosing_address( + kctx, + meta->gpu_addr); + + kbase_unmap_external_resource(kctx, reg, meta->alloc); + list_del(&meta->ext_res_node); + kfree(meta); + + return true; +} + +int kbase_sticky_resource_init(struct kbase_context *kctx) +{ + INIT_LIST_HEAD(&kctx->ext_res_meta_head); + + return 0; +} + +void kbase_sticky_resource_term(struct kbase_context *kctx) +{ + struct kbase_ctx_ext_res_meta *walker; + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Free any sticky resources which haven't been unmapped. + * + * Note: + * We don't care about refcounts at this point as no future + * references to the meta data will be made. + * Region termination would find these if we didn't free them + * here, but it's more efficient if we do the clean up here. + */ + while (!list_empty(&kctx->ext_res_meta_head)) { + walker = list_first_entry(&kctx->ext_res_meta_head, + struct kbase_ctx_ext_res_meta, ext_res_node); + + kbase_sticky_resource_release(kctx, walker, 0); + } +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.h b/drivers/gpu/arm/bifrost/mali_kbase_mem.h new file mode 100644 index 000000000000..820a9beeee78 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.h @@ -0,0 +1,1142 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.h + * Base kernel memory APIs + */ + +#ifndef _KBASE_MEM_H_ +#define _KBASE_MEM_H_ + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include +#ifdef CONFIG_KDS +#include +#endif /* CONFIG_KDS */ +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include "mali_base_kernel.h" +#include +#include "mali_kbase_pm.h" +#include "mali_kbase_defs.h" +#if defined(CONFIG_MALI_GATOR_SUPPORT) +#include "mali_kbase_gator.h" +#endif +/* Required for kbase_mem_evictable_unmake */ +#include "mali_kbase_mem_linux.h" + +/* Part of the workaround for uTLB invalid pages is to ensure we grow/shrink tmem by 4 pages at a time */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316 (2) /* round to 4 pages */ + +/* Part of the workaround for PRLAM-9630 requires us to grow/shrink memory by 8 pages. +The MMU reads in 8 page table entries from memory at a time, if we have more than one page fault within the same 8 pages and +page tables are updated accordingly, the MMU does not re-read the page table entries from memory for the subsequent page table +updates and generates duplicate page faults as the page table information used by the MMU is not valid. */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630 (3) /* round to 8 pages */ + +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2 (0) /* round to 1 page */ + +/* This must always be a power of 2 */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_8316 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_9630 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630) +/** + * A CPU mapping + */ +struct kbase_cpu_mapping { + struct list_head mappings_list; + struct kbase_mem_phy_alloc *alloc; + struct kbase_context *kctx; + struct kbase_va_region *region; + int count; + int free_on_close; +}; + +enum kbase_memory_type { + KBASE_MEM_TYPE_NATIVE, + KBASE_MEM_TYPE_IMPORTED_UMP, + KBASE_MEM_TYPE_IMPORTED_UMM, + KBASE_MEM_TYPE_IMPORTED_USER_BUF, + KBASE_MEM_TYPE_ALIAS, + KBASE_MEM_TYPE_TB, + KBASE_MEM_TYPE_RAW +}; + +/* internal structure, mirroring base_mem_aliasing_info, + * but with alloc instead of a gpu va (handle) */ +struct kbase_aliased { + struct kbase_mem_phy_alloc *alloc; /* NULL for special, non-NULL for native */ + u64 offset; /* in pages */ + u64 length; /* in pages */ +}; + +/** + * @brief Physical pages tracking object properties + */ +#define KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED (1ul << 0) +#define KBASE_MEM_PHY_ALLOC_LARGE (1ul << 1) + +/* physical pages tracking object. + * Set up to track N pages. + * N not stored here, the creator holds that info. + * This object only tracks how many elements are actually valid (present). + * Changing of nents or *pages should only happen if the kbase_mem_phy_alloc is not + * shared with another region or client. CPU mappings are OK to exist when changing, as + * long as the tracked mappings objects are updated as part of the change. + */ +struct kbase_mem_phy_alloc { + struct kref kref; /* number of users of this alloc */ + atomic_t gpu_mappings; + size_t nents; /* 0..N */ + struct tagged_addr *pages; /* N elements, only 0..nents are valid */ + + /* kbase_cpu_mappings */ + struct list_head mappings; + + /* Node used to store this allocation on the eviction list */ + struct list_head evict_node; + /* Physical backing size when the pages where evicted */ + size_t evicted; + /* + * Back reference to the region structure which created this + * allocation, or NULL if it has been freed. + */ + struct kbase_va_region *reg; + + /* type of buffer */ + enum kbase_memory_type type; + + unsigned long properties; + + struct list_head zone_cache; + + /* member in union valid based on @a type */ + union { +#ifdef CONFIG_UMP + ump_dd_handle ump_handle; +#endif /* CONFIG_UMP */ +#if defined(CONFIG_DMA_SHARED_BUFFER) + struct { + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + unsigned int current_mapping_usage_count; + struct sg_table *sgt; + } umm; +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ + struct { + u64 stride; + size_t nents; + struct kbase_aliased *aliased; + } alias; + /* Used by type = (KBASE_MEM_TYPE_NATIVE, KBASE_MEM_TYPE_TB) */ + struct kbase_context *kctx; + struct kbase_alloc_import_user_buf { + unsigned long address; + unsigned long size; + unsigned long nr_pages; + struct page **pages; + /* top bit (1<<31) of current_mapping_usage_count + * specifies that this import was pinned on import + * See PINNED_ON_IMPORT + */ + u32 current_mapping_usage_count; + struct mm_struct *mm; + dma_addr_t *dma_addrs; + } user_buf; + } imported; +}; + +/* The top bit of kbase_alloc_import_user_buf::current_mapping_usage_count is + * used to signify that a buffer was pinned when it was imported. Since the + * reference count is limited by the number of atoms that can be submitted at + * once there should be no danger of overflowing into this bit. + * Stealing the top bit also has the benefit that + * current_mapping_usage_count != 0 if and only if the buffer is mapped. + */ +#define PINNED_ON_IMPORT (1<<31) + +static inline void kbase_mem_phy_alloc_gpu_mapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + atomic_inc(&alloc->gpu_mappings); +} + +static inline void kbase_mem_phy_alloc_gpu_unmapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + if (0 > atomic_dec_return(&alloc->gpu_mappings)) { + pr_err("Mismatched %s:\n", __func__); + dump_stack(); + } +} + +/** + * kbase_mem_is_imported - Indicate whether a memory type is imported + * + * @type: the memory type + * + * Return: true if the memory type is imported, false otherwise + */ +static inline bool kbase_mem_is_imported(enum kbase_memory_type type) +{ + return (type == KBASE_MEM_TYPE_IMPORTED_UMP) || + (type == KBASE_MEM_TYPE_IMPORTED_UMM) || + (type == KBASE_MEM_TYPE_IMPORTED_USER_BUF); +} + +void kbase_mem_kref_free(struct kref *kref); + +int kbase_mem_init(struct kbase_device *kbdev); +void kbase_mem_halt(struct kbase_device *kbdev); +void kbase_mem_term(struct kbase_device *kbdev); + +static inline struct kbase_mem_phy_alloc *kbase_mem_phy_alloc_get(struct kbase_mem_phy_alloc *alloc) +{ + kref_get(&alloc->kref); + return alloc; +} + +static inline struct kbase_mem_phy_alloc *kbase_mem_phy_alloc_put(struct kbase_mem_phy_alloc *alloc) +{ + kref_put(&alloc->kref, kbase_mem_kref_free); + return NULL; +} + +/** + * A GPU memory region, and attributes for CPU mappings. + */ +struct kbase_va_region { + struct rb_node rblink; + struct list_head link; + + struct kbase_context *kctx; /* Backlink to base context */ + + u64 start_pfn; /* The PFN in GPU space */ + size_t nr_pages; + +/* Free region */ +#define KBASE_REG_FREE (1ul << 0) +/* CPU write access */ +#define KBASE_REG_CPU_WR (1ul << 1) +/* GPU write access */ +#define KBASE_REG_GPU_WR (1ul << 2) +/* No eXecute flag */ +#define KBASE_REG_GPU_NX (1ul << 3) +/* Is CPU cached? */ +#define KBASE_REG_CPU_CACHED (1ul << 4) +/* Is GPU cached? */ +#define KBASE_REG_GPU_CACHED (1ul << 5) + +#define KBASE_REG_GROWABLE (1ul << 6) +/* Can grow on pf? */ +#define KBASE_REG_PF_GROW (1ul << 7) + +/* Bit 8 is unused */ + +/* inner shareable coherency */ +#define KBASE_REG_SHARE_IN (1ul << 9) +/* inner & outer shareable coherency */ +#define KBASE_REG_SHARE_BOTH (1ul << 10) + +/* Space for 4 different zones */ +#define KBASE_REG_ZONE_MASK (3ul << 11) +#define KBASE_REG_ZONE(x) (((x) & 3) << 11) + +/* GPU read access */ +#define KBASE_REG_GPU_RD (1ul<<13) +/* CPU read access */ +#define KBASE_REG_CPU_RD (1ul<<14) + +/* Index of chosen MEMATTR for this region (0..7) */ +#define KBASE_REG_MEMATTR_MASK (7ul << 16) +#define KBASE_REG_MEMATTR_INDEX(x) (((x) & 7) << 16) +#define KBASE_REG_MEMATTR_VALUE(x) (((x) & KBASE_REG_MEMATTR_MASK) >> 16) + +#define KBASE_REG_SECURE (1ul << 19) + +#define KBASE_REG_DONT_NEED (1ul << 20) + +/* Imported buffer is padded? */ +#define KBASE_REG_IMPORT_PAD (1ul << 21) + +/* Bit 22 is reserved. + * + * Do not remove, use the next unreserved bit for new flags */ +#define KBASE_REG_RESERVED_BIT_22 (1ul << 22) + +#define KBASE_REG_ZONE_SAME_VA KBASE_REG_ZONE(0) + +/* only used with 32-bit clients */ +/* + * On a 32bit platform, custom VA should be wired from (4GB + shader region) + * to the VA limit of the GPU. Unfortunately, the Linux mmap() interface + * limits us to 2^32 pages (2^44 bytes, see mmap64 man page for reference). + * So we put the default limit to the maximum possible on Linux and shrink + * it down, if required by the GPU, during initialization. + */ + +/* + * Dedicated 16MB region for shader code: + * VA range 0x101000000-0x102000000 + */ +#define KBASE_REG_ZONE_EXEC KBASE_REG_ZONE(1) +#define KBASE_REG_ZONE_EXEC_BASE (0x101000000ULL >> PAGE_SHIFT) +#define KBASE_REG_ZONE_EXEC_SIZE ((16ULL * 1024 * 1024) >> PAGE_SHIFT) + +#define KBASE_REG_ZONE_CUSTOM_VA KBASE_REG_ZONE(2) +#define KBASE_REG_ZONE_CUSTOM_VA_BASE (KBASE_REG_ZONE_EXEC_BASE + KBASE_REG_ZONE_EXEC_SIZE) /* Starting after KBASE_REG_ZONE_EXEC */ +#define KBASE_REG_ZONE_CUSTOM_VA_SIZE (((1ULL << 44) >> PAGE_SHIFT) - KBASE_REG_ZONE_CUSTOM_VA_BASE) +/* end 32-bit clients only */ + + unsigned long flags; + + size_t extent; /* nr of pages alloc'd on PF */ + + struct kbase_mem_phy_alloc *cpu_alloc; /* the one alloc object we mmap to the CPU when mapping this region */ + struct kbase_mem_phy_alloc *gpu_alloc; /* the one alloc object we mmap to the GPU when mapping this region */ + + /* non-NULL if this memory object is a kds_resource */ + struct kds_resource *kds_res; + + /* List head used to store the region in the JIT allocation pool */ + struct list_head jit_node; +}; + +/* Common functions */ +static inline struct tagged_addr *kbase_get_cpu_phy_pages( + struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(reg->cpu_alloc); + KBASE_DEBUG_ASSERT(reg->gpu_alloc); + KBASE_DEBUG_ASSERT(reg->cpu_alloc->nents == reg->gpu_alloc->nents); + + return reg->cpu_alloc->pages; +} + +static inline struct tagged_addr *kbase_get_gpu_phy_pages( + struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(reg->cpu_alloc); + KBASE_DEBUG_ASSERT(reg->gpu_alloc); + KBASE_DEBUG_ASSERT(reg->cpu_alloc->nents == reg->gpu_alloc->nents); + + return reg->gpu_alloc->pages; +} + +static inline size_t kbase_reg_current_backed_size(struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(reg); + /* if no alloc object the backed size naturally is 0 */ + if (!reg->cpu_alloc) + return 0; + + KBASE_DEBUG_ASSERT(reg->cpu_alloc); + KBASE_DEBUG_ASSERT(reg->gpu_alloc); + KBASE_DEBUG_ASSERT(reg->cpu_alloc->nents == reg->gpu_alloc->nents); + + return reg->cpu_alloc->nents; +} + +#define KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD ((size_t)(4*1024)) /* size above which vmalloc is used over kmalloc */ + +static inline struct kbase_mem_phy_alloc *kbase_alloc_create(size_t nr_pages, enum kbase_memory_type type) +{ + struct kbase_mem_phy_alloc *alloc; + size_t alloc_size = sizeof(*alloc) + sizeof(*alloc->pages) * nr_pages; + size_t per_page_size = sizeof(*alloc->pages); + + /* Imported pages may have page private data already in use */ + if (type == KBASE_MEM_TYPE_IMPORTED_USER_BUF) { + alloc_size += nr_pages * + sizeof(*alloc->imported.user_buf.dma_addrs); + per_page_size += sizeof(*alloc->imported.user_buf.dma_addrs); + } + + /* + * Prevent nr_pages*per_page_size + sizeof(*alloc) from + * wrapping around. + */ + if (nr_pages > ((((size_t) -1) - sizeof(*alloc)) + / per_page_size)) + return ERR_PTR(-ENOMEM); + + /* Allocate based on the size to reduce internal fragmentation of vmem */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc = vzalloc(alloc_size); + else + alloc = kzalloc(alloc_size, GFP_KERNEL); + + if (!alloc) + return ERR_PTR(-ENOMEM); + + /* Store allocation method */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc->properties |= KBASE_MEM_PHY_ALLOC_LARGE; + + kref_init(&alloc->kref); + atomic_set(&alloc->gpu_mappings, 0); + alloc->nents = 0; + alloc->pages = (void *)(alloc + 1); + INIT_LIST_HEAD(&alloc->mappings); + alloc->type = type; + INIT_LIST_HEAD(&alloc->zone_cache); + + if (type == KBASE_MEM_TYPE_IMPORTED_USER_BUF) + alloc->imported.user_buf.dma_addrs = + (void *) (alloc->pages + nr_pages); + + return alloc; +} + +static inline int kbase_reg_prepare_native(struct kbase_va_region *reg, + struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(!reg->cpu_alloc); + KBASE_DEBUG_ASSERT(!reg->gpu_alloc); + KBASE_DEBUG_ASSERT(reg->flags & KBASE_REG_FREE); + + reg->cpu_alloc = kbase_alloc_create(reg->nr_pages, + KBASE_MEM_TYPE_NATIVE); + if (IS_ERR(reg->cpu_alloc)) + return PTR_ERR(reg->cpu_alloc); + else if (!reg->cpu_alloc) + return -ENOMEM; + reg->cpu_alloc->imported.kctx = kctx; + INIT_LIST_HEAD(®->cpu_alloc->evict_node); + if (kbase_ctx_flag(kctx, KCTX_INFINITE_CACHE) + && (reg->flags & KBASE_REG_CPU_CACHED)) { + reg->gpu_alloc = kbase_alloc_create(reg->nr_pages, + KBASE_MEM_TYPE_NATIVE); + reg->gpu_alloc->imported.kctx = kctx; + INIT_LIST_HEAD(®->gpu_alloc->evict_node); + } else { + reg->gpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); + } + + INIT_LIST_HEAD(®->jit_node); + reg->flags &= ~KBASE_REG_FREE; + return 0; +} + +static inline int kbase_atomic_add_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_add_return(num_pages, used_pages); +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +static inline int kbase_atomic_sub_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_sub_return(num_pages, used_pages); +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +/* + * Max size for kbdev memory pool (in pages) + */ +#define KBASE_MEM_POOL_MAX_SIZE_KBDEV (SZ_64M >> PAGE_SHIFT) + +/* + * Max size for kctx memory pool (in pages) + */ +#define KBASE_MEM_POOL_MAX_SIZE_KCTX (SZ_64M >> PAGE_SHIFT) + +/* + * The order required for a 2MB page allocation (2^order * 4KB = 2MB) + */ +#define KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER 9 + +/* + * The order required for a 4KB page allocation + */ +#define KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER 0 + +/** + * kbase_mem_pool_init - Create a memory pool for a kbase device + * @pool: Memory pool to initialize + * @max_size: Maximum number of free pages the pool can hold + * @order: Page order for physical page size (order=0=>4kB, order=9=>2MB) + * @kbdev: Kbase device where memory is used + * @next_pool: Pointer to the next pool or NULL. + * + * Allocations from @pool are in whole pages. Each @pool has a free list where + * pages can be quickly allocated from. The free list is initially empty and + * filled whenever pages are freed back to the pool. The number of free pages + * in the pool will in general not exceed @max_size, but the pool may in + * certain corner cases grow above @max_size. + * + * If @next_pool is not NULL, we will allocate from @next_pool before going to + * the kernel allocator. Similarily pages can spill over to @next_pool when + * @pool is full. Pages are zeroed before they spill over to another pool, to + * prevent leaking information between applications. + * + * A shrinker is registered so that Linux mm can reclaim pages from the pool as + * needed. + * + * Return: 0 on success, negative -errno on error + */ +int kbase_mem_pool_init(struct kbase_mem_pool *pool, + size_t max_size, + size_t order, + struct kbase_device *kbdev, + struct kbase_mem_pool *next_pool); + +/** + * kbase_mem_pool_term - Destroy a memory pool + * @pool: Memory pool to destroy + * + * Pages in the pool will spill over to @next_pool (if available) or freed to + * the kernel. + */ +void kbase_mem_pool_term(struct kbase_mem_pool *pool); + +/** + * kbase_mem_pool_alloc - Allocate a page from memory pool + * @pool: Memory pool to allocate from + * + * Allocations from the pool are made as follows: + * 1. If there are free pages in the pool, allocate a page from @pool. + * 2. Otherwise, if @next_pool is not NULL and has free pages, allocate a page + * from @next_pool. + * 3. Return NULL if no memory in the pool + * + * Return: Pointer to allocated page, or NULL if allocation failed. + */ +struct page *kbase_mem_pool_alloc(struct kbase_mem_pool *pool); + +/** + * kbase_mem_pool_free - Free a page to memory pool + * @pool: Memory pool where page should be freed + * @page: Page to free to the pool + * @dirty: Whether some of the page may be dirty in the cache. + * + * Pages are freed to the pool as follows: + * 1. If @pool is not full, add @page to @pool. + * 2. Otherwise, if @next_pool is not NULL and not full, add @page to + * @next_pool. + * 3. Finally, free @page to the kernel. + */ +void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *page, + bool dirty); + +/** + * kbase_mem_pool_alloc_pages - Allocate pages from memory pool + * @pool: Memory pool to allocate from + * @nr_pages: Number of pages to allocate + * @pages: Pointer to array where the physical address of the allocated + * pages will be stored. + * @partial_allowed: If fewer pages allocated is allowed + * + * Like kbase_mem_pool_alloc() but optimized for allocating many pages. + * + * Return: + * On success number of pages allocated (could be less than nr_pages if + * partial_allowed). + * On error an error code. + */ +int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_pages, + struct tagged_addr *pages, bool partial_allowed); + +/** + * kbase_mem_pool_free_pages - Free pages to memory pool + * @pool: Memory pool where pages should be freed + * @nr_pages: Number of pages to free + * @pages: Pointer to array holding the physical addresses of the pages to + * free. + * @dirty: Whether any pages may be dirty in the cache. + * @reclaimed: Whether the pages where reclaimable and thus should bypass + * the pool and go straight to the kernel. + * + * Like kbase_mem_pool_free() but optimized for freeing many pages. + */ +void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, + struct tagged_addr *pages, bool dirty, bool reclaimed); + +/** + * kbase_mem_pool_size - Get number of free pages in memory pool + * @pool: Memory pool to inspect + * + * Note: the size of the pool may in certain corner cases exceed @max_size! + * + * Return: Number of free pages in the pool + */ +static inline size_t kbase_mem_pool_size(struct kbase_mem_pool *pool) +{ + return ACCESS_ONCE(pool->cur_size); +} + +/** + * kbase_mem_pool_max_size - Get maximum number of free pages in memory pool + * @pool: Memory pool to inspect + * + * Return: Maximum number of free pages in the pool + */ +static inline size_t kbase_mem_pool_max_size(struct kbase_mem_pool *pool) +{ + return pool->max_size; +} + + +/** + * kbase_mem_pool_set_max_size - Set maximum number of free pages in memory pool + * @pool: Memory pool to inspect + * @max_size: Maximum number of free pages the pool can hold + * + * If @max_size is reduced, the pool will be shrunk to adhere to the new limit. + * For details see kbase_mem_pool_shrink(). + */ +void kbase_mem_pool_set_max_size(struct kbase_mem_pool *pool, size_t max_size); + +/** + * kbase_mem_pool_grow - Grow the pool + * @pool: Memory pool to grow + * @nr_to_grow: Number of pages to add to the pool + * + * Adds @nr_to_grow pages to the pool. Note that this may cause the pool to + * become larger than the maximum size specified. + * + * Returns: 0 on success, -ENOMEM if unable to allocate sufficent pages + */ +int kbase_mem_pool_grow(struct kbase_mem_pool *pool, size_t nr_to_grow); + +/** + * kbase_mem_pool_trim - Grow or shrink the pool to a new size + * @pool: Memory pool to trim + * @new_size: New number of pages in the pool + * + * If @new_size > @cur_size, fill the pool with new pages from the kernel, but + * not above the max_size for the pool. + * If @new_size < @cur_size, shrink the pool by freeing pages to the kernel. + */ +void kbase_mem_pool_trim(struct kbase_mem_pool *pool, size_t new_size); + +/** + * kbase_mem_alloc_page - Allocate a new page for a device + * @pool: Memory pool to allocate a page from + * + * Most uses should use kbase_mem_pool_alloc to allocate a page. However that + * function can fail in the event the pool is empty. + * + * Return: A new page or NULL if no memory + */ +struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool); + +int kbase_region_tracker_init(struct kbase_context *kctx); +int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages); +void kbase_region_tracker_term(struct kbase_context *kctx); + +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, u64 gpu_addr); + +/** + * @brief Check that a pointer is actually a valid region. + * + * Must be called with context lock held. + */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, u64 gpu_addr); + +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone); +void kbase_free_alloced_region(struct kbase_va_region *reg); +int kbase_add_va_region(struct kbase_context *kctx, struct kbase_va_region *reg, u64 addr, size_t nr_pages, size_t align); + +bool kbase_check_alloc_flags(unsigned long flags); +bool kbase_check_import_flags(unsigned long flags); + +/** + * kbase_update_region_flags - Convert user space flags to kernel region flags + * + * @kctx: kbase context + * @reg: The region to update the flags on + * @flags: The flags passed from user space + * + * The user space flag BASE_MEM_COHERENT_SYSTEM_REQUIRED will be rejected and + * this function will fail if the system does not support system coherency. + * + * Return: 0 if successful, -EINVAL if the flags are not supported + */ +int kbase_update_region_flags(struct kbase_context *kctx, + struct kbase_va_region *reg, unsigned long flags); + +void kbase_gpu_vm_lock(struct kbase_context *kctx); +void kbase_gpu_vm_unlock(struct kbase_context *kctx); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size); + +int kbase_mmu_init(struct kbase_context *kctx); +void kbase_mmu_term(struct kbase_context *kctx); + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx); +void kbase_mmu_free_pgd(struct kbase_context *kctx); +int kbase_mmu_insert_pages_no_flush(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags); +int kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags); +int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr phys, size_t nr, + unsigned long flags); + +int kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr); +int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags); + +/** + * @brief Register region and map it on the GPU. + * + * Call kbase_add_va_region() and map the region on the GPU. + */ +int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64 addr, size_t nr_pages, size_t align); + +/** + * @brief Remove the region from the GPU and unregister it. + * + * Must be called with context lock held. + */ +int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg); + +/** + * The caller has the following locking conditions: + * - It must hold kbase_device->mmu_hw_mutex + * - It must hold the hwaccess_lock + */ +void kbase_mmu_update(struct kbase_context *kctx); + +/** + * kbase_mmu_disable() - Disable the MMU for a previously active kbase context. + * @kctx: Kbase context + * + * Disable and perform the required cache maintenance to remove the all + * data from provided kbase context from the GPU caches. + * + * The caller has the following locking conditions: + * - It must hold kbase_device->mmu_hw_mutex + * - It must hold the hwaccess_lock + */ +void kbase_mmu_disable(struct kbase_context *kctx); + +/** + * kbase_mmu_disable_as() - Set the MMU to unmapped mode for the specified + * address space. + * @kbdev: Kbase device + * @as_nr: The address space number to set to unmapped. + * + * This function must only be called during reset/power-up and it used to + * ensure the registers are in a known state. + * + * The caller must hold kbdev->mmu_hw_mutex. + */ +void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr); + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +/** Dump the MMU tables to a buffer + * + * This function allocates a buffer (of @c nr_pages pages) to hold a dump of the MMU tables and fills it. If the + * buffer is too small then the return value will be NULL. + * + * The GPU vm lock must be held when calling this function. + * + * The buffer returned should be freed with @ref vfree when it is no longer required. + * + * @param[in] kctx The kbase context to dump + * @param[in] nr_pages The number of pages to allocate for the buffer. + * + * @return The address of the buffer containing the MMU dump or NULL on error (including if the @c nr_pages is too + * small) + */ +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages); + +/** + * kbase_sync_now - Perform cache maintenance on a memory region + * + * @kctx: The kbase context of the region + * @sset: A syncset structure describing the region and direction of the + * synchronisation required + * + * Return: 0 on success or error code + */ +int kbase_sync_now(struct kbase_context *kctx, struct basep_syncset *sset); +void kbase_sync_single(struct kbase_context *kctx, struct tagged_addr cpu_pa, + struct tagged_addr gpu_pa, off_t offset, size_t size, + enum kbase_sync_type sync_fn); +void kbase_pre_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); +void kbase_post_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); + +/* OS specific functions */ +int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr); +int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg); +void kbase_os_mem_map_lock(struct kbase_context *kctx); +void kbase_os_mem_map_unlock(struct kbase_context *kctx); + +/** + * @brief Update the memory allocation counters for the current process + * + * OS specific call to updates the current memory allocation counters for the current process with + * the supplied delta. + * + * @param[in] kctx The kbase context + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages); + +/** + * @brief Add to the memory allocation counters for the current process + * + * OS specific call to add to the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, pages); +} + +/** + * @brief Subtract from the memory allocation counters for the current process + * + * OS specific call to subtract from the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static inline void kbase_process_page_usage_dec(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, 0 - pages); +} + +/** + * kbasep_find_enclosing_cpu_mapping_offset() - Find the offset of the CPU + * mapping of a memory allocation containing a given address range + * + * Searches for a CPU mapping of any part of any region that fully encloses the + * CPU virtual address range specified by @uaddr and @size. Returns a failure + * indication if only part of the address range lies within a CPU mapping. + * + * @kctx: The kernel base context used for the allocation. + * @uaddr: Start of the CPU virtual address range. + * @size: Size of the CPU virtual address range (in bytes). + * @offset: The offset from the start of the allocation to the specified CPU + * virtual address. + * + * Return: 0 if offset was obtained successfully. Error code otherwise. + */ +int kbasep_find_enclosing_cpu_mapping_offset( + struct kbase_context *kctx, + unsigned long uaddr, size_t size, u64 *offset); + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer); +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** +* @brief Allocates physical pages. +* +* Allocates \a nr_pages_requested and updates the alloc object. +* +* @param[in] alloc allocation object to add pages to +* @param[in] nr_pages_requested number of physical pages to allocate +* +* @return 0 if all pages have been successfully allocated. Error code otherwise +*/ +int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pages_requested); + +/** +* @brief Free physical pages. +* +* Frees \a nr_pages and updates the alloc object. +* +* @param[in] alloc allocation object to free pages from +* @param[in] nr_pages_to_free number of physical pages to free +*/ +int kbase_free_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pages_to_free); + +static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr) +{ + SetPagePrivate(p); + if (sizeof(dma_addr_t) > sizeof(p->private)) { + /* on 32-bit ARM with LPAE dma_addr_t becomes larger, but the + * private field stays the same. So we have to be clever and + * use the fact that we only store DMA addresses of whole pages, + * so the low bits should be zero */ + KBASE_DEBUG_ASSERT(!(dma_addr & (PAGE_SIZE - 1))); + set_page_private(p, dma_addr >> PAGE_SHIFT); + } else { + set_page_private(p, dma_addr); + } +} + +static inline dma_addr_t kbase_dma_addr(struct page *p) +{ + if (sizeof(dma_addr_t) > sizeof(p->private)) + return ((dma_addr_t)page_private(p)) << PAGE_SHIFT; + + return (dma_addr_t)page_private(p); +} + +static inline void kbase_clear_dma_addr(struct page *p) +{ + ClearPagePrivate(p); +} + +/** +* @brief Process a bus or page fault. +* +* This function will process a fault on a specific address space +* +* @param[in] kbdev The @ref kbase_device the fault happened on +* @param[in] kctx The @ref kbase_context for the faulting address space if +* one was found. +* @param[in] as The address space that has the fault +*/ +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, + struct kbase_context *kctx, struct kbase_as *as); + +/** + * @brief Process a page fault. + * + * @param[in] data work_struct passed by queue_work() + */ +void page_fault_worker(struct work_struct *data); + +/** + * @brief Process a bus fault. + * + * @param[in] data work_struct passed by queue_work() + */ +void bus_fault_worker(struct work_struct *data); + +/** + * @brief Flush MMU workqueues. + * + * This function will cause any outstanding page or bus faults to be processed. + * It should be called prior to powering off the GPU. + * + * @param[in] kbdev Device pointer + */ +void kbase_flush_mmu_wqs(struct kbase_device *kbdev); + +/** + * kbase_sync_single_for_device - update physical memory and give GPU ownership + * @kbdev: Device pointer + * @handle: DMA address of region + * @size: Size of region to sync + * @dir: DMA data direction + */ + +void kbase_sync_single_for_device(struct kbase_device *kbdev, dma_addr_t handle, + size_t size, enum dma_data_direction dir); + +/** + * kbase_sync_single_for_cpu - update physical memory and give CPU ownership + * @kbdev: Device pointer + * @handle: DMA address of region + * @size: Size of region to sync + * @dir: DMA data direction + */ + +void kbase_sync_single_for_cpu(struct kbase_device *kbdev, dma_addr_t handle, + size_t size, enum dma_data_direction dir); + +#ifdef CONFIG_DEBUG_FS +/** + * kbase_jit_debugfs_init - Add per context debugfs entry for JIT. + * @kctx: kbase context + */ +void kbase_jit_debugfs_init(struct kbase_context *kctx); +#endif /* CONFIG_DEBUG_FS */ + +/** + * kbase_jit_init - Initialize the JIT memory pool management + * @kctx: kbase context + * + * Returns zero on success or negative error number on failure. + */ +int kbase_jit_init(struct kbase_context *kctx); + +/** + * kbase_jit_allocate - Allocate JIT memory + * @kctx: kbase context + * @info: JIT allocation information + * + * Return: JIT allocation on success or NULL on failure. + */ +struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, + struct base_jit_alloc_info *info); + +/** + * kbase_jit_free - Free a JIT allocation + * @kctx: kbase context + * @reg: JIT allocation + * + * Frees a JIT allocation and places it into the free pool for later reuse. + */ +void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg); + +/** + * kbase_jit_backing_lost - Inform JIT that an allocation has lost backing + * @reg: JIT allocation + */ +void kbase_jit_backing_lost(struct kbase_va_region *reg); + +/** + * kbase_jit_evict - Evict a JIT allocation from the pool + * @kctx: kbase context + * + * Evict the least recently used JIT allocation from the pool. This can be + * required if normal VA allocations are failing due to VA exhaustion. + * + * Return: True if a JIT allocation was freed, false otherwise. + */ +bool kbase_jit_evict(struct kbase_context *kctx); + +/** + * kbase_jit_term - Terminate the JIT memory pool management + * @kctx: kbase context + */ +void kbase_jit_term(struct kbase_context *kctx); + +/** + * kbase_map_external_resource - Map an external resource to the GPU. + * @kctx: kbase context. + * @reg: The region to map. + * @locked_mm: The mm_struct which has been locked for this operation. + * @kds_res_count: The number of KDS resources. + * @kds_resources: Array of KDS resources. + * @kds_access_bitmap: Access bitmap for KDS. + * @exclusive: If the KDS resource requires exclusive access. + * + * Return: The physical allocation which backs the region on success or NULL + * on failure. + */ +struct kbase_mem_phy_alloc *kbase_map_external_resource( + struct kbase_context *kctx, struct kbase_va_region *reg, + struct mm_struct *locked_mm +#ifdef CONFIG_KDS + , u32 *kds_res_count, struct kds_resource **kds_resources, + unsigned long *kds_access_bitmap, bool exclusive +#endif + ); + +/** + * kbase_unmap_external_resource - Unmap an external resource from the GPU. + * @kctx: kbase context. + * @reg: The region to unmap or NULL if it has already been released. + * @alloc: The physical allocation being unmapped. + */ +void kbase_unmap_external_resource(struct kbase_context *kctx, + struct kbase_va_region *reg, struct kbase_mem_phy_alloc *alloc); + +/** + * kbase_sticky_resource_init - Initialize sticky resource management. + * @kctx: kbase context + * + * Returns zero on success or negative error number on failure. + */ +int kbase_sticky_resource_init(struct kbase_context *kctx); + +/** + * kbase_sticky_resource_acquire - Acquire a reference on a sticky resource. + * @kctx: kbase context. + * @gpu_addr: The GPU address of the external resource. + * + * Return: The metadata object which represents the binding between the + * external resource and the kbase context on success or NULL on failure. + */ +struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( + struct kbase_context *kctx, u64 gpu_addr); + +/** + * kbase_sticky_resource_release - Release a reference on a sticky resource. + * @kctx: kbase context. + * @meta: Binding metadata. + * @gpu_addr: GPU address of the external resource. + * + * If meta is NULL then gpu_addr will be used to scan the metadata list and + * find the matching metadata (if any), otherwise the provided meta will be + * used and gpu_addr will be ignored. + * + * Return: True if the release found the metadata and the reference was dropped. + */ +bool kbase_sticky_resource_release(struct kbase_context *kctx, + struct kbase_ctx_ext_res_meta *meta, u64 gpu_addr); + +/** + * kbase_sticky_resource_term - Terminate sticky resource management. + * @kctx: kbase context + */ +void kbase_sticky_resource_term(struct kbase_context *kctx); + +/** + * kbase_zone_cache_update - Update the memory zone cache after new pages have + * been added. + * @alloc: The physical memory allocation to build the cache for. + * @start_offset: Offset to where the new pages start. + * + * Updates an existing memory zone cache, updating the counters for the + * various zones. + * If the memory allocation doesn't already have a zone cache assume that + * one isn't created and thus don't do anything. + * + * Return: Zero cache was updated, negative error code on error. + */ +int kbase_zone_cache_update(struct kbase_mem_phy_alloc *alloc, + size_t start_offset); + +/** + * kbase_zone_cache_build - Build the memory zone cache. + * @alloc: The physical memory allocation to build the cache for. + * + * Create a new zone cache for the provided physical memory allocation if + * one doesn't already exist, if one does exist then just return. + * + * Return: Zero if the zone cache was created, negative error code on error. + */ +int kbase_zone_cache_build(struct kbase_mem_phy_alloc *alloc); + +/** + * kbase_zone_cache_clear - Clear the memory zone cache. + * @alloc: The physical memory allocation to clear the cache on. + */ +void kbase_zone_cache_clear(struct kbase_mem_phy_alloc *alloc); + +#endif /* _KBASE_MEM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c new file mode 100644 index 000000000000..842444c9b0bd --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c @@ -0,0 +1,2678 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.c + * Base kernel memory APIs, Linux implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) +#include +#endif /* LINUX_VERSION_CODE >= 3.5.0 && < 4.8.0 */ +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ +#include +#include + +#include +#include +#include +#include + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma); + +/** + * kbase_mem_shrink_cpu_mapping - Shrink the CPU mapping(s) of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region + * @new_pages: The number of pages after the shrink + * @old_pages: The number of pages before the shrink + * + * Shrink (or completely remove) all CPU mappings which reference the shrunk + * part of the allocation. + * + * Note: Caller must be holding the processes mmap_sem lock. + */ +static void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + +/** + * kbase_mem_shrink_gpu_mapping - Shrink the GPU mapping of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region or NULL if there isn't one + * @new_pages: The number of pages after the shrink + * @old_pages: The number of pages before the shrink + * + * Return: 0 on success, negative -errno on error + * + * Unmap the shrunk pages from the GPU mapping. Note that the size of the region + * itself is unmodified as we still need to reserve the VA, only the page tables + * will be modified by this function. + */ +static int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + +struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, + u64 va_pages, u64 commit_pages, u64 extent, u64 *flags, + u64 *gpu_va) +{ + int zone; + int gpu_pc_bits; + struct kbase_va_region *reg; + struct device *dev; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(gpu_va); + + dev = kctx->kbdev->dev; + *gpu_va = 0; /* return 0 on failure */ + + gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + + if (0 == va_pages) { + dev_warn(dev, "kbase_mem_alloc called with 0 va_pages!"); + goto bad_size; + } + + if (va_pages > (U64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + if (!kbase_check_alloc_flags(*flags)) { + dev_warn(dev, + "kbase_mem_alloc called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + if ((*flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED) != 0 && + !kbase_device_is_cpu_coherent(kctx->kbdev)) { + dev_warn(dev, "kbase_mem_alloc call required coherent mem when unavailable"); + goto bad_flags; + } + if ((*flags & BASE_MEM_COHERENT_SYSTEM) != 0 && + !kbase_device_is_cpu_coherent(kctx->kbdev)) { + /* Remove COHERENT_SYSTEM flag if coherent mem is unavailable */ + *flags &= ~BASE_MEM_COHERENT_SYSTEM; + } + + /* Limit GPU executable allocs to GPU PC size */ + if ((*flags & BASE_MEM_PROT_GPU_EX) && + (va_pages > (1ULL << gpu_pc_bits >> PAGE_SHIFT))) + goto bad_ex_size; + + /* find out which VA zone to use */ + if (*flags & BASE_MEM_SAME_VA) + zone = KBASE_REG_ZONE_SAME_VA; + else if (*flags & BASE_MEM_PROT_GPU_EX) + zone = KBASE_REG_ZONE_EXEC; + else + zone = KBASE_REG_ZONE_CUSTOM_VA; + + reg = kbase_alloc_free_region(kctx, 0, va_pages, zone); + if (!reg) { + dev_err(dev, "Failed to allocate free region"); + goto no_region; + } + + if (kbase_update_region_flags(kctx, reg, *flags) != 0) + goto invalid_flags; + + if (kbase_reg_prepare_native(reg, kctx) != 0) { + dev_err(dev, "Failed to prepare region"); + goto prepare_failed; + } + + if (*flags & BASE_MEM_GROW_ON_GPF) + reg->extent = extent; + else + reg->extent = 0; + + if (kbase_alloc_phy_pages(reg, va_pages, commit_pages) != 0) { + dev_warn(dev, "Failed to allocate %lld pages (va_pages=%lld)", + (unsigned long long)commit_pages, + (unsigned long long)va_pages); + goto no_mem; + } + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & BASE_MEM_SAME_VA) { + unsigned long prot = PROT_NONE; + unsigned long va_size = va_pages << PAGE_SHIFT; + unsigned long va_map = va_size; + unsigned long cookie, cookie_nr; + unsigned long cpu_addr; + + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(dev, "No cookies available for allocation!"); + kbase_gpu_vm_unlock(kctx); + goto no_cookie; + } + /* return a cookie */ + cookie_nr = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << cookie_nr); + BUG_ON(kctx->pending_regions[cookie_nr]); + kctx->pending_regions[cookie_nr] = reg; + + kbase_gpu_vm_unlock(kctx); + + /* relocate to correct base */ + cookie = cookie_nr + PFN_DOWN(BASE_MEM_COOKIE_BASE); + cookie <<= PAGE_SHIFT; + + /* + * 10.1-10.4 UKU userland relies on the kernel to call mmap. + * For all other versions we can just return the cookie + */ + if (kctx->api_version < KBASE_API_VERSION(10, 1) || + kctx->api_version > KBASE_API_VERSION(10, 4)) { + *gpu_va = (u64) cookie; + return reg; + } + if (*flags & BASE_MEM_PROT_CPU_RD) + prot |= PROT_READ; + if (*flags & BASE_MEM_PROT_CPU_WR) + prot |= PROT_WRITE; + + cpu_addr = vm_mmap(kctx->filp, 0, va_map, prot, + MAP_SHARED, cookie); + + if (IS_ERR_VALUE(cpu_addr)) { + kbase_gpu_vm_lock(kctx); + kctx->pending_regions[cookie_nr] = NULL; + kctx->cookies |= (1UL << cookie_nr); + kbase_gpu_vm_unlock(kctx); + goto no_mmap; + } + + *gpu_va = (u64) cpu_addr; + } else /* we control the VA */ { + if (kbase_gpu_mmap(kctx, reg, 0, va_pages, 1) != 0) { + dev_warn(dev, "Failed to map memory on GPU"); + kbase_gpu_vm_unlock(kctx); + goto no_mmap; + } + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + + kbase_gpu_vm_unlock(kctx); + } + + return reg; + +no_mmap: +no_cookie: +no_mem: + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); +invalid_flags: +prepare_failed: + kfree(reg); +no_region: +bad_ex_size: +bad_flags: +bad_size: + return NULL; +} +KBASE_EXPORT_TEST_API(kbase_mem_alloc); + +int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, int query, u64 * const out) +{ + struct kbase_va_region *reg; + int ret = -EINVAL; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(out); + + if (gpu_addr & ~PAGE_MASK) { + dev_warn(kctx->kbdev->dev, "mem_query: gpu_addr: passed parameter is invalid"); + return -EINVAL; + } + + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + switch (query) { + case KBASE_MEM_QUERY_COMMIT_SIZE: + if (reg->cpu_alloc->type != KBASE_MEM_TYPE_ALIAS) { + *out = kbase_reg_current_backed_size(reg); + } else { + size_t i; + struct kbase_aliased *aliased; + *out = 0; + aliased = reg->cpu_alloc->imported.alias.aliased; + for (i = 0; i < reg->cpu_alloc->imported.alias.nents; i++) + *out += aliased[i].length; + } + break; + case KBASE_MEM_QUERY_VA_SIZE: + *out = reg->nr_pages; + break; + case KBASE_MEM_QUERY_FLAGS: + { + *out = 0; + if (KBASE_REG_CPU_WR & reg->flags) + *out |= BASE_MEM_PROT_CPU_WR; + if (KBASE_REG_CPU_RD & reg->flags) + *out |= BASE_MEM_PROT_CPU_RD; + if (KBASE_REG_CPU_CACHED & reg->flags) + *out |= BASE_MEM_CACHED_CPU; + if (KBASE_REG_GPU_WR & reg->flags) + *out |= BASE_MEM_PROT_GPU_WR; + if (KBASE_REG_GPU_RD & reg->flags) + *out |= BASE_MEM_PROT_GPU_RD; + if (!(KBASE_REG_GPU_NX & reg->flags)) + *out |= BASE_MEM_PROT_GPU_EX; + if (KBASE_REG_SHARE_BOTH & reg->flags) + *out |= BASE_MEM_COHERENT_SYSTEM; + if (KBASE_REG_SHARE_IN & reg->flags) + *out |= BASE_MEM_COHERENT_LOCAL; + break; + } + default: + *out = 0; + goto out_unlock; + } + + ret = 0; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return ret; +} + +/** + * kbase_mem_evictable_reclaim_count_objects - Count number of pages in the + * Ephemeral memory eviction list. + * @s: Shrinker + * @sc: Shrinker control + * + * Return: Number of pages which can be freed. + */ +static +unsigned long kbase_mem_evictable_reclaim_count_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_context *kctx; + struct kbase_mem_phy_alloc *alloc; + unsigned long pages = 0; + + kctx = container_of(s, struct kbase_context, reclaim); + + mutex_lock(&kctx->jit_evict_lock); + + list_for_each_entry(alloc, &kctx->evict_list, evict_node) + pages += alloc->nents; + + mutex_unlock(&kctx->jit_evict_lock); + return pages; +} + +/** + * kbase_mem_evictable_reclaim_scan_objects - Scan the Ephemeral memory eviction + * list for pages and try to reclaim them. + * @s: Shrinker + * @sc: Shrinker control + * + * Return: Number of pages freed (can be less then requested) or -1 if the + * shrinker failed to free pages in its pool. + * + * Note: + * This function accesses region structures without taking the region lock, + * this is required as the OOM killer can call the shrinker after the region + * lock has already been held. + * This is safe as we can guarantee that a region on the eviction list will + * not be freed (kbase_mem_free_region removes the allocation from the list + * before destroying it), or modified by other parts of the driver. + * The eviction list itself is guarded by the eviction lock and the MMU updates + * are protected by their own lock. + */ +static +unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_context *kctx; + struct kbase_mem_phy_alloc *alloc; + struct kbase_mem_phy_alloc *tmp; + unsigned long freed = 0; + + kctx = container_of(s, struct kbase_context, reclaim); + mutex_lock(&kctx->jit_evict_lock); + + list_for_each_entry_safe(alloc, tmp, &kctx->evict_list, evict_node) { + int err; + + err = kbase_mem_shrink_gpu_mapping(kctx, alloc->reg, + 0, alloc->nents); + if (err != 0) { + /* + * Failed to remove GPU mapping, tell the shrinker + * to stop trying to shrink our slab even though we + * have pages in it. + */ + freed = -1; + goto out_unlock; + } + + /* + * Update alloc->evicted before freeing the backing so the + * helper can determine that it needs to bypass the accounting + * and memory pool. + */ + alloc->evicted = alloc->nents; + + kbase_free_phy_pages_helper(alloc, alloc->evicted); + freed += alloc->evicted; + list_del_init(&alloc->evict_node); + + /* + * Inform the JIT allocator this region has lost backing + * as it might need to free the allocation. + */ + kbase_jit_backing_lost(alloc->reg); + + /* Enough pages have been freed so stop now */ + if (freed > sc->nr_to_scan) + break; + } +out_unlock: + mutex_unlock(&kctx->jit_evict_lock); + + return freed; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) +static int kbase_mem_evictable_reclaim_shrink(struct shrinker *s, + struct shrink_control *sc) +{ + if (sc->nr_to_scan == 0) + return kbase_mem_evictable_reclaim_count_objects(s, sc); + + return kbase_mem_evictable_reclaim_scan_objects(s, sc); +} +#endif + +int kbase_mem_evictable_init(struct kbase_context *kctx) +{ + INIT_LIST_HEAD(&kctx->evict_list); + mutex_init(&kctx->jit_evict_lock); + + /* Register shrinker */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) + kctx->reclaim.shrink = kbase_mem_evictable_reclaim_shrink; +#else + kctx->reclaim.count_objects = kbase_mem_evictable_reclaim_count_objects; + kctx->reclaim.scan_objects = kbase_mem_evictable_reclaim_scan_objects; +#endif + kctx->reclaim.seeks = DEFAULT_SEEKS; + /* Kernel versions prior to 3.1 : + * struct shrinker does not define batch */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) + kctx->reclaim.batch = 0; +#endif + register_shrinker(&kctx->reclaim); + return 0; +} + +void kbase_mem_evictable_deinit(struct kbase_context *kctx) +{ + unregister_shrinker(&kctx->reclaim); +} + +struct kbase_mem_zone_cache_entry { + /* List head used to link the cache entry to the memory allocation. */ + struct list_head zone_node; + /* The zone the cacheline is for. */ + struct zone *zone; + /* The number of pages in the allocation which belong to this zone. */ + u64 count; +}; + +static bool kbase_zone_cache_builder(struct kbase_mem_phy_alloc *alloc, + size_t start_offset) +{ + struct kbase_mem_zone_cache_entry *cache = NULL; + size_t i; + int ret = 0; + + for (i = start_offset; i < alloc->nents; i++) { + struct page *p = phys_to_page(as_phys_addr_t(alloc->pages[i])); + struct zone *zone = page_zone(p); + bool create = true; + + if (cache && (cache->zone == zone)) { + /* + * Fast path check as most of the time adjacent + * pages come from the same zone. + */ + create = false; + } else { + /* + * Slow path check, walk all the cache entries to see + * if we already know about this zone. + */ + list_for_each_entry(cache, &alloc->zone_cache, zone_node) { + if (cache->zone == zone) { + create = false; + break; + } + } + } + + /* This zone wasn't found in the cache, create an entry for it */ + if (create) { + cache = kmalloc(sizeof(*cache), GFP_KERNEL); + if (!cache) { + ret = -ENOMEM; + goto bail; + } + cache->zone = zone; + cache->count = 0; + list_add(&cache->zone_node, &alloc->zone_cache); + } + + cache->count++; + } + return 0; + +bail: + return ret; +} + +int kbase_zone_cache_update(struct kbase_mem_phy_alloc *alloc, + size_t start_offset) +{ + /* + * Bail if the zone cache is empty, only update the cache if it + * existed in the first place. + */ + if (list_empty(&alloc->zone_cache)) + return 0; + + return kbase_zone_cache_builder(alloc, start_offset); +} + +int kbase_zone_cache_build(struct kbase_mem_phy_alloc *alloc) +{ + /* Bail if the zone cache already exists */ + if (!list_empty(&alloc->zone_cache)) + return 0; + + return kbase_zone_cache_builder(alloc, 0); +} + +void kbase_zone_cache_clear(struct kbase_mem_phy_alloc *alloc) +{ + struct kbase_mem_zone_cache_entry *walker; + + while(!list_empty(&alloc->zone_cache)){ + walker = list_first_entry(&alloc->zone_cache, + struct kbase_mem_zone_cache_entry, zone_node); + list_del(&walker->zone_node); + kfree(walker); + } +} + +/** + * kbase_mem_evictable_mark_reclaim - Mark the pages as reclaimable. + * @alloc: The physical allocation + */ +static void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc) +{ + struct kbase_context *kctx = alloc->imported.kctx; + struct kbase_mem_zone_cache_entry *zone_cache; + int __maybe_unused new_page_count; + int err; + + /* Attempt to build a zone cache of tracking */ + err = kbase_zone_cache_build(alloc); + if (err == 0) { + /* Bulk update all the zones */ + list_for_each_entry(zone_cache, &alloc->zone_cache, zone_node) { + zone_page_state_add(zone_cache->count, + zone_cache->zone, NR_SLAB_RECLAIMABLE); + } + } else { + /* Fall-back to page by page updates */ + int i; + + for (i = 0; i < alloc->nents; i++) { + struct page *p; + struct zone *zone; + + p = phys_to_page(as_phys_addr_t(alloc->pages[i])); + zone = page_zone(p); + + zone_page_state_add(1, zone, NR_SLAB_RECLAIMABLE); + } + } + + kbase_process_page_usage_dec(kctx, alloc->nents); + new_page_count = kbase_atomic_sub_pages(alloc->nents, + &kctx->used_pages); + kbase_atomic_sub_pages(alloc->nents, &kctx->kbdev->memdev.used_pages); + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); +} + +/** + * kbase_mem_evictable_unmark_reclaim - Mark the pages as no longer reclaimable. + * @alloc: The physical allocation + */ +static +void kbase_mem_evictable_unmark_reclaim(struct kbase_mem_phy_alloc *alloc) +{ + struct kbase_context *kctx = alloc->imported.kctx; + struct kbase_mem_zone_cache_entry *zone_cache; + int __maybe_unused new_page_count; + int err; + + new_page_count = kbase_atomic_add_pages(alloc->nents, + &kctx->used_pages); + kbase_atomic_add_pages(alloc->nents, &kctx->kbdev->memdev.used_pages); + + /* Increase mm counters so that the allocation is accounted for + * against the process and thus is visible to the OOM killer, + * then remove it from the reclaimable accounting. */ + kbase_process_page_usage_inc(kctx, alloc->nents); + + /* Attempt to build a zone cache of tracking */ + err = kbase_zone_cache_build(alloc); + if (err == 0) { + /* Bulk update all the zones */ + list_for_each_entry(zone_cache, &alloc->zone_cache, zone_node) { + zone_page_state_add(-zone_cache->count, + zone_cache->zone, NR_SLAB_RECLAIMABLE); + } + } else { + /* Fall-back to page by page updates */ + int i; + + for (i = 0; i < alloc->nents; i++) { + struct page *p; + struct zone *zone; + + p = phys_to_page(as_phys_addr_t(alloc->pages[i])); + zone = page_zone(p); + zone_page_state_add(-1, zone, NR_SLAB_RECLAIMABLE); + } + } + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); +} + +int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc) +{ + struct kbase_context *kctx = gpu_alloc->imported.kctx; + + lockdep_assert_held(&kctx->reg_lock); + + /* This alloction can't already be on a list. */ + WARN_ON(!list_empty(&gpu_alloc->evict_node)); + + kbase_mem_shrink_cpu_mapping(kctx, gpu_alloc->reg, + 0, gpu_alloc->nents); + + /* + * Add the allocation to the eviction list, after this point the shrink + * can reclaim it. + */ + mutex_lock(&kctx->jit_evict_lock); + list_add(&gpu_alloc->evict_node, &kctx->evict_list); + mutex_unlock(&kctx->jit_evict_lock); + kbase_mem_evictable_mark_reclaim(gpu_alloc); + + gpu_alloc->reg->flags |= KBASE_REG_DONT_NEED; + return 0; +} + +bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *gpu_alloc) +{ + struct kbase_context *kctx = gpu_alloc->imported.kctx; + int err = 0; + + lockdep_assert_held(&kctx->reg_lock); + + /* + * First remove the allocation from the eviction list as it's no + * longer eligible for eviction. + */ + list_del_init(&gpu_alloc->evict_node); + + if (gpu_alloc->evicted == 0) { + /* + * The backing is still present, update the VM stats as it's + * in use again. + */ + kbase_mem_evictable_unmark_reclaim(gpu_alloc); + } else { + /* If the region is still alive ... */ + if (gpu_alloc->reg) { + /* ... allocate replacement backing ... */ + err = kbase_alloc_phy_pages_helper(gpu_alloc, + gpu_alloc->evicted); + + /* + * ... and grow the mapping back to its + * pre-eviction size. + */ + if (!err) + err = kbase_mem_grow_gpu_mapping(kctx, + gpu_alloc->reg, + gpu_alloc->evicted, 0); + + gpu_alloc->evicted = 0; + } + } + + /* If the region is still alive remove the DONT_NEED attribute. */ + if (gpu_alloc->reg) + gpu_alloc->reg->flags &= ~KBASE_REG_DONT_NEED; + + return (err == 0); +} + +int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned int flags, unsigned int mask) +{ + struct kbase_va_region *reg; + int ret = -EINVAL; + unsigned int real_flags = 0; + unsigned int prev_flags = 0; + bool prev_needed, new_needed; + + KBASE_DEBUG_ASSERT(kctx); + + if (!gpu_addr) + return -EINVAL; + + if ((gpu_addr & ~PAGE_MASK) && (gpu_addr >= PAGE_SIZE)) + return -EINVAL; + + /* nuke other bits */ + flags &= mask; + + /* check for only supported flags */ + if (flags & ~(BASE_MEM_FLAGS_MODIFIABLE)) + goto out; + + /* mask covers bits we don't support? */ + if (mask & ~(BASE_MEM_FLAGS_MODIFIABLE)) + goto out; + + /* convert flags */ + if (BASE_MEM_COHERENT_SYSTEM & flags) + real_flags |= KBASE_REG_SHARE_BOTH; + else if (BASE_MEM_COHERENT_LOCAL & flags) + real_flags |= KBASE_REG_SHARE_IN; + + /* now we can lock down the context, and find the region */ + down_write(¤t->mm->mmap_sem); + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + /* Is the region being transitioning between not needed and needed? */ + prev_needed = (KBASE_REG_DONT_NEED & reg->flags) == KBASE_REG_DONT_NEED; + new_needed = (BASE_MEM_DONT_NEED & flags) == BASE_MEM_DONT_NEED; + if (prev_needed != new_needed) { + /* Aliased allocations can't be made ephemeral */ + if (atomic_read(®->cpu_alloc->gpu_mappings) > 1) + goto out_unlock; + + if (new_needed) { + /* Only native allocations can be marked not needed */ + if (reg->cpu_alloc->type != KBASE_MEM_TYPE_NATIVE) { + ret = -EINVAL; + goto out_unlock; + } + ret = kbase_mem_evictable_make(reg->gpu_alloc); + if (ret) + goto out_unlock; + } else { + kbase_mem_evictable_unmake(reg->gpu_alloc); + } + } + + /* limit to imported memory */ + if ((reg->gpu_alloc->type != KBASE_MEM_TYPE_IMPORTED_UMP) && + (reg->gpu_alloc->type != KBASE_MEM_TYPE_IMPORTED_UMM)) + goto out_unlock; + + /* no change? */ + if (real_flags == (reg->flags & (KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH))) { + ret = 0; + goto out_unlock; + } + + /* save for roll back */ + prev_flags = reg->flags; + reg->flags &= ~(KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH); + reg->flags |= real_flags; + + /* Currently supporting only imported memory */ + switch (reg->gpu_alloc->type) { +#ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ret = kbase_mmu_update_pages(kctx, reg->start_pfn, + kbase_get_gpu_phy_pages(reg), + reg->gpu_alloc->nents, reg->flags); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + /* Future use will use the new flags, existing mapping will NOT be updated + * as memory should not be in use by the GPU when updating the flags. + */ + ret = 0; + WARN_ON(reg->gpu_alloc->imported.umm.current_mapping_usage_count); + break; +#endif + default: + break; + } + + /* roll back on error, i.e. not UMP */ + if (ret) + reg->flags = prev_flags; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + up_write(¤t->mm->mmap_sem); +out: + return ret; +} + +#define KBASE_MEM_IMPORT_HAVE_PAGES (1UL << BASE_MEM_FLAGS_NR_BITS) + +#ifdef CONFIG_UMP +static struct kbase_va_region *kbase_mem_from_ump(struct kbase_context *kctx, ump_secure_id id, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + ump_dd_handle umph; + u64 block_count; + const ump_dd_physical_block_64 *block_array; + u64 i, j; + int page = 0; + ump_alloc_flags ump_flags; + ump_alloc_flags cpu_flags; + ump_alloc_flags gpu_flags; + + if (*flags & BASE_MEM_SECURE) + goto bad_flags; + + umph = ump_dd_from_secure_id(id); + if (UMP_DD_INVALID_MEMORY_HANDLE == umph) + goto bad_id; + + ump_flags = ump_dd_allocation_flags_get(umph); + cpu_flags = (ump_flags >> UMP_DEVICE_CPU_SHIFT) & UMP_DEVICE_MASK; + gpu_flags = (ump_flags >> DEFAULT_UMP_GPU_DEVICE_SHIFT) & + UMP_DEVICE_MASK; + + *va_pages = ump_dd_size_get_64(umph); + *va_pages >>= PAGE_SHIFT; + + if (!*va_pages) + goto bad_size; + + if (*va_pages > (U64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + if (*flags & BASE_MEM_SAME_VA) + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + else + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + + if (!reg) + goto no_region; + + /* we've got pages to map now, and support SAME_VA */ + *flags |= KBASE_MEM_IMPORT_HAVE_PAGES; + + reg->gpu_alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMP); + if (IS_ERR_OR_NULL(reg->gpu_alloc)) + goto no_alloc_obj; + + reg->cpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + + reg->gpu_alloc->imported.ump_handle = umph; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMP is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMP cannot be grown */ + + /* Override import flags based on UMP flags */ + *flags &= ~(BASE_MEM_CACHED_CPU); + *flags &= ~(BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR); + *flags &= ~(BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR); + + if ((cpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) { + reg->flags |= KBASE_REG_CPU_CACHED; + *flags |= BASE_MEM_CACHED_CPU; + } + + if (cpu_flags & UMP_PROT_CPU_WR) { + reg->flags |= KBASE_REG_CPU_WR; + *flags |= BASE_MEM_PROT_CPU_WR; + } + + if (cpu_flags & UMP_PROT_CPU_RD) { + reg->flags |= KBASE_REG_CPU_RD; + *flags |= BASE_MEM_PROT_CPU_RD; + } + + if ((gpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) + reg->flags |= KBASE_REG_GPU_CACHED; + + if (gpu_flags & UMP_PROT_DEVICE_WR) { + reg->flags |= KBASE_REG_GPU_WR; + *flags |= BASE_MEM_PROT_GPU_WR; + } + + if (gpu_flags & UMP_PROT_DEVICE_RD) { + reg->flags |= KBASE_REG_GPU_RD; + *flags |= BASE_MEM_PROT_GPU_RD; + } + + /* ump phys block query */ + ump_dd_phys_blocks_get_64(umph, &block_count, &block_array); + + for (i = 0; i < block_count; i++) { + for (j = 0; j < (block_array[i].size >> PAGE_SHIFT); j++) { + struct tagged_addr tagged; + + tagged = as_tagged(block_array[i].addr + + (j << PAGE_SHIFT)); + reg->gpu_alloc->pages[page] = tagged; + page++; + } + } + reg->gpu_alloc->nents = *va_pages; + reg->extent = 0; + + return reg; + +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + ump_dd_release(umph); +bad_id: +bad_flags: + return NULL; +} +#endif /* CONFIG_UMP */ + +#ifdef CONFIG_DMA_SHARED_BUFFER +static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx, + int fd, u64 *va_pages, u64 *flags, u32 padding) +{ + struct kbase_va_region *reg; + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + bool shared_zone = false; + + dma_buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dma_buf)) + goto no_buf; + + dma_attachment = dma_buf_attach(dma_buf, kctx->kbdev->dev); + if (!dma_attachment) + goto no_attachment; + + *va_pages = (PAGE_ALIGN(dma_buf->size) >> PAGE_SHIFT) + padding; + if (!*va_pages) + goto bad_size; + + if (*va_pages > (U64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* ignore SAME_VA */ + *flags &= ~BASE_MEM_SAME_VA; + + if (*flags & BASE_MEM_IMPORT_SHARED) + shared_zone = true; + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* + * 64-bit tasks require us to reserve VA on the CPU that we use + * on the GPU. + */ + shared_zone = true; + } +#endif + + if (shared_zone) { + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + } else { + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_region; + + reg->gpu_alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMM); + if (IS_ERR_OR_NULL(reg->gpu_alloc)) + goto no_alloc_obj; + + reg->cpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + + /* No pages to map yet */ + reg->gpu_alloc->nents = 0; + + if (kbase_update_region_flags(kctx, reg, *flags) != 0) + goto invalid_flags; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMM is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMM cannot be grown */ + reg->flags |= KBASE_REG_GPU_CACHED; + + if (*flags & BASE_MEM_SECURE) + reg->flags |= KBASE_REG_SECURE; + + if (padding) + reg->flags |= KBASE_REG_IMPORT_PAD; + + reg->gpu_alloc->type = KBASE_MEM_TYPE_IMPORTED_UMM; + reg->gpu_alloc->imported.umm.sgt = NULL; + reg->gpu_alloc->imported.umm.dma_buf = dma_buf; + reg->gpu_alloc->imported.umm.dma_attachment = dma_attachment; + reg->gpu_alloc->imported.umm.current_mapping_usage_count = 0; + reg->extent = 0; + + return reg; + +invalid_flags: + kbase_mem_phy_alloc_put(reg->gpu_alloc); +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + dma_buf_detach(dma_buf, dma_attachment); +no_attachment: + dma_buf_put(dma_buf); +no_buf: + return NULL; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +static u32 kbase_get_cache_line_alignment(struct kbase_context *kctx) +{ + u32 cpu_cache_line_size = cache_line_size(); + u32 gpu_cache_line_size = + (1UL << kctx->kbdev->gpu_props.props.l2_props.log2_line_size); + + return ((cpu_cache_line_size > gpu_cache_line_size) ? + cpu_cache_line_size : + gpu_cache_line_size); +} + +static struct kbase_va_region *kbase_mem_from_user_buffer( + struct kbase_context *kctx, unsigned long address, + unsigned long size, u64 *va_pages, u64 *flags) +{ + long i; + struct kbase_va_region *reg; + long faulted_pages; + int zone = KBASE_REG_ZONE_CUSTOM_VA; + bool shared_zone = false; + u32 cache_line_alignment = kbase_get_cache_line_alignment(kctx); + struct kbase_alloc_import_user_buf *user_buf; + struct page **pages = NULL; + + if ((address & (cache_line_alignment - 1)) != 0 || + (size & (cache_line_alignment - 1)) != 0) { + /* Coherency must be enabled to handle partial cache lines */ + if (*flags & (BASE_MEM_COHERENT_SYSTEM | + BASE_MEM_COHERENT_SYSTEM_REQUIRED)) { + /* Force coherent system required flag, import will + * then fail if coherency isn't available + */ + *flags |= BASE_MEM_COHERENT_SYSTEM_REQUIRED; + } else { + dev_warn(kctx->kbdev->dev, + "User buffer is not cache line aligned and no coherency enabled\n"); + goto bad_size; + } + } + + *va_pages = (PAGE_ALIGN(address + size) >> PAGE_SHIFT) - + PFN_DOWN(address); + if (!*va_pages) + goto bad_size; + + if (*va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* SAME_VA generally not supported with imported memory (no known use cases) */ + *flags &= ~BASE_MEM_SAME_VA; + + if (*flags & BASE_MEM_IMPORT_SHARED) + shared_zone = true; + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* + * 64-bit tasks require us to reserve VA on the CPU that we use + * on the GPU. + */ + shared_zone = true; + } +#endif + + if (shared_zone) { + *flags |= BASE_MEM_NEED_MMAP; + zone = KBASE_REG_ZONE_SAME_VA; + } + + reg = kbase_alloc_free_region(kctx, 0, *va_pages, zone); + + if (!reg) + goto no_region; + + reg->gpu_alloc = kbase_alloc_create(*va_pages, + KBASE_MEM_TYPE_IMPORTED_USER_BUF); + if (IS_ERR_OR_NULL(reg->gpu_alloc)) + goto no_alloc_obj; + + reg->cpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + + if (kbase_update_region_flags(kctx, reg, *flags) != 0) + goto invalid_flags; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* User-buffers are always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* Cannot be grown */ + + user_buf = ®->gpu_alloc->imported.user_buf; + + user_buf->size = size; + user_buf->address = address; + user_buf->nr_pages = *va_pages; + user_buf->mm = current->mm; + user_buf->pages = kmalloc_array(*va_pages, sizeof(struct page *), + GFP_KERNEL); + + if (!user_buf->pages) + goto no_page_array; + + /* If the region is coherent with the CPU then the memory is imported + * and mapped onto the GPU immediately. + * Otherwise get_user_pages is called as a sanity check, but with + * NULL as the pages argument which will fault the pages, but not + * pin them. The memory will then be pinned only around the jobs that + * specify the region as an external resource. + */ + if (reg->flags & KBASE_REG_SHARE_BOTH) { + pages = user_buf->pages; + *flags |= KBASE_MEM_IMPORT_HAVE_PAGES; + } + + down_read(¤t->mm->mmap_sem); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) + faulted_pages = get_user_pages(current, current->mm, address, *va_pages, + reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + faulted_pages = get_user_pages(address, *va_pages, + reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL); +#else + faulted_pages = get_user_pages(address, *va_pages, + reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, + pages, NULL); +#endif + + up_read(¤t->mm->mmap_sem); + + if (faulted_pages != *va_pages) + goto fault_mismatch; + + atomic_inc(¤t->mm->mm_count); + + reg->gpu_alloc->nents = 0; + reg->extent = 0; + + if (pages) { + struct device *dev = kctx->kbdev->dev; + unsigned long local_size = user_buf->size; + unsigned long offset = user_buf->address & ~PAGE_MASK; + struct tagged_addr *pa = kbase_get_gpu_phy_pages(reg); + + /* Top bit signifies that this was pinned on import */ + user_buf->current_mapping_usage_count |= PINNED_ON_IMPORT; + + for (i = 0; i < faulted_pages; i++) { + dma_addr_t dma_addr; + unsigned long min; + + min = MIN(PAGE_SIZE - offset, local_size); + dma_addr = dma_map_page(dev, pages[i], + offset, min, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) + goto unwind_dma_map; + + user_buf->dma_addrs[i] = dma_addr; + pa[i] = as_tagged(page_to_phys(pages[i])); + + local_size -= min; + offset = 0; + } + + reg->gpu_alloc->nents = faulted_pages; + } + + return reg; + +unwind_dma_map: + while (i--) { + dma_unmap_page(kctx->kbdev->dev, + user_buf->dma_addrs[i], + PAGE_SIZE, DMA_BIDIRECTIONAL); + } +fault_mismatch: + if (pages) { + for (i = 0; i < faulted_pages; i++) + put_page(pages[i]); + } + kfree(user_buf->pages); +no_page_array: +invalid_flags: + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + return NULL; + +} + + +u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, + u64 nents, struct base_mem_aliasing_info *ai, + u64 *num_pages) +{ + struct kbase_va_region *reg; + u64 gpu_va; + size_t i; + bool coherent; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(ai); + KBASE_DEBUG_ASSERT(num_pages); + + /* mask to only allowed flags */ + *flags &= (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | + BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL | + BASE_MEM_COHERENT_SYSTEM_REQUIRED); + + if (!(*flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR))) { + dev_warn(kctx->kbdev->dev, + "kbase_mem_alias called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + coherent = (*flags & BASE_MEM_COHERENT_SYSTEM) != 0 || + (*flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED) != 0; + + if (!stride) + goto bad_stride; + + if (!nents) + goto bad_nents; + + if ((nents * stride) > (U64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* calculate the number of pages this alias will cover */ + *num_pages = nents * stride; + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* 64-bit tasks must MMAP anyway, but not expose this address to + * clients */ + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_SAME_VA); + } else { +#else + if (1) { +#endif + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_reg; + + /* zero-sized page array, as we don't need one/can support one */ + reg->gpu_alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_ALIAS); + if (IS_ERR_OR_NULL(reg->gpu_alloc)) + goto no_alloc_obj; + + reg->cpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + + if (kbase_update_region_flags(kctx, reg, *flags) != 0) + goto invalid_flags; + + reg->gpu_alloc->imported.alias.nents = nents; + reg->gpu_alloc->imported.alias.stride = stride; + reg->gpu_alloc->imported.alias.aliased = vzalloc(sizeof(*reg->gpu_alloc->imported.alias.aliased) * nents); + if (!reg->gpu_alloc->imported.alias.aliased) + goto no_aliased_array; + + kbase_gpu_vm_lock(kctx); + + /* validate and add src handles */ + for (i = 0; i < nents; i++) { + if (ai[i].handle.basep.handle < BASE_MEM_FIRST_FREE_ADDRESS) { + if (ai[i].handle.basep.handle != + BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE) + goto bad_handle; /* unsupported magic handle */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + reg->gpu_alloc->imported.alias.aliased[i].length = ai[i].length; + } else { + struct kbase_va_region *aliasing_reg; + struct kbase_mem_phy_alloc *alloc; + + aliasing_reg = kbase_region_tracker_find_region_base_address( + kctx, + (ai[i].handle.basep.handle >> PAGE_SHIFT) << PAGE_SHIFT); + + /* validate found region */ + if (!aliasing_reg) + goto bad_handle; /* Not found */ + if (aliasing_reg->flags & KBASE_REG_FREE) + goto bad_handle; /* Free region */ + if (aliasing_reg->flags & KBASE_REG_DONT_NEED) + goto bad_handle; /* Ephemeral region */ + if (!aliasing_reg->gpu_alloc) + goto bad_handle; /* No alloc */ + if (aliasing_reg->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE) + goto bad_handle; /* Not a native alloc */ + if (coherent != ((aliasing_reg->flags & KBASE_REG_SHARE_BOTH) != 0)) + goto bad_handle; + /* Non-coherent memory cannot alias + coherent memory, and vice versa.*/ + + /* check size against stride */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + + alloc = aliasing_reg->gpu_alloc; + + /* check against the alloc's size */ + if (ai[i].offset > alloc->nents) + goto bad_handle; /* beyond end */ + if (ai[i].offset + ai[i].length > alloc->nents) + goto bad_handle; /* beyond end */ + + reg->gpu_alloc->imported.alias.aliased[i].alloc = kbase_mem_phy_alloc_get(alloc); + reg->gpu_alloc->imported.alias.aliased[i].length = ai[i].length; + reg->gpu_alloc->imported.alias.aliased[i].offset = ai[i].offset; + } + } + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) { + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(kctx->kbdev->dev, "No cookies available for allocation!"); + goto no_cookie; + } + /* return a cookie */ + gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << gpu_va); + BUG_ON(kctx->pending_regions[gpu_va]); + kctx->pending_regions[gpu_va] = reg; + + /* relocate to correct base */ + gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + gpu_va <<= PAGE_SHIFT; + } else /* we control the VA */ { +#else + if (1) { +#endif + if (kbase_gpu_mmap(kctx, reg, 0, *num_pages, 1) != 0) { + dev_warn(kctx->kbdev->dev, "Failed to map memory on GPU"); + goto no_mmap; + } + /* return real GPU VA */ + gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + reg->flags &= ~KBASE_REG_FREE; + reg->flags &= ~KBASE_REG_GROWABLE; + + kbase_gpu_vm_unlock(kctx); + + return gpu_va; + +#ifdef CONFIG_64BIT +no_cookie: +#endif +no_mmap: +bad_handle: + kbase_gpu_vm_unlock(kctx); +no_aliased_array: +invalid_flags: + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); +no_alloc_obj: + kfree(reg); +no_reg: +bad_size: +bad_nents: +bad_stride: +bad_flags: + return 0; +} + +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, + void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages, + u64 *flags) +{ + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(gpu_va); + KBASE_DEBUG_ASSERT(va_pages); + KBASE_DEBUG_ASSERT(flags); + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) + *flags |= BASE_MEM_SAME_VA; +#endif + + if (!kbase_check_import_flags(*flags)) { + dev_warn(kctx->kbdev->dev, + "kbase_mem_import called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + if ((*flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED) != 0 && + !kbase_device_is_cpu_coherent(kctx->kbdev)) { + dev_warn(kctx->kbdev->dev, + "kbase_mem_import call required coherent mem when unavailable"); + goto bad_flags; + } + if ((*flags & BASE_MEM_COHERENT_SYSTEM) != 0 && + !kbase_device_is_cpu_coherent(kctx->kbdev)) { + /* Remove COHERENT_SYSTEM flag if coherent mem is unavailable */ + *flags &= ~BASE_MEM_COHERENT_SYSTEM; + } + + if ((padding != 0) && (type != BASE_MEM_IMPORT_TYPE_UMM)) { + dev_warn(kctx->kbdev->dev, + "padding is only supported for UMM"); + goto bad_flags; + } + + switch (type) { +#ifdef CONFIG_UMP + case BASE_MEM_IMPORT_TYPE_UMP: { + ump_secure_id id; + + if (get_user(id, (ump_secure_id __user *)phandle)) + reg = NULL; + else + reg = kbase_mem_from_ump(kctx, id, va_pages, flags); + } + break; +#endif /* CONFIG_UMP */ +#ifdef CONFIG_DMA_SHARED_BUFFER + case BASE_MEM_IMPORT_TYPE_UMM: { + int fd; + + if (get_user(fd, (int __user *)phandle)) + reg = NULL; + else + reg = kbase_mem_from_umm(kctx, fd, va_pages, flags, + padding); + } + break; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + case BASE_MEM_IMPORT_TYPE_USER_BUFFER: { + struct base_mem_import_user_buffer user_buffer; + void __user *uptr; + + if (copy_from_user(&user_buffer, phandle, + sizeof(user_buffer))) { + reg = NULL; + } else { +#ifdef CONFIG_COMPAT + if (kbase_ctx_flag(kctx, KCTX_COMPAT)) + uptr = compat_ptr(user_buffer.ptr); + else +#endif + uptr = u64_to_user_ptr(user_buffer.ptr); + + reg = kbase_mem_from_user_buffer(kctx, + (unsigned long)uptr, user_buffer.length, + va_pages, flags); + } + break; + } + default: { + reg = NULL; + break; + } + } + + if (!reg) + goto no_reg; + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & (BASE_MEM_SAME_VA | BASE_MEM_NEED_MMAP)) { + /* Bind to a cookie */ + if (!kctx->cookies) + goto no_cookie; + /* return a cookie */ + *gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << *gpu_va); + BUG_ON(kctx->pending_regions[*gpu_va]); + kctx->pending_regions[*gpu_va] = reg; + + /* relocate to correct base */ + *gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + *gpu_va <<= PAGE_SHIFT; + + } else if (*flags & KBASE_MEM_IMPORT_HAVE_PAGES) { + /* we control the VA, mmap now to the GPU */ + if (kbase_gpu_mmap(kctx, reg, 0, *va_pages, 1) != 0) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } else { + /* we control the VA, but nothing to mmap yet */ + if (kbase_add_va_region(kctx, reg, 0, *va_pages, 1) != 0) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + /* clear out private flags */ + *flags &= ((1UL << BASE_MEM_FLAGS_NR_BITS) - 1); + + kbase_gpu_vm_unlock(kctx); + + return 0; + +no_gpu_va: +no_cookie: + kbase_gpu_vm_unlock(kctx); + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); + kfree(reg); +no_reg: +bad_flags: + *gpu_va = 0; + *va_pages = 0; + *flags = 0; + return -ENOMEM; +} + +int kbase_mem_grow_gpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages) +{ + struct tagged_addr *phy_pages; + u64 delta = new_pages - old_pages; + int ret = 0; + + lockdep_assert_held(&kctx->reg_lock); + + /* Map the new pages into the GPU */ + phy_pages = kbase_get_gpu_phy_pages(reg); + ret = kbase_mmu_insert_pages(kctx, reg->start_pfn + old_pages, + phy_pages + old_pages, delta, reg->flags); + + return ret; +} + +static void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages) +{ + u64 gpu_va_start = reg->start_pfn; + + if (new_pages == old_pages) + /* Nothing to do */ + return; + + unmap_mapping_range(kctx->filp->f_inode->i_mapping, + (gpu_va_start + new_pages)<start_pfn + new_pages, delta); + + return ret; +} + +int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages) +{ + u64 old_pages; + u64 delta; + int res = -EINVAL; + struct kbase_va_region *reg; + bool read_locked = false; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(gpu_addr != 0); + + if (gpu_addr & ~PAGE_MASK) { + dev_warn(kctx->kbdev->dev, "kbase:mem_commit: gpu_addr: passed parameter is invalid"); + return -EINVAL; + } + + down_write(¤t->mm->mmap_sem); + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + KBASE_DEBUG_ASSERT(reg->cpu_alloc); + KBASE_DEBUG_ASSERT(reg->gpu_alloc); + + if (reg->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE) + goto out_unlock; + + if (0 == (reg->flags & KBASE_REG_GROWABLE)) + goto out_unlock; + + /* Would overflow the VA region */ + if (new_pages > reg->nr_pages) + goto out_unlock; + + /* can't be mapped more than once on the GPU */ + if (atomic_read(®->gpu_alloc->gpu_mappings) > 1) + goto out_unlock; + /* can't grow regions which are ephemeral */ + if (reg->flags & KBASE_REG_DONT_NEED) + goto out_unlock; + + if (new_pages == reg->gpu_alloc->nents) { + /* no change */ + res = 0; + goto out_unlock; + } + + old_pages = kbase_reg_current_backed_size(reg); + if (new_pages > old_pages) { + delta = new_pages - old_pages; + + /* + * No update to the mm so downgrade the writer lock to a read + * lock so other readers aren't blocked after this point. + */ + downgrade_write(¤t->mm->mmap_sem); + read_locked = true; + + /* Allocate some more pages */ + if (kbase_alloc_phy_pages_helper(reg->cpu_alloc, delta) != 0) { + res = -ENOMEM; + goto out_unlock; + } + if (reg->cpu_alloc != reg->gpu_alloc) { + if (kbase_alloc_phy_pages_helper( + reg->gpu_alloc, delta) != 0) { + res = -ENOMEM; + kbase_free_phy_pages_helper(reg->cpu_alloc, + delta); + goto out_unlock; + } + } + + /* No update required for CPU mappings, that's done on fault. */ + + /* Update GPU mapping. */ + res = kbase_mem_grow_gpu_mapping(kctx, reg, + new_pages, old_pages); + + /* On error free the new pages */ + if (res) { + kbase_free_phy_pages_helper(reg->cpu_alloc, delta); + if (reg->cpu_alloc != reg->gpu_alloc) + kbase_free_phy_pages_helper(reg->gpu_alloc, + delta); + res = -ENOMEM; + goto out_unlock; + } + } else { + delta = old_pages - new_pages; + + /* Update all CPU mapping(s) */ + kbase_mem_shrink_cpu_mapping(kctx, reg, + new_pages, old_pages); + + /* Update the GPU mapping */ + res = kbase_mem_shrink_gpu_mapping(kctx, reg, + new_pages, old_pages); + if (res) { + res = -ENOMEM; + goto out_unlock; + } + + kbase_free_phy_pages_helper(reg->cpu_alloc, delta); + if (reg->cpu_alloc != reg->gpu_alloc) + kbase_free_phy_pages_helper(reg->gpu_alloc, delta); + } + +out_unlock: + kbase_gpu_vm_unlock(kctx); + if (read_locked) + up_read(¤t->mm->mmap_sem); + else + up_write(¤t->mm->mmap_sem); + + return res; +} + +static void kbase_cpu_vm_open(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + /* non-atomic as we're under Linux' mm lock */ + map->count++; +} + +static void kbase_cpu_vm_close(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + + /* non-atomic as we're under Linux' mm lock */ + if (--map->count) + return; + + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + kbase_gpu_vm_lock(map->kctx); + + if (map->free_on_close) { + KBASE_DEBUG_ASSERT((map->region->flags & KBASE_REG_ZONE_MASK) == + KBASE_REG_ZONE_SAME_VA); + /* Avoid freeing memory on the process death which results in + * GPU Page Fault. Memory will be freed in kbase_destroy_context + */ + if (!(current->flags & PF_EXITING)) + kbase_mem_free_region(map->kctx, map->region); + } + + list_del(&map->mappings_list); + + kbase_gpu_vm_unlock(map->kctx); + + kbase_mem_phy_alloc_put(map->alloc); + kfree(map); +} + +KBASE_EXPORT_TEST_API(kbase_cpu_vm_close); + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) +static int kbase_cpu_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ +#else +static int kbase_cpu_vm_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; +#endif + struct kbase_cpu_mapping *map = vma->vm_private_data; + pgoff_t rel_pgoff; + size_t i; + pgoff_t addr; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + rel_pgoff = vmf->pgoff - map->region->start_pfn; + + kbase_gpu_vm_lock(map->kctx); + if (rel_pgoff >= map->alloc->nents) + goto locked_bad_fault; + + /* Fault on access to DONT_NEED regions */ + if (map->alloc->reg && (map->alloc->reg->flags & KBASE_REG_DONT_NEED)) + goto locked_bad_fault; + + /* insert all valid pages from the fault location */ + i = rel_pgoff; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + addr = (pgoff_t)((uintptr_t)vmf->virtual_address >> PAGE_SHIFT); +#else + addr = (pgoff_t)(vmf->address >> PAGE_SHIFT); +#endif + while (i < map->alloc->nents && (addr < vma->vm_end >> PAGE_SHIFT)) { + int ret = vm_insert_pfn(vma, addr << PAGE_SHIFT, + PFN_DOWN(as_phys_addr_t(map->alloc->pages[i]))); + if (ret < 0 && ret != -EBUSY) + goto locked_bad_fault; + + i++; addr++; + } + + kbase_gpu_vm_unlock(map->kctx); + /* we resolved it, nothing for VM to do */ + return VM_FAULT_NOPAGE; + +locked_bad_fault: + kbase_gpu_vm_unlock(map->kctx); + return VM_FAULT_SIGBUS; +} + +const struct vm_operations_struct kbase_vm_ops = { + .open = kbase_cpu_vm_open, + .close = kbase_cpu_vm_close, + .fault = kbase_cpu_vm_fault +}; + +static int kbase_cpu_mmap(struct kbase_va_region *reg, struct vm_area_struct *vma, void *kaddr, size_t nr_pages, unsigned long aligned_offset, int free_on_close) +{ + struct kbase_cpu_mapping *map; + struct tagged_addr *page_array; + int err = 0; + int i; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + + if (!map) { + WARN_ON(1); + err = -ENOMEM; + goto out; + } + + /* + * VM_DONTCOPY - don't make this mapping available in fork'ed processes + * VM_DONTEXPAND - disable mremap on this region + * VM_IO - disables paging + * VM_DONTDUMP - Don't include in core dumps (3.7 only) + * VM_MIXEDMAP - Support mixing struct page*s and raw pfns. + * This is needed to support using the dedicated and + * the OS based memory backends together. + */ + /* + * This will need updating to propagate coherency flags + * See MIDBASE-1057 + */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_ops; + vma->vm_private_data = map; + + page_array = kbase_get_cpu_phy_pages(reg); + + if (!(reg->flags & KBASE_REG_CPU_CACHED) && + (reg->flags & (KBASE_REG_CPU_WR|KBASE_REG_CPU_RD))) { + /* We can't map vmalloc'd memory uncached. + * Other memory will have been returned from + * kbase_mem_pool which would be + * suitable for mapping uncached. + */ + BUG_ON(kaddr); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + + if (!kaddr) { + unsigned long addr = vma->vm_start + aligned_offset; + u64 start_off = vma->vm_pgoff - reg->start_pfn + + (aligned_offset>>PAGE_SHIFT); + + vma->vm_flags |= VM_PFNMAP; + for (i = 0; i < nr_pages; i++) { + phys_addr_t phys; + + phys = as_phys_addr_t(page_array[i + start_off]); + err = vm_insert_pfn(vma, addr, PFN_DOWN(phys)); + if (WARN_ON(err)) + break; + + addr += PAGE_SIZE; + } + } else { + WARN_ON(aligned_offset); + /* MIXEDMAP so we can vfree the kaddr early and not track it after map time */ + vma->vm_flags |= VM_MIXEDMAP; + /* vmalloc remaping is easy... */ + err = remap_vmalloc_range(vma, kaddr, 0); + WARN_ON(err); + } + + if (err) { + kfree(map); + goto out; + } + + map->region = reg; + map->free_on_close = free_on_close; + map->kctx = reg->kctx; + map->alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); + map->count = 1; /* start with one ref */ + + if (reg->flags & KBASE_REG_CPU_CACHED) + map->alloc->properties |= KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED; + + list_add(&map->mappings_list, &map->alloc->mappings); + + out: + return err; +} + +static int kbase_trace_buffer_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kaddr) +{ + struct kbase_va_region *new_reg; + u32 nr_pages; + size_t size; + int err = 0; + u32 *tb; + int owns_tb = 1; + + dev_dbg(kctx->kbdev->dev, "in %s\n", __func__); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + if (!kctx->jctx.tb) { + KBASE_DEBUG_ASSERT(0 != size); + tb = vmalloc_user(size); + + if (NULL == tb) { + err = -ENOMEM; + goto out; + } + + err = kbase_device_trace_buffer_install(kctx, tb, size); + if (err) { + vfree(tb); + goto out; + } + } else { + err = -EINVAL; + goto out; + } + + *kaddr = kctx->jctx.tb; + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_region; + } + + new_reg->cpu_alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_TB); + if (IS_ERR_OR_NULL(new_reg->cpu_alloc)) { + err = -ENOMEM; + new_reg->cpu_alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->gpu_alloc = kbase_mem_phy_alloc_get(new_reg->cpu_alloc); + + new_reg->cpu_alloc->imported.kctx = kctx; + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + + /* alloc now owns the tb */ + owns_tb = 0; + + if (kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1) != 0) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_va_region; + } + + *reg = new_reg; + + /* map read only, noexec */ + vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); + /* the rest of the flags is added by the cpu_mmap handler */ + + dev_dbg(kctx->kbdev->dev, "%s done\n", __func__); + return 0; + +out_no_va_region: +out_no_alloc: + kbase_free_alloced_region(new_reg); +out_no_region: + if (owns_tb) { + kbase_device_trace_buffer_uninstall(kctx); + vfree(tb); + } +out: + return err; +} + +static int kbase_mmu_dump_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kmap_addr) +{ + struct kbase_va_region *new_reg; + void *kaddr; + u32 nr_pages; + size_t size; + int err = 0; + + dev_dbg(kctx->kbdev->dev, "in kbase_mmu_dump_mmap\n"); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + kaddr = kbase_mmu_dump(kctx, nr_pages); + + if (!kaddr) { + err = -ENOMEM; + goto out; + } + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out; + } + + new_reg->cpu_alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(new_reg->cpu_alloc)) { + err = -ENOMEM; + new_reg->cpu_alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->gpu_alloc = kbase_mem_phy_alloc_get(new_reg->cpu_alloc); + + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + if (kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1) != 0) { + err = -ENOMEM; + WARN_ON(1); + goto out_va_region; + } + + *kmap_addr = kaddr; + *reg = new_reg; + + dev_dbg(kctx->kbdev->dev, "kbase_mmu_dump_mmap done\n"); + return 0; + +out_no_alloc: +out_va_region: + kbase_free_alloced_region(new_reg); +out: + return err; +} + + +void kbase_os_mem_map_lock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + down_read(&mm->mmap_sem); +} + +void kbase_os_mem_map_unlock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + up_read(&mm->mmap_sem); +} + +static int kbasep_reg_mmap(struct kbase_context *kctx, + struct vm_area_struct *vma, + struct kbase_va_region **regm, + size_t *nr_pages, size_t *aligned_offset) + +{ + int cookie = vma->vm_pgoff - PFN_DOWN(BASE_MEM_COOKIE_BASE); + struct kbase_va_region *reg; + int err = 0; + + *aligned_offset = 0; + + dev_dbg(kctx->kbdev->dev, "in kbasep_reg_mmap\n"); + + /* SAME_VA stuff, fetch the right region */ + reg = kctx->pending_regions[cookie]; + if (!reg) { + err = -ENOMEM; + goto out; + } + + if ((reg->flags & KBASE_REG_GPU_NX) && (reg->nr_pages != *nr_pages)) { + /* incorrect mmap size */ + /* leave the cookie for a potential later + * mapping, or to be reclaimed later when the + * context is freed */ + err = -ENOMEM; + goto out; + } + + if ((vma->vm_flags & VM_READ && !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(kctx->kbdev->dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out; + } + + /* adjust down nr_pages to what we have physically */ + *nr_pages = kbase_reg_current_backed_size(reg); + + if (kbase_gpu_mmap(kctx, reg, vma->vm_start + *aligned_offset, + reg->nr_pages, 1) != 0) { + dev_err(kctx->kbdev->dev, "%s:%d\n", __FILE__, __LINE__); + /* Unable to map in GPU space. */ + WARN_ON(1); + err = -ENOMEM; + goto out; + } + /* no need for the cookie anymore */ + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + /* + * Overwrite the offset with the region start_pfn, so we effectively + * map from offset 0 in the region. However subtract the aligned + * offset so that when user space trims the mapping the beginning of + * the trimmed VMA has the correct vm_pgoff; + */ + vma->vm_pgoff = reg->start_pfn - ((*aligned_offset)>>PAGE_SHIFT); +out: + *regm = reg; + dev_dbg(kctx->kbdev->dev, "kbasep_reg_mmap done\n"); + + return err; +} + +int kbase_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct kbase_context *kctx = file->private_data; + struct kbase_va_region *reg = NULL; + void *kaddr = NULL; + size_t nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int err = 0; + int free_on_close = 0; + struct device *dev = kctx->kbdev->dev; + size_t aligned_offset = 0; + + dev_dbg(dev, "kbase_mmap\n"); + + /* strip away corresponding VM_MAY% flags to the VM_% flags requested */ + vma->vm_flags &= ~((vma->vm_flags & (VM_READ | VM_WRITE)) << 4); + + if (0 == nr_pages) { + err = -EINVAL; + goto out; + } + + if (!(vma->vm_flags & VM_SHARED)) { + err = -EINVAL; + goto out; + } + + kbase_gpu_vm_lock(kctx); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MAP_TRACKING_HANDLE)) { + /* The non-mapped tracking helper page */ + err = kbase_tracking_page_setup(kctx, vma); + goto out_unlock; + } + + /* if not the MTP, verify that the MTP has been mapped */ + rcu_read_lock(); + /* catches both when the special page isn't present or + * when we've forked */ + if (rcu_dereference(kctx->process_mm) != current->mm) { + err = -EINVAL; + rcu_read_unlock(); + goto out_unlock; + } + rcu_read_unlock(); + + switch (vma->vm_pgoff) { + case PFN_DOWN(BASEP_MEM_INVALID_HANDLE): + case PFN_DOWN(BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE): + /* Illegal handle for direct map */ + err = -EINVAL; + goto out_unlock; + case PFN_DOWN(BASE_MEM_TRACE_BUFFER_HANDLE): + err = kbase_trace_buffer_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + dev_dbg(dev, "kbase_trace_buffer_mmap ok\n"); + /* free the region on munmap */ + free_on_close = 1; + break; + case PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE): + /* MMU dump */ + err = kbase_mmu_dump_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + /* free the region on munmap */ + free_on_close = 1; + break; + case PFN_DOWN(BASE_MEM_COOKIE_BASE) ... + PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: { + err = kbasep_reg_mmap(kctx, vma, ®, &nr_pages, + &aligned_offset); + if (0 != err) + goto out_unlock; + /* free the region on munmap */ + free_on_close = 1; + break; + } + default: { + reg = kbase_region_tracker_find_region_enclosing_address(kctx, + (u64)vma->vm_pgoff << PAGE_SHIFT); + + if (reg && !(reg->flags & KBASE_REG_FREE)) { + /* will this mapping overflow the size of the region? */ + if (nr_pages > (reg->nr_pages - + (vma->vm_pgoff - reg->start_pfn))) { + err = -ENOMEM; + goto out_unlock; + } + + if ((vma->vm_flags & VM_READ && + !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && + !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out_unlock; + } + +#ifdef CONFIG_DMA_SHARED_BUFFER + if (KBASE_MEM_TYPE_IMPORTED_UMM == + reg->cpu_alloc->type) { + err = dma_buf_mmap( + reg->cpu_alloc->imported.umm.dma_buf, + vma, vma->vm_pgoff - reg->start_pfn); + goto out_unlock; + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + /* limit what we map to the amount currently backed */ + if (reg->cpu_alloc->nents < (vma->vm_pgoff - reg->start_pfn + nr_pages)) { + if ((vma->vm_pgoff - reg->start_pfn) >= reg->cpu_alloc->nents) + nr_pages = 0; + else + nr_pages = reg->cpu_alloc->nents - (vma->vm_pgoff - reg->start_pfn); + } + } else { + err = -ENOMEM; + goto out_unlock; + } + } /* default */ + } /* switch */ + + err = kbase_cpu_mmap(reg, vma, kaddr, nr_pages, aligned_offset, free_on_close); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE)) { + /* MMU dump - userspace should now have a reference on + * the pages, so we can now free the kernel mapping */ + vfree(kaddr); + } + +out_unlock: + kbase_gpu_vm_unlock(kctx); +out: + if (err) + dev_err(dev, "mmap failed %d\n", err); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mmap); + +static void kbasep_sync_mem_regions(struct kbase_context *kctx, + struct kbase_vmap_struct *map, enum kbase_sync_type dest) +{ + size_t i; + off_t const offset = (uintptr_t)map->gpu_addr & ~PAGE_MASK; + size_t const page_count = PFN_UP(offset + map->size); + + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), map->size); + struct tagged_addr cpu_pa = map->cpu_pages[0]; + struct tagged_addr gpu_pa = map->gpu_pages[0]; + + kbase_sync_single(kctx, cpu_pa, gpu_pa, offset, sz, dest); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + cpu_pa = map->cpu_pages[i]; + gpu_pa = map->gpu_pages[i]; + kbase_sync_single(kctx, cpu_pa, gpu_pa, 0, PAGE_SIZE, dest); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + cpu_pa = map->cpu_pages[page_count - 1]; + gpu_pa = map->gpu_pages[page_count - 1]; + sz = ((offset + map->size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, cpu_pa, gpu_pa, 0, sz, dest); + } +} + +void *kbase_vmap_prot(struct kbase_context *kctx, u64 gpu_addr, size_t size, + unsigned long prot_request, struct kbase_vmap_struct *map) +{ + struct kbase_va_region *reg; + unsigned long page_index; + unsigned int offset = gpu_addr & ~PAGE_MASK; + size_t page_count = PFN_UP(offset + size); + struct tagged_addr *page_array; + struct page **pages; + void *cpu_addr = NULL; + pgprot_t prot; + size_t i; + + if (!size || !map) + return NULL; + + /* check if page_count calculation will wrap */ + if (size > ((size_t)-1 / PAGE_SIZE)) + return NULL; + + kbase_gpu_vm_lock(kctx); + + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_index = (gpu_addr >> PAGE_SHIFT) - reg->start_pfn; + + /* check if page_index + page_count will wrap */ + if (-1UL - page_count < page_index) + goto out_unlock; + + if (page_index + page_count > kbase_reg_current_backed_size(reg)) + goto out_unlock; + + if (reg->flags & KBASE_REG_DONT_NEED) + goto out_unlock; + + /* check access permissions can be satisfied + * Intended only for checking KBASE_REG_{CPU,GPU}_{RD,WR} */ + if ((reg->flags & prot_request) != prot_request) + goto out_unlock; + + page_array = kbase_get_cpu_phy_pages(reg); + if (!page_array) + goto out_unlock; + + pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto out_unlock; + + for (i = 0; i < page_count; i++) + pages[i] = phys_to_page(as_phys_addr_t(page_array[page_index + + i])); + + prot = PAGE_KERNEL; + if (!(reg->flags & KBASE_REG_CPU_CACHED)) { + /* Map uncached */ + prot = pgprot_writecombine(prot); + } + /* Note: enforcing a RO prot_request onto prot is not done, since: + * - CPU-arch-specific integration required + * - kbase_vmap() requires no access checks to be made/enforced */ + + cpu_addr = vmap(pages, page_count, VM_MAP, prot); + + kfree(pages); + + if (!cpu_addr) + goto out_unlock; + + map->gpu_addr = gpu_addr; + map->cpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); + map->cpu_pages = &kbase_get_cpu_phy_pages(reg)[page_index]; + map->gpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + map->gpu_pages = &kbase_get_gpu_phy_pages(reg)[page_index]; + map->addr = (void *)((uintptr_t)cpu_addr + offset); + map->size = size; + map->sync_needed = ((reg->flags & KBASE_REG_CPU_CACHED) != 0) && + !kbase_mem_is_imported(map->gpu_alloc->type); + + if (map->sync_needed) + kbasep_sync_mem_regions(kctx, map, KBASE_SYNC_TO_CPU); + kbase_gpu_vm_unlock(kctx); + + return map->addr; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return NULL; +} + +void *kbase_vmap(struct kbase_context *kctx, u64 gpu_addr, size_t size, + struct kbase_vmap_struct *map) +{ + /* 0 is specified for prot_request to indicate no access checks should + * be made. + * + * As mentioned in kbase_vmap_prot() this means that a kernel-side + * CPU-RO mapping is not enforced to allow this to work */ + return kbase_vmap_prot(kctx, gpu_addr, size, 0u, map); +} +KBASE_EXPORT_TEST_API(kbase_vmap); + +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map) +{ + void *addr = (void *)((uintptr_t)map->addr & PAGE_MASK); + vunmap(addr); + + if (map->sync_needed) + kbasep_sync_mem_regions(kctx, map, KBASE_SYNC_TO_DEVICE); + map->gpu_addr = 0; + map->cpu_alloc = kbase_mem_phy_alloc_put(map->cpu_alloc); + map->gpu_alloc = kbase_mem_phy_alloc_put(map->gpu_alloc); + map->cpu_pages = NULL; + map->gpu_pages = NULL; + map->addr = NULL; + map->size = 0; + map->sync_needed = false; +} +KBASE_EXPORT_TEST_API(kbase_vunmap); + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages) +{ + struct mm_struct *mm; + + rcu_read_lock(); + mm = rcu_dereference(kctx->process_mm); + if (mm) { + atomic_add(pages, &kctx->nonmapped_pages); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, pages); + spin_unlock(&mm->page_table_lock); +#endif + } + rcu_read_unlock(); +} + +static void kbasep_os_process_page_usage_drain(struct kbase_context *kctx) +{ + int pages; + struct mm_struct *mm; + + spin_lock(&kctx->mm_update_lock); + mm = rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock)); + if (!mm) { + spin_unlock(&kctx->mm_update_lock); + return; + } + + rcu_assign_pointer(kctx->process_mm, NULL); + spin_unlock(&kctx->mm_update_lock); + synchronize_rcu(); + + pages = atomic_xchg(&kctx->nonmapped_pages, 0); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, -pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, -pages); + spin_unlock(&mm->page_table_lock); +#endif +} + +static void kbase_special_vm_close(struct vm_area_struct *vma) +{ + struct kbase_context *kctx; + + kctx = vma->vm_private_data; + kbasep_os_process_page_usage_drain(kctx); +} + +static const struct vm_operations_struct kbase_vm_special_ops = { + .close = kbase_special_vm_close, +}; + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma) +{ + /* check that this is the only tracking page */ + spin_lock(&kctx->mm_update_lock); + if (rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock))) { + spin_unlock(&kctx->mm_update_lock); + return -EFAULT; + } + + rcu_assign_pointer(kctx->process_mm, current->mm); + + spin_unlock(&kctx->mm_update_lock); + + /* no real access */ + vma->vm_flags &= ~(VM_READ | VM_MAYREAD | VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_special_ops; + vma->vm_private_data = kctx; + + return 0; +} +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle) +{ + int res; + void *va; + dma_addr_t dma_pa; + struct kbase_va_region *reg; + struct tagged_addr *page_array; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + unsigned long attrs = DMA_ATTR_WRITE_COMBINE; +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); +#endif + + u32 pages = ((size - 1) >> PAGE_SHIFT) + 1; + u32 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | + BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR; + u32 i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(0 != size); + KBASE_DEBUG_ASSERT(0 != pages); + + if (size == 0) + goto err; + + /* All the alloc calls return zeroed memory */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + va = dma_alloc_attrs(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL, + attrs); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + va = dma_alloc_attrs(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL, + &attrs); +#else + va = dma_alloc_writecombine(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL); +#endif + if (!va) + goto err; + + /* Store the state so we can free it later. */ + handle->cpu_va = va; + handle->dma_pa = dma_pa; + handle->size = size; + + + reg = kbase_alloc_free_region(kctx, 0, pages, KBASE_REG_ZONE_SAME_VA); + if (!reg) + goto no_reg; + + reg->flags &= ~KBASE_REG_FREE; + if (kbase_update_region_flags(kctx, reg, flags) != 0) + goto invalid_flags; + + reg->cpu_alloc = kbase_alloc_create(pages, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(reg->cpu_alloc)) + goto no_alloc; + + reg->gpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); + + page_array = kbase_get_cpu_phy_pages(reg); + + for (i = 0; i < pages; i++) + page_array[i] = as_tagged(dma_pa + (i << PAGE_SHIFT)); + + reg->cpu_alloc->nents = pages; + + kbase_gpu_vm_lock(kctx); + res = kbase_gpu_mmap(kctx, reg, (uintptr_t) va, pages, 1); + kbase_gpu_vm_unlock(kctx); + if (res) + goto no_mmap; + + return va; + +no_mmap: + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); +no_alloc: +invalid_flags: + kfree(reg); +no_reg: +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + dma_free_attrs(kctx->kbdev->dev, size, va, dma_pa, attrs); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + dma_free_attrs(kctx->kbdev->dev, size, va, dma_pa, &attrs); +#else + dma_free_writecombine(kctx->kbdev->dev, size, va, dma_pa); +#endif +err: + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_va_alloc); + +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle) +{ + struct kbase_va_region *reg; + int err; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) + DEFINE_DMA_ATTRS(attrs); +#endif + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(handle->cpu_va != NULL); + + kbase_gpu_vm_lock(kctx); + reg = kbase_region_tracker_find_region_base_address(kctx, (uintptr_t)handle->cpu_va); + KBASE_DEBUG_ASSERT(reg); + err = kbase_gpu_munmap(kctx, reg); + kbase_gpu_vm_unlock(kctx); + KBASE_DEBUG_ASSERT(!err); + + kbase_mem_phy_alloc_put(reg->cpu_alloc); + kbase_mem_phy_alloc_put(reg->gpu_alloc); + kfree(reg); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + dma_free_attrs(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa, DMA_ATTR_WRITE_COMBINE); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + dma_free_attrs(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa, &attrs); +#else + dma_free_writecombine(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa); +#endif +} +KBASE_EXPORT_SYMBOL(kbase_va_free); + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h new file mode 100644 index 000000000000..db35f62a7431 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h @@ -0,0 +1,240 @@ +/* + * + * (C) COPYRIGHT 2010, 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.h + * Base kernel memory APIs, Linux implementation. + */ + +#ifndef _KBASE_MEM_LINUX_H_ +#define _KBASE_MEM_LINUX_H_ + +/** A HWC dump mapping */ +struct kbase_hwc_dma_mapping { + void *cpu_va; + dma_addr_t dma_pa; + size_t size; +}; + +struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, + u64 va_pages, u64 commit_pages, u64 extent, u64 *flags, + u64 *gpu_va); +int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, int query, u64 *const pages); +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, + void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages, + u64 *flags); +u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 nents, struct base_mem_aliasing_info *ai, u64 *num_pages); +int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned int flags, unsigned int mask); + +/** + * kbase_mem_commit - Change the physical backing size of a region + * + * @kctx: The kernel context + * @gpu_addr: Handle to the memory region + * @new_pages: Number of physical pages to back the region with + * + * Return: 0 on success or error code + */ +int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages); + +int kbase_mmap(struct file *file, struct vm_area_struct *vma); + +/** + * kbase_mem_evictable_init - Initialize the Ephemeral memory the eviction + * mechanism. + * @kctx: The kbase context to initialize. + * + * Return: Zero on success or -errno on failure. + */ +int kbase_mem_evictable_init(struct kbase_context *kctx); + +/** + * kbase_mem_evictable_deinit - De-initialize the Ephemeral memory eviction + * mechanism. + * @kctx: The kbase context to de-initialize. + */ +void kbase_mem_evictable_deinit(struct kbase_context *kctx); + +/** + * kbase_mem_grow_gpu_mapping - Grow the GPU mapping of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region + * @new_pages: The number of pages after the grow + * @old_pages: The number of pages before the grow + * + * Return: 0 on success, -errno on error. + * + * Expand the GPU mapping to encompass the new psychical pages which have + * been added to the allocation. + * + * Note: Caller must be holding the region lock. + */ +int kbase_mem_grow_gpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + +/** + * kbase_mem_evictable_make - Make a physical allocation eligible for eviction + * @gpu_alloc: The physical allocation to make evictable + * + * Return: 0 on success, -errno on error. + * + * Take the provided region and make all the physical pages within it + * reclaimable by the kernel, updating the per-process VM stats as well. + * Remove any CPU mappings (as these can't be removed in the shrinker callback + * as mmap_sem might already be taken) but leave the GPU mapping intact as + * and until the shrinker reclaims the allocation. + * + * Note: Must be called with the region lock of the containing context. + */ +int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc); + +/** + * kbase_mem_evictable_unmake - Remove a physical allocations eligibility for + * eviction. + * @alloc: The physical allocation to remove eviction eligibility from. + * + * Return: True if the allocation had its backing restored and false if + * it hasn't. + * + * Make the physical pages in the region no longer reclaimable and update the + * per-process stats, if the shrinker has already evicted the memory then + * re-allocate it if the region is still alive. + * + * Note: Must be called with the region lock of the containing context. + */ +bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *alloc); + +struct kbase_vmap_struct { + u64 gpu_addr; + struct kbase_mem_phy_alloc *cpu_alloc; + struct kbase_mem_phy_alloc *gpu_alloc; + struct tagged_addr *cpu_pages; + struct tagged_addr *gpu_pages; + void *addr; + size_t size; + bool sync_needed; +}; + + +/** + * kbase_vmap_prot - Map a GPU VA range into the kernel safely, only if the + * requested access permissions are supported + * @kctx: Context the VA range belongs to + * @gpu_addr: Start address of VA range + * @size: Size of VA range + * @prot_request: Flags indicating how the caller will then access the memory + * @map: Structure to be given to kbase_vunmap() on freeing + * + * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error + * + * Map a GPU VA Range into the kernel. The VA range must be contained within a + * GPU memory region. Appropriate CPU cache-flushing operations are made as + * required, dependent on the CPU mapping for the memory region. + * + * This is safer than using kmap() on the pages directly, + * because the pages here are refcounted to prevent freeing (and hence reuse + * elsewhere in the system) until an kbase_vunmap() + * + * The flags in @prot_request should use KBASE_REG_{CPU,GPU}_{RD,WR}, to check + * whether the region should allow the intended access, and return an error if + * disallowed. This is essential for security of imported memory, particularly + * a user buf from SHM mapped into the process as RO. In that case, write + * access must be checked if the intention is for kernel to write to the + * memory. + * + * The checks are also there to help catch access errors on memory where + * security is not a concern: imported memory that is always RW, and memory + * that was allocated and owned by the process attached to @kctx. In this case, + * it helps to identify memory that was was mapped with the wrong access type. + * + * Note: KBASE_REG_GPU_{RD,WR} flags are currently supported for legacy cases + * where either the security of memory is solely dependent on those flags, or + * when userspace code was expecting only the GPU to access the memory (e.g. HW + * workarounds). + * + * All cache maintenance operations shall be ignored if the + * memory region has been imported. + * + */ +void *kbase_vmap_prot(struct kbase_context *kctx, u64 gpu_addr, size_t size, + unsigned long prot_request, struct kbase_vmap_struct *map); + +/** + * kbase_vmap - Map a GPU VA range into the kernel safely + * @kctx: Context the VA range belongs to + * @gpu_addr: Start address of VA range + * @size: Size of VA range + * @map: Structure to be given to kbase_vunmap() on freeing + * + * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error + * + * Map a GPU VA Range into the kernel. The VA range must be contained within a + * GPU memory region. Appropriate CPU cache-flushing operations are made as + * required, dependent on the CPU mapping for the memory region. + * + * This is safer than using kmap() on the pages directly, + * because the pages here are refcounted to prevent freeing (and hence reuse + * elsewhere in the system) until an kbase_vunmap() + * + * kbase_vmap_prot() should be used in preference, since kbase_vmap() makes no + * checks to ensure the security of e.g. imported user bufs from RO SHM. + * + * Note: All cache maintenance operations shall be ignored if the memory region + * has been imported. + */ +void *kbase_vmap(struct kbase_context *kctx, u64 gpu_addr, size_t size, + struct kbase_vmap_struct *map); + +/** + * kbase_vunmap - Unmap a GPU VA range from the kernel + * @kctx: Context the VA range belongs to + * @map: Structure describing the mapping from the corresponding kbase_vmap() + * call + * + * Unmaps a GPU VA range from the kernel, given its @map structure obtained + * from kbase_vmap(). Appropriate CPU cache-flushing operations are made as + * required, dependent on the CPU mapping for the memory region. + * + * The reference taken on pages during kbase_vmap() is released. + * + * Note: All cache maintenance operations shall be ignored if the memory region + * has been imported. + */ +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map); + +/** @brief Allocate memory from kernel space and map it onto the GPU + * + * @param kctx The context used for the allocation/mapping + * @param size The size of the allocation in bytes + * @param handle An opaque structure used to contain the state needed to free the memory + * @return the VA for kernel space and GPU MMU + */ +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle); + +/** @brief Free/unmap memory allocated by kbase_va_alloc + * + * @param kctx The context used for the allocation/mapping + * @param handle An opaque structure returned by the kbase_va_alloc function. + */ +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle); + +extern const struct vm_operations_struct kbase_vm_ops; + +#endif /* _KBASE_MEM_LINUX_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_lowlevel.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_lowlevel.h new file mode 100644 index 000000000000..f4e88491327e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_lowlevel.h @@ -0,0 +1,89 @@ +/* + * + * (C) COPYRIGHT 2012-2014,2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_MEM_LOWLEVEL_H +#define _KBASE_MEM_LOWLEVEL_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include + +/** + * @brief Flags for kbase_phy_allocator_pages_alloc + */ +#define KBASE_PHY_PAGES_FLAG_DEFAULT (0) /** Default allocation flag */ +#define KBASE_PHY_PAGES_FLAG_CLEAR (1 << 0) /** Clear the pages after allocation */ +#define KBASE_PHY_PAGES_FLAG_POISON (1 << 1) /** Fill the memory with a poison value */ + +#define KBASE_PHY_PAGES_SUPPORTED_FLAGS (KBASE_PHY_PAGES_FLAG_DEFAULT|KBASE_PHY_PAGES_FLAG_CLEAR|KBASE_PHY_PAGES_FLAG_POISON) + +#define KBASE_PHY_PAGES_POISON_VALUE 0xFD /** Value to fill the memory with when KBASE_PHY_PAGES_FLAG_POISON is set */ + +enum kbase_sync_type { + KBASE_SYNC_TO_CPU, + KBASE_SYNC_TO_DEVICE +}; + +struct tagged_addr { phys_addr_t tagged_addr; }; + +#define HUGE_PAGE (1u << 0) +#define HUGE_HEAD (1u << 1) +#define FROM_PARTIAL (1u << 2) + +static inline phys_addr_t as_phys_addr_t(struct tagged_addr t) +{ + return t.tagged_addr & PAGE_MASK; +} + +static inline struct tagged_addr as_tagged(phys_addr_t phys) +{ + struct tagged_addr t; + + t.tagged_addr = phys & PAGE_MASK; + return t; +} + +static inline struct tagged_addr as_tagged_tag(phys_addr_t phys, int tag) +{ + struct tagged_addr t; + + t.tagged_addr = (phys & PAGE_MASK) | (tag & ~PAGE_MASK); + return t; +} + +static inline bool is_huge(struct tagged_addr t) +{ + return t.tagged_addr & HUGE_PAGE; +} + +static inline bool is_huge_head(struct tagged_addr t) +{ + int mask = HUGE_HEAD | HUGE_PAGE; + + return mask == (t.tagged_addr & mask); +} + +static inline bool is_partial(struct tagged_addr t) +{ + return t.tagged_addr & FROM_PARTIAL; +} + +#endif /* _KBASE_LOWLEVEL_H */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c new file mode 100644 index 000000000000..696730ac5b2b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c @@ -0,0 +1,651 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define pool_dbg(pool, format, ...) \ + dev_dbg(pool->kbdev->dev, "%s-pool [%zu/%zu]: " format, \ + (pool->next_pool) ? "kctx" : "kbdev", \ + kbase_mem_pool_size(pool), \ + kbase_mem_pool_max_size(pool), \ + ##__VA_ARGS__) + +#define NOT_DIRTY false +#define NOT_RECLAIMED false + +static inline void kbase_mem_pool_lock(struct kbase_mem_pool *pool) +{ + spin_lock(&pool->pool_lock); +} + +static inline void kbase_mem_pool_unlock(struct kbase_mem_pool *pool) +{ + spin_unlock(&pool->pool_lock); +} + +static size_t kbase_mem_pool_capacity(struct kbase_mem_pool *pool) +{ + ssize_t max_size = kbase_mem_pool_max_size(pool); + ssize_t cur_size = kbase_mem_pool_size(pool); + + return max(max_size - cur_size, (ssize_t)0); +} + +static bool kbase_mem_pool_is_full(struct kbase_mem_pool *pool) +{ + return kbase_mem_pool_size(pool) >= kbase_mem_pool_max_size(pool); +} + +static bool kbase_mem_pool_is_empty(struct kbase_mem_pool *pool) +{ + return kbase_mem_pool_size(pool) == 0; +} + +static void kbase_mem_pool_add_locked(struct kbase_mem_pool *pool, + struct page *p) +{ + lockdep_assert_held(&pool->pool_lock); + + list_add(&p->lru, &pool->page_list); + pool->cur_size++; + + zone_page_state_add(1, page_zone(p), NR_SLAB_RECLAIMABLE); + + pool_dbg(pool, "added page\n"); +} + +static void kbase_mem_pool_add(struct kbase_mem_pool *pool, struct page *p) +{ + kbase_mem_pool_lock(pool); + kbase_mem_pool_add_locked(pool, p); + kbase_mem_pool_unlock(pool); +} + +static void kbase_mem_pool_add_list_locked(struct kbase_mem_pool *pool, + struct list_head *page_list, size_t nr_pages) +{ + struct page *p; + + lockdep_assert_held(&pool->pool_lock); + + list_for_each_entry(p, page_list, lru) { + zone_page_state_add(1, page_zone(p), NR_SLAB_RECLAIMABLE); + } + + list_splice(page_list, &pool->page_list); + pool->cur_size += nr_pages; + + pool_dbg(pool, "added %zu pages\n", nr_pages); +} + +static void kbase_mem_pool_add_list(struct kbase_mem_pool *pool, + struct list_head *page_list, size_t nr_pages) +{ + kbase_mem_pool_lock(pool); + kbase_mem_pool_add_list_locked(pool, page_list, nr_pages); + kbase_mem_pool_unlock(pool); +} + +static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool) +{ + struct page *p; + + lockdep_assert_held(&pool->pool_lock); + + if (kbase_mem_pool_is_empty(pool)) + return NULL; + + p = list_first_entry(&pool->page_list, struct page, lru); + list_del_init(&p->lru); + pool->cur_size--; + + zone_page_state_add(-1, page_zone(p), NR_SLAB_RECLAIMABLE); + + pool_dbg(pool, "removed page\n"); + + return p; +} + +static struct page *kbase_mem_pool_remove(struct kbase_mem_pool *pool) +{ + struct page *p; + + kbase_mem_pool_lock(pool); + p = kbase_mem_pool_remove_locked(pool); + kbase_mem_pool_unlock(pool); + + return p; +} + +static void kbase_mem_pool_sync_page(struct kbase_mem_pool *pool, + struct page *p) +{ + struct device *dev = pool->kbdev->dev; + dma_sync_single_for_device(dev, kbase_dma_addr(p), + (PAGE_SIZE << pool->order), DMA_BIDIRECTIONAL); +} + +static void kbase_mem_pool_zero_page(struct kbase_mem_pool *pool, + struct page *p) +{ + int i; + + for (i = 0; i < (1U << pool->order); i++) + clear_highpage(p+i); + + kbase_mem_pool_sync_page(pool, p); +} + +static void kbase_mem_pool_spill(struct kbase_mem_pool *next_pool, + struct page *p) +{ + /* Zero page before spilling */ + kbase_mem_pool_zero_page(next_pool, p); + + kbase_mem_pool_add(next_pool, p); +} + +struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) +{ + struct page *p; + gfp_t gfp; + struct device *dev = pool->kbdev->dev; + dma_addr_t dma_addr; + int i; + +#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + gfp = GFP_USER | __GFP_ZERO; +#else + gfp = GFP_HIGHUSER | __GFP_ZERO; +#endif + + if (current->flags & PF_KTHREAD) { + /* Don't trigger OOM killer from kernel threads, e.g. when + * growing memory on GPU page fault */ + gfp |= __GFP_NORETRY; + } + + /* don't warn on higer order failures */ + if (pool->order) + gfp |= __GFP_NOWARN; + + p = alloc_pages(gfp, pool->order); + if (!p) + return NULL; + + dma_addr = dma_map_page(dev, p, 0, (PAGE_SIZE << pool->order), + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) { + __free_pages(p, pool->order); + return NULL; + } + + WARN_ON(dma_addr != page_to_phys(p)); + for (i = 0; i < (1u << pool->order); i++) + kbase_set_dma_addr(p+i, dma_addr + PAGE_SIZE * i); + + return p; +} + +static void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, + struct page *p) +{ + struct device *dev = pool->kbdev->dev; + dma_addr_t dma_addr = kbase_dma_addr(p); + int i; + + dma_unmap_page(dev, dma_addr, (PAGE_SIZE << pool->order), + DMA_BIDIRECTIONAL); + for (i = 0; i < (1u << pool->order); i++) + kbase_clear_dma_addr(p+i); + __free_pages(p, pool->order); + + pool_dbg(pool, "freed page to kernel\n"); +} + +static size_t kbase_mem_pool_shrink_locked(struct kbase_mem_pool *pool, + size_t nr_to_shrink) +{ + struct page *p; + size_t i; + + lockdep_assert_held(&pool->pool_lock); + + for (i = 0; i < nr_to_shrink && !kbase_mem_pool_is_empty(pool); i++) { + p = kbase_mem_pool_remove_locked(pool); + kbase_mem_pool_free_page(pool, p); + } + + return i; +} + +static size_t kbase_mem_pool_shrink(struct kbase_mem_pool *pool, + size_t nr_to_shrink) +{ + size_t nr_freed; + + kbase_mem_pool_lock(pool); + nr_freed = kbase_mem_pool_shrink_locked(pool, nr_to_shrink); + kbase_mem_pool_unlock(pool); + + return nr_freed; +} + +int kbase_mem_pool_grow(struct kbase_mem_pool *pool, + size_t nr_to_grow) +{ + struct page *p; + size_t i; + + for (i = 0; i < nr_to_grow; i++) { + p = kbase_mem_alloc_page(pool); + if (!p) + return -ENOMEM; + kbase_mem_pool_add(pool, p); + } + + return 0; +} + +void kbase_mem_pool_trim(struct kbase_mem_pool *pool, size_t new_size) +{ + size_t cur_size; + int err = 0; + + cur_size = kbase_mem_pool_size(pool); + + if (new_size > pool->max_size) + new_size = pool->max_size; + + if (new_size < cur_size) + kbase_mem_pool_shrink(pool, cur_size - new_size); + else if (new_size > cur_size) + err = kbase_mem_pool_grow(pool, new_size - cur_size); + + if (err) { + size_t grown_size = kbase_mem_pool_size(pool); + + dev_warn(pool->kbdev->dev, + "Mem pool not grown to the required size of %zu bytes, grown for additional %zu bytes instead!\n", + (new_size - cur_size), (grown_size - cur_size)); + } +} + +void kbase_mem_pool_set_max_size(struct kbase_mem_pool *pool, size_t max_size) +{ + size_t cur_size; + size_t nr_to_shrink; + + kbase_mem_pool_lock(pool); + + pool->max_size = max_size; + + cur_size = kbase_mem_pool_size(pool); + if (max_size < cur_size) { + nr_to_shrink = cur_size - max_size; + kbase_mem_pool_shrink_locked(pool, nr_to_shrink); + } + + kbase_mem_pool_unlock(pool); +} + + +static unsigned long kbase_mem_pool_reclaim_count_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_pool *pool; + + pool = container_of(s, struct kbase_mem_pool, reclaim); + pool_dbg(pool, "reclaim count: %zu\n", kbase_mem_pool_size(pool)); + return kbase_mem_pool_size(pool); +} + +static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_pool *pool; + unsigned long freed; + + pool = container_of(s, struct kbase_mem_pool, reclaim); + + pool_dbg(pool, "reclaim scan %ld:\n", sc->nr_to_scan); + + freed = kbase_mem_pool_shrink(pool, sc->nr_to_scan); + + pool_dbg(pool, "reclaim freed %ld pages\n", freed); + + return freed; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) +static int kbase_mem_pool_reclaim_shrink(struct shrinker *s, + struct shrink_control *sc) +{ + if (sc->nr_to_scan == 0) + return kbase_mem_pool_reclaim_count_objects(s, sc); + + return kbase_mem_pool_reclaim_scan_objects(s, sc); +} +#endif + +int kbase_mem_pool_init(struct kbase_mem_pool *pool, + size_t max_size, + size_t order, + struct kbase_device *kbdev, + struct kbase_mem_pool *next_pool) +{ + pool->cur_size = 0; + pool->max_size = max_size; + pool->order = order; + pool->kbdev = kbdev; + pool->next_pool = next_pool; + + spin_lock_init(&pool->pool_lock); + INIT_LIST_HEAD(&pool->page_list); + + /* Register shrinker */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) + pool->reclaim.shrink = kbase_mem_pool_reclaim_shrink; +#else + pool->reclaim.count_objects = kbase_mem_pool_reclaim_count_objects; + pool->reclaim.scan_objects = kbase_mem_pool_reclaim_scan_objects; +#endif + pool->reclaim.seeks = DEFAULT_SEEKS; + /* Kernel versions prior to 3.1 : + * struct shrinker does not define batch */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) + pool->reclaim.batch = 0; +#endif + register_shrinker(&pool->reclaim); + + pool_dbg(pool, "initialized\n"); + + return 0; +} + +void kbase_mem_pool_term(struct kbase_mem_pool *pool) +{ + struct kbase_mem_pool *next_pool = pool->next_pool; + struct page *p; + size_t nr_to_spill = 0; + LIST_HEAD(spill_list); + int i; + + pool_dbg(pool, "terminate()\n"); + + unregister_shrinker(&pool->reclaim); + + kbase_mem_pool_lock(pool); + pool->max_size = 0; + + if (next_pool && !kbase_mem_pool_is_full(next_pool)) { + /* Spill to next pool (may overspill) */ + nr_to_spill = kbase_mem_pool_capacity(next_pool); + nr_to_spill = min(kbase_mem_pool_size(pool), nr_to_spill); + + /* Zero pages first without holding the next_pool lock */ + for (i = 0; i < nr_to_spill; i++) { + p = kbase_mem_pool_remove_locked(pool); + kbase_mem_pool_zero_page(pool, p); + list_add(&p->lru, &spill_list); + } + } + + while (!kbase_mem_pool_is_empty(pool)) { + /* Free remaining pages to kernel */ + p = kbase_mem_pool_remove_locked(pool); + kbase_mem_pool_free_page(pool, p); + } + + kbase_mem_pool_unlock(pool); + + if (next_pool && nr_to_spill) { + /* Add new page list to next_pool */ + kbase_mem_pool_add_list(next_pool, &spill_list, nr_to_spill); + + pool_dbg(pool, "terminate() spilled %zu pages\n", nr_to_spill); + } + + pool_dbg(pool, "terminated\n"); +} + +struct page *kbase_mem_pool_alloc(struct kbase_mem_pool *pool) +{ + struct page *p; + + do { + pool_dbg(pool, "alloc()\n"); + p = kbase_mem_pool_remove(pool); + + if (p) + return p; + + pool = pool->next_pool; + } while (pool); + + return NULL; +} + +void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *p, + bool dirty) +{ + struct kbase_mem_pool *next_pool = pool->next_pool; + + pool_dbg(pool, "free()\n"); + + if (!kbase_mem_pool_is_full(pool)) { + /* Add to our own pool */ + if (dirty) + kbase_mem_pool_sync_page(pool, p); + + kbase_mem_pool_add(pool, p); + } else if (next_pool && !kbase_mem_pool_is_full(next_pool)) { + /* Spill to next pool */ + kbase_mem_pool_spill(next_pool, p); + } else { + /* Free page */ + kbase_mem_pool_free_page(pool, p); + } +} + +int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_4k_pages, + struct tagged_addr *pages, bool partial_allowed) +{ + struct page *p; + size_t nr_from_pool; + size_t i = 0; + int err = -ENOMEM; + size_t nr_pages_internal; + + nr_pages_internal = nr_4k_pages / (1u << (pool->order)); + + if (nr_pages_internal * (1u << pool->order) != nr_4k_pages) + return -EINVAL; + + pool_dbg(pool, "alloc_pages(4k=%zu):\n", nr_4k_pages); + pool_dbg(pool, "alloc_pages(internal=%zu):\n", nr_pages_internal); + + /* Get pages from this pool */ + kbase_mem_pool_lock(pool); + nr_from_pool = min(nr_pages_internal, kbase_mem_pool_size(pool)); + while (nr_from_pool--) { + int j; + p = kbase_mem_pool_remove_locked(pool); + if (pool->order) { + pages[i++] = as_tagged_tag(page_to_phys(p), + HUGE_HEAD | HUGE_PAGE); + for (j = 1; j < (1u << pool->order); j++) + pages[i++] = as_tagged_tag(page_to_phys(p) + + PAGE_SIZE * j, + HUGE_PAGE); + } else { + pages[i++] = as_tagged(page_to_phys(p)); + } + } + kbase_mem_pool_unlock(pool); + + if (i != nr_4k_pages && pool->next_pool) { + /* Allocate via next pool */ + err = kbase_mem_pool_alloc_pages(pool->next_pool, + nr_4k_pages - i, pages + i, partial_allowed); + + if (err < 0) + goto err_rollback; + + i += err; + } else { + /* Get any remaining pages from kernel */ + while (i != nr_4k_pages) { + p = kbase_mem_alloc_page(pool); + if (!p) { + if (partial_allowed) + goto done; + else + goto err_rollback; + } + + if (pool->order) { + int j; + + pages[i++] = as_tagged_tag(page_to_phys(p), + HUGE_PAGE | + HUGE_HEAD); + for (j = 1; j < (1u << pool->order); j++) { + phys_addr_t phys; + + phys = page_to_phys(p) + PAGE_SIZE * j; + pages[i++] = as_tagged_tag(phys, + HUGE_PAGE); + } + } else { + pages[i++] = as_tagged(page_to_phys(p)); + } + } + } + +done: + pool_dbg(pool, "alloc_pages(%zu) done\n", i); + + return i; + +err_rollback: + kbase_mem_pool_free_pages(pool, i, pages, NOT_DIRTY, NOT_RECLAIMED); + return err; +} + +static void kbase_mem_pool_add_array(struct kbase_mem_pool *pool, + size_t nr_pages, struct tagged_addr *pages, + bool zero, bool sync) +{ + struct page *p; + size_t nr_to_pool = 0; + LIST_HEAD(new_page_list); + size_t i; + + if (!nr_pages) + return; + + pool_dbg(pool, "add_array(%zu, zero=%d, sync=%d):\n", + nr_pages, zero, sync); + + /* Zero/sync pages first without holding the pool lock */ + for (i = 0; i < nr_pages; i++) { + if (unlikely(!as_phys_addr_t(pages[i]))) + continue; + + if (is_huge_head(pages[i]) || !is_huge(pages[i])) { + p = phys_to_page(as_phys_addr_t(pages[i])); + if (zero) + kbase_mem_pool_zero_page(pool, p); + else if (sync) + kbase_mem_pool_sync_page(pool, p); + + list_add(&p->lru, &new_page_list); + nr_to_pool++; + } + pages[i] = as_tagged(0); + } + + /* Add new page list to pool */ + kbase_mem_pool_add_list(pool, &new_page_list, nr_to_pool); + + pool_dbg(pool, "add_array(%zu) added %zu pages\n", + nr_pages, nr_to_pool); +} + +void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, + struct tagged_addr *pages, bool dirty, bool reclaimed) +{ + struct kbase_mem_pool *next_pool = pool->next_pool; + struct page *p; + size_t nr_to_pool; + LIST_HEAD(to_pool_list); + size_t i = 0; + + pool_dbg(pool, "free_pages(%zu):\n", nr_pages); + + if (!reclaimed) { + /* Add to this pool */ + nr_to_pool = kbase_mem_pool_capacity(pool); + nr_to_pool = min(nr_pages, nr_to_pool); + + kbase_mem_pool_add_array(pool, nr_to_pool, pages, false, dirty); + + i += nr_to_pool; + + if (i != nr_pages && next_pool) { + /* Spill to next pool (may overspill) */ + nr_to_pool = kbase_mem_pool_capacity(next_pool); + nr_to_pool = min(nr_pages - i, nr_to_pool); + + kbase_mem_pool_add_array(next_pool, nr_to_pool, + pages + i, true, dirty); + i += nr_to_pool; + } + } + + /* Free any remaining pages to kernel */ + for (; i < nr_pages; i++) { + if (unlikely(!as_phys_addr_t(pages[i]))) + continue; + + if (is_huge(pages[i]) && !is_huge_head(pages[i])) { + pages[i] = as_tagged(0); + continue; + } + + p = phys_to_page(as_phys_addr_t(pages[i])); + + if (reclaimed) + zone_page_state_add(-1, page_zone(p), + NR_SLAB_RECLAIMABLE); + + kbase_mem_pool_free_page(pool, p); + pages[i] = as_tagged(0); + } + + pool_dbg(pool, "free_pages(%zu) done\n", nr_pages); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c new file mode 100644 index 000000000000..319cf2568aba --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c @@ -0,0 +1,88 @@ +/* + * + * (C) COPYRIGHT 2014-2015, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include + +#ifdef CONFIG_DEBUG_FS + +static int kbase_mem_pool_debugfs_size_get(void *data, u64 *val) +{ + struct kbase_mem_pool *pool = (struct kbase_mem_pool *)data; + + *val = kbase_mem_pool_size(pool); + + return 0; +} + +static int kbase_mem_pool_debugfs_size_set(void *data, u64 val) +{ + struct kbase_mem_pool *pool = (struct kbase_mem_pool *)data; + + kbase_mem_pool_trim(pool, val); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(kbase_mem_pool_debugfs_size_fops, + kbase_mem_pool_debugfs_size_get, + kbase_mem_pool_debugfs_size_set, + "%llu\n"); + +static int kbase_mem_pool_debugfs_max_size_get(void *data, u64 *val) +{ + struct kbase_mem_pool *pool = (struct kbase_mem_pool *)data; + + *val = kbase_mem_pool_max_size(pool); + + return 0; +} + +static int kbase_mem_pool_debugfs_max_size_set(void *data, u64 val) +{ + struct kbase_mem_pool *pool = (struct kbase_mem_pool *)data; + + kbase_mem_pool_set_max_size(pool, val); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(kbase_mem_pool_debugfs_max_size_fops, + kbase_mem_pool_debugfs_max_size_get, + kbase_mem_pool_debugfs_max_size_set, + "%llu\n"); + +void kbase_mem_pool_debugfs_init(struct dentry *parent, + struct kbase_mem_pool *pool, + struct kbase_mem_pool *lp_pool) +{ + debugfs_create_file("mem_pool_size", S_IRUGO | S_IWUSR, parent, + pool, &kbase_mem_pool_debugfs_size_fops); + + debugfs_create_file("mem_pool_max_size", S_IRUGO | S_IWUSR, parent, + pool, &kbase_mem_pool_debugfs_max_size_fops); + + debugfs_create_file("lp_mem_pool_size", S_IRUGO | S_IWUSR, parent, + lp_pool, &kbase_mem_pool_debugfs_size_fops); + + debugfs_create_file("lp_mem_pool_max_size", S_IRUGO | S_IWUSR, parent, + lp_pool, &kbase_mem_pool_debugfs_max_size_fops); +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.h new file mode 100644 index 000000000000..496eaf3f1e1a --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2014-2015, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_MEM_POOL_DEBUGFS_H +#define _KBASE_MEM_POOL_DEBUGFS_H + +#include + +/** + * kbase_mem_pool_debugfs_init - add debugfs knobs for @pool + * @parent: Parent debugfs dentry + * @pool: Memory pool of small pages to control + * @lp_pool: Memory pool of large pages to control + * + * Adds four debugfs files under @parent: + * - mem_pool_size: get/set the current size of @pool + * - mem_pool_max_size: get/set the max size of @pool + * - lp_mem_pool_size: get/set the current size of @lp_pool + * - lp_mem_pool_max_size: get/set the max size of @lp_pool + */ +void kbase_mem_pool_debugfs_init(struct dentry *parent, + struct kbase_mem_pool *pool, + struct kbase_mem_pool *lp_pool); + +#endif /*_KBASE_MEM_POOL_DEBUGFS_H*/ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c new file mode 100644 index 000000000000..d58fd8d62fde --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c @@ -0,0 +1,121 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS + +/** Show callback for the @c mem_profile debugfs file. + * + * This function is called to get the contents of the @c mem_profile debugfs + * file. This is a report of current memory usage and distribution in userspace. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if it successfully prints data in debugfs entry file, non-zero otherwise + */ +static int kbasep_mem_profile_seq_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + + mutex_lock(&kctx->mem_profile_lock); + + seq_write(sfile, kctx->mem_profile_data, kctx->mem_profile_size); + + seq_putc(sfile, '\n'); + + mutex_unlock(&kctx->mem_profile_lock); + + return 0; +} + +/* + * File operations related to debugfs entry for mem_profile + */ +static int kbasep_mem_profile_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_mem_profile_seq_show, in->i_private); +} + +static const struct file_operations kbasep_mem_profile_debugfs_fops = { + .open = kbasep_mem_profile_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + int err = 0; + + mutex_lock(&kctx->mem_profile_lock); + + dev_dbg(kctx->kbdev->dev, "initialised: %d", + kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)); + + if (!kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)) { + if (!debugfs_create_file("mem_profile", S_IRUGO, + kctx->kctx_dentry, kctx, + &kbasep_mem_profile_debugfs_fops)) { + err = -EAGAIN; + } else { + kbase_ctx_flag_set(kctx, + KCTX_MEM_PROFILE_INITIALIZED); + } + } + + if (kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)) { + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = data; + kctx->mem_profile_size = size; + } else { + kfree(data); + } + + dev_dbg(kctx->kbdev->dev, "returning: %d, initialised: %d", + err, kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)); + + mutex_unlock(&kctx->mem_profile_lock); + + return err; +} + +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx) +{ + mutex_lock(&kctx->mem_profile_lock); + + dev_dbg(kctx->kbdev->dev, "initialised: %d", + kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)); + + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = NULL; + kctx->mem_profile_size = 0; + + mutex_unlock(&kctx->mem_profile_lock); +} + +#else /* CONFIG_DEBUG_FS */ + +int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + kfree(data); + return 0; +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.h new file mode 100644 index 000000000000..a1dc2e0b165b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.h @@ -0,0 +1,59 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_profile_debugfs.h + * Header file for mem profiles entries in debugfs + * + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_H +#define _KBASE_MEM_PROFILE_DEBUGFS_H + +#include +#include + +/** + * @brief Remove entry from Mali memory profile debugfs + */ +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx); + +/** + * @brief Insert @p data to the debugfs file so it can be read by userspace + * + * The function takes ownership of @p data and frees it later when new data + * is inserted. + * + * If the debugfs entry corresponding to the @p kctx doesn't exist, + * an attempt will be made to create it. + * + * @param kctx The context whose debugfs file @p data should be inserted to + * @param data A NULL-terminated string to be inserted to the debugfs file, + * without the trailing new line character + * @param size The length of the @p data string + * @return 0 if @p data inserted correctly + * -EAGAIN in case of error + * @post @ref mem_profile_initialized will be set to @c true + * the first time this function succeeds. + */ +int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size); + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_H*/ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h new file mode 100644 index 000000000000..82f0702974c2 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_mem_profile_debugfs_buf_size.h + * Header file for the size of the buffer to accumulate the histogram report text in + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ +#define _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ + +/** + * The size of the buffer to accumulate the histogram report text in + * @see @ref CCTXP_HIST_BUF_SIZE_MAX_LENGTH_REPORT + */ +#define KBASE_MEM_PROFILE_MAX_BUF_SIZE ((size_t) (64 + ((80 + (56 * 64)) * 15) + 56)) + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_*/ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mmu.c b/drivers/gpu/arm/bifrost/mali_kbase_mmu.c new file mode 100644 index 000000000000..2dd20fc4a05b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mmu.c @@ -0,0 +1,2138 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mmu.c + * Base kernel MMU management. + */ + +/* #define DEBUG 1 */ +#include +#include +#include +#include +#if defined(CONFIG_MALI_GATOR_SUPPORT) +#include +#endif +#include +#include +#include + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#include +#include +#include +#include +#include +#include + +#define KBASE_MMU_PAGE_ENTRIES 512 + +/** + * kbase_mmu_flush_invalidate() - Flush and invalidate the GPU caches. + * @kctx: The KBase context. + * @vpfn: The virtual page frame number to start the flush on. + * @nr: The number of pages to flush. + * @sync: Set if the operation should be synchronous or not. + * + * Issue a cache flush + invalidate to the GPU caches and invalidate the TLBs. + * + * If sync is not set then transactions still in flight when the flush is issued + * may use the old page tables and the data they write will not be written out + * to memory, this function returns after the flush has been issued but + * before all accesses which might effect the flushed region have completed. + * + * If sync is set then accesses in the flushed region will be drained + * before data is flush and invalidated through L1, L2 and into memory, + * after which point this function will return. + */ +static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, + u64 vpfn, size_t nr, bool sync); + +/** + * kbase_mmu_sync_pgd - sync page directory to memory + * @kbdev: Device pointer. + * @handle: Address of DMA region. + * @size: Size of the region to sync. + * + * This should be called after each page directory update. + */ + +static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, + dma_addr_t handle, size_t size) +{ + /* If page table is not coherent then ensure the gpu can read + * the pages from memory + */ + if (kbdev->system_coherency != COHERENCY_ACE) + dma_sync_single_for_device(kbdev->dev, handle, size, + DMA_TO_DEVICE); +} + +/* + * Definitions: + * - PGD: Page Directory. + * - PTE: Page Table Entry. A 64bit value pointing to the next + * level of translation + * - ATE: Address Transation Entry. A 64bit value pointing to + * a 4kB physical page. + */ + +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str); + + +static size_t make_multiple(size_t minimum, size_t multiple) +{ + size_t remainder = minimum % multiple; + + if (remainder == 0) + return minimum; + + return minimum + multiple - remainder; +} + +void page_fault_worker(struct work_struct *data) +{ + u64 fault_pfn; + u32 fault_status; + size_t new_pages; + size_t fault_rel_pfn; + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; + struct kbase_va_region *region; + int err; + bool grown = false; + + faulting_as = container_of(data, struct kbase_as, work_pagefault); + fault_pfn = faulting_as->fault_addr >> PAGE_SHIFT; + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); + if (WARN_ON(!kctx)) { + atomic_dec(&kbdev->faults_pending); + return; + } + + KBASE_DEBUG_ASSERT(kctx->kbdev == kbdev); + + if (unlikely(faulting_as->protected_mode)) + { + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Protected mode fault"); + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + + goto fault_done; + } + + fault_status = faulting_as->fault_status; + switch (fault_status & AS_FAULTSTATUS_EXCEPTION_CODE_MASK) { + + case AS_FAULTSTATUS_EXCEPTION_CODE_TRANSLATION_FAULT: + /* need to check against the region to handle this one */ + break; + + case AS_FAULTSTATUS_EXCEPTION_CODE_PERMISSION_FAULT: + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Permission failure"); + goto fault_done; + + case AS_FAULTSTATUS_EXCEPTION_CODE_TRANSTAB_BUS_FAULT: + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Translation table bus fault"); + goto fault_done; + + case AS_FAULTSTATUS_EXCEPTION_CODE_ACCESS_FLAG: + /* nothing to do, but we don't expect this fault currently */ + dev_warn(kbdev->dev, "Access flag unexpectedly set"); + goto fault_done; + + case AS_FAULTSTATUS_EXCEPTION_CODE_ADDRESS_SIZE_FAULT: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Address size fault"); + else + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Unknown fault code"); + goto fault_done; + + case AS_FAULTSTATUS_EXCEPTION_CODE_MEMORY_ATTRIBUTES_FAULT: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory attributes fault"); + else + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Unknown fault code"); + goto fault_done; + + default: + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Unknown fault code"); + goto fault_done; + } + + /* so we have a translation fault, let's see if it is for growable + * memory */ + kbase_gpu_vm_lock(kctx); + + region = kbase_region_tracker_find_region_enclosing_address(kctx, + faulting_as->fault_addr); + if (!region || region->flags & KBASE_REG_FREE) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not mapped on the GPU"); + goto fault_done; + } + + if (region->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "DMA-BUF is not mapped on the GPU"); + goto fault_done; + } + + if ((region->flags & GROWABLE_FLAGS_REQUIRED) + != GROWABLE_FLAGS_REQUIRED) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not growable"); + goto fault_done; + } + + if ((region->flags & KBASE_REG_DONT_NEED)) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Don't need memory can't be grown"); + goto fault_done; + } + + /* find the size we need to grow it by */ + /* we know the result fit in a size_t due to kbase_region_tracker_find_region_enclosing_address + * validating the fault_adress to be within a size_t from the start_pfn */ + fault_rel_pfn = fault_pfn - region->start_pfn; + + if (fault_rel_pfn < kbase_reg_current_backed_size(region)) { + dev_dbg(kbdev->dev, "Page fault @ 0x%llx in allocated region 0x%llx-0x%llx of growable TMEM: Ignoring", + faulting_as->fault_addr, region->start_pfn, + region->start_pfn + + kbase_reg_current_backed_size(region)); + + mutex_lock(&kbdev->mmu_hw_mutex); + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* [1] in case another page fault occurred while we were + * handling the (duplicate) page fault we need to ensure we + * don't loose the other page fault as result of us clearing + * the MMU IRQ. Therefore, after we clear the MMU IRQ we send + * an UNLOCK command that will retry any stalled memory + * transaction (which should cause the other page fault to be + * raised again). + */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, NULL, 0, 0, + AS_COMMAND_UNLOCK, 1); + + mutex_unlock(&kbdev->mmu_hw_mutex); + + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + + goto fault_done; + } + + new_pages = make_multiple(fault_rel_pfn - + kbase_reg_current_backed_size(region) + 1, + region->extent); + + /* cap to max vsize */ + if (new_pages + kbase_reg_current_backed_size(region) > + region->nr_pages) + new_pages = region->nr_pages - + kbase_reg_current_backed_size(region); + + if (0 == new_pages) { + mutex_lock(&kbdev->mmu_hw_mutex); + + /* Duplicate of a fault we've already handled, nothing to do */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* See comment [1] about UNLOCK usage */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, NULL, 0, 0, + AS_COMMAND_UNLOCK, 1); + + mutex_unlock(&kbdev->mmu_hw_mutex); + + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + goto fault_done; + } + + if (kbase_alloc_phy_pages_helper(region->gpu_alloc, new_pages) == 0) { + if (region->gpu_alloc != region->cpu_alloc) { + if (kbase_alloc_phy_pages_helper( + region->cpu_alloc, new_pages) == 0) { + grown = true; + } else { + kbase_free_phy_pages_helper(region->gpu_alloc, + new_pages); + } + } else { + grown = true; + } + } + + + if (grown) { + u64 pfn_offset; + u32 op; + + /* alloc success */ + KBASE_DEBUG_ASSERT(kbase_reg_current_backed_size(region) <= region->nr_pages); + + /* set up the new pages */ + pfn_offset = kbase_reg_current_backed_size(region) - new_pages; + /* + * Note: + * Issuing an MMU operation will unlock the MMU and cause the + * translation to be replayed. If the page insertion fails then + * rather then trying to continue the context should be killed + * so the no_flush version of insert_pages is used which allows + * us to unlock the MMU as we see fit. + */ + err = kbase_mmu_insert_pages_no_flush(kctx, + region->start_pfn + pfn_offset, + &kbase_get_gpu_phy_pages(region)[pfn_offset], + new_pages, region->flags); + if (err) { + kbase_free_phy_pages_helper(region->gpu_alloc, new_pages); + if (region->gpu_alloc != region->cpu_alloc) + kbase_free_phy_pages_helper(region->cpu_alloc, + new_pages); + kbase_gpu_vm_unlock(kctx); + /* The locked VA region will be unlocked and the cache invalidated in here */ + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page table update failure"); + goto fault_done; + } +#if defined(CONFIG_MALI_GATOR_SUPPORT) + kbase_trace_mali_page_fault_insert_pages(as_no, new_pages); +#endif + KBASE_TLSTREAM_AUX_PAGEFAULT(kctx->id, (u64)new_pages); + + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + + /* flush L2 and unlock the VA (resumes the MMU) */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6367)) + op = AS_COMMAND_FLUSH; + else + op = AS_COMMAND_FLUSH_PT; + + /* clear MMU interrupt - this needs to be done after updating + * the page tables but before issuing a FLUSH command. The + * FLUSH cmd has a side effect that it restarts stalled memory + * transactions in other address spaces which may cause + * another fault to occur. If we didn't clear the interrupt at + * this stage a new IRQ might not be raised when the GPU finds + * a MMU IRQ is already pending. + */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + + kbase_mmu_hw_do_operation(kbdev, faulting_as, kctx, + faulting_as->fault_addr >> PAGE_SHIFT, + new_pages, + op, 1); + + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + + /* reenable this in the mask */ + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + } else { + /* failed to extend, handle as a normal PF */ + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page allocation failure"); + } + +fault_done: + /* + * By this point, the fault was handled in some way, + * so release the ctx refcount + */ + kbasep_js_runpool_release_ctx(kbdev, kctx); + + atomic_dec(&kbdev->faults_pending); +} + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx) +{ + u64 *page; + int i; + struct page *p; + int new_page_count __maybe_unused; + + KBASE_DEBUG_ASSERT(NULL != kctx); + new_page_count = kbase_atomic_add_pages(1, &kctx->used_pages); + kbase_atomic_add_pages(1, &kctx->kbdev->memdev.used_pages); + + p = kbase_mem_pool_alloc(&kctx->mem_pool); + if (!p) + goto sub_pages; + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); + + page = kmap(p); + if (NULL == page) + goto alloc_free; + + kbase_process_page_usage_inc(kctx, 1); + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) + kctx->kbdev->mmu_mode->entry_invalidate(&page[i]); + + kbase_mmu_sync_pgd(kctx->kbdev, kbase_dma_addr(p), PAGE_SIZE); + + kunmap(p); + return page_to_phys(p); + +alloc_free: + kbase_mem_pool_free(&kctx->mem_pool, p, false); +sub_pages: + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_alloc_pgd); + +/* Given PGD PFN for level N, return PGD PFN for level N+1, allocating the + * new table from the pool if needed and possible + */ +static int mmu_get_next_pgd(struct kbase_context *kctx, + phys_addr_t *pgd, u64 vpfn, int level) +{ + u64 *page; + phys_addr_t target_pgd; + struct page *p; + + KBASE_DEBUG_ASSERT(*pgd); + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->mmu_lock); + + /* + * Architecture spec defines level-0 as being the top-most. + * This is a bit unfortunate here, but we keep the same convention. + */ + vpfn >>= (3 - level) * 9; + vpfn &= 0x1FF; + + p = pfn_to_page(PFN_DOWN(*pgd)); + page = kmap(p); + if (NULL == page) { + dev_warn(kctx->kbdev->dev, "mmu_get_next_pgd: kmap failure\n"); + return -EINVAL; + } + + target_pgd = kctx->kbdev->mmu_mode->pte_to_phy_addr(page[vpfn]); + + if (!target_pgd) { + target_pgd = kbase_mmu_alloc_pgd(kctx); + if (!target_pgd) { + dev_dbg(kctx->kbdev->dev, "mmu_get_next_pgd: kbase_mmu_alloc_pgd failure\n"); + kunmap(p); + return -ENOMEM; + } + + kctx->kbdev->mmu_mode->entry_set_pte(&page[vpfn], target_pgd); + + kbase_mmu_sync_pgd(kctx->kbdev, kbase_dma_addr(p), PAGE_SIZE); + /* Rely on the caller to update the address space flags. */ + } + + kunmap(p); + *pgd = target_pgd; + + return 0; +} + +/* + * Returns the PGD for the specified level of translation + */ +static int mmu_get_pgd_at_level(struct kbase_context *kctx, + u64 vpfn, + unsigned int level, + phys_addr_t *out_pgd) +{ + phys_addr_t pgd; + int l; + + lockdep_assert_held(&kctx->mmu_lock); + pgd = kctx->pgd; + + for (l = MIDGARD_MMU_TOPLEVEL; l < level; l++) { + int err = mmu_get_next_pgd(kctx, &pgd, vpfn, l); + /* Handle failure condition */ + if (err) { + dev_dbg(kctx->kbdev->dev, + "%s: mmu_get_next_pgd failure at level %d\n", + __func__, l); + return err; + } + } + + *out_pgd = pgd; + + return 0; +} + +#define mmu_get_bottom_pgd(kctx, vpfn, out_pgd) \ + mmu_get_pgd_at_level((kctx), (vpfn), MIDGARD_MMU_BOTTOMLEVEL, (out_pgd)) + + +static void mmu_insert_pages_failure_recovery(struct kbase_context *kctx, + u64 from_vpfn, u64 to_vpfn) +{ + phys_addr_t pgd; + u64 vpfn = from_vpfn; + struct kbase_mmu_mode const *mmu_mode; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (U64_MAX / PAGE_SIZE)); + KBASE_DEBUG_ASSERT(from_vpfn <= to_vpfn); + + lockdep_assert_held(&kctx->mmu_lock); + lockdep_assert_held(&kctx->reg_lock); + + mmu_mode = kctx->kbdev->mmu_mode; + + while (vpfn < to_vpfn) { + unsigned int i; + unsigned int idx = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - idx; + unsigned int pcount = 0; + unsigned int left = to_vpfn - vpfn; + unsigned int level; + u64 *page; + + if (count > left) + count = left; + + /* need to check if this is a 2MB page or a 4kB */ + pgd = kctx->pgd; + + for (level = MIDGARD_MMU_TOPLEVEL; + level <= MIDGARD_MMU_BOTTOMLEVEL; level++) { + idx = (vpfn >> ((3 - level) * 9)) & 0x1FF; + page = kmap(phys_to_page(pgd)); + if (mmu_mode->ate_is_valid(page[idx], level)) + break; /* keep the mapping */ + kunmap(phys_to_page(pgd)); + pgd = mmu_mode->pte_to_phy_addr(page[idx]); + } + + switch (level) { + case MIDGARD_MMU_LEVEL(2): + /* remap to single entry to update */ + pcount = 1; + break; + case MIDGARD_MMU_BOTTOMLEVEL: + /* page count is the same as the logical count */ + pcount = count; + break; + default: + dev_warn(kctx->kbdev->dev, "%sNo support for ATEs at level %d\n", + __func__, level); + goto next; + } + + /* Invalidate the entries we added */ + for (i = 0; i < pcount; i++) + mmu_mode->entry_invalidate(&page[idx + i]); + + kbase_mmu_sync_pgd(kctx->kbdev, + kbase_dma_addr(phys_to_page(pgd)) + 8 * idx, + 8 * pcount); + kunmap(phys_to_page(pgd)); + +next: + vpfn += count; + } +} + +/* + * Map the single page 'phys' 'nr' of times, starting at GPU PFN 'vpfn' + */ +int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + /* In case the insert_single_page only partially completes we need to be + * able to recover */ + bool recover_required = false; + u64 recover_vpfn = vpfn; + size_t recover_count = 0; + size_t remain = nr; + int err; + struct kbase_mmu_mode const *mmu_mode; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (U64_MAX / PAGE_SIZE)); + + mmu_mode = kctx->kbdev->mmu_mode; + + /* Early out if there is nothing to do */ + if (nr == 0) + return 0; + + mutex_lock(&kctx->mmu_lock); + + while (remain) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > remain) + count = remain; + + /* + * Repeatedly calling mmu_get_bottom_pte() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + do { + err = mmu_get_bottom_pgd(kctx, vpfn, &pgd); + if (err != -ENOMEM) + break; + /* Fill the memory pool with enough pages for + * the page walk to succeed + */ + mutex_unlock(&kctx->mmu_lock); + err = kbase_mem_pool_grow(&kctx->mem_pool, + MIDGARD_MMU_BOTTOMLEVEL); + mutex_lock(&kctx->mmu_lock); + } while (!err); + if (err) { + dev_warn(kctx->kbdev->dev, "kbase_mmu_insert_pages: mmu_get_bottom_pgd failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_vpfn + + recover_count + ); + } + goto fail_unlock; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kbase_mmu_insert_pages: kmap failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_vpfn + + recover_count + ); + } + err = -ENOMEM; + goto fail_unlock; + } + + for (i = 0; i < count; i++) { + unsigned int ofs = index + i; + + /* Fail if the current page is a valid ATE entry */ + KBASE_DEBUG_ASSERT(0 == (pgd_page[ofs] & 1UL)); + + mmu_mode->entry_set_ate(&pgd_page[ofs], + phys, flags, + MIDGARD_MMU_BOTTOMLEVEL); + } + + vpfn += count; + remain -= count; + + kbase_mmu_sync_pgd(kctx->kbdev, + kbase_dma_addr(p) + (index * sizeof(u64)), + count * sizeof(u64)); + + kunmap(p); + /* We have started modifying the page table. + * If further pages need inserting and fail we need to undo what + * has already taken place */ + recover_required = true; + recover_count += count; + } + mutex_unlock(&kctx->mmu_lock); + kbase_mmu_flush_invalidate(kctx, vpfn, nr, false); + return 0; + +fail_unlock: + mutex_unlock(&kctx->mmu_lock); + kbase_mmu_flush_invalidate(kctx, vpfn, nr, false); + return err; +} + +static inline void cleanup_empty_pte(struct kbase_context *kctx, u64 *pte) +{ + phys_addr_t tmp_pgd; + struct page *tmp_p; + + tmp_pgd = kctx->kbdev->mmu_mode->pte_to_phy_addr(*pte); + tmp_p = phys_to_page(tmp_pgd); + kbase_mem_pool_free(&kctx->mem_pool, tmp_p, false); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); +} + +int kbase_mmu_insert_pages_no_flush(struct kbase_context *kctx, + const u64 start_vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + u64 insert_vpfn = start_vpfn; + size_t remain = nr; + int err; + struct kbase_mmu_mode const *mmu_mode; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(start_vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(start_vpfn <= (U64_MAX / PAGE_SIZE)); + + mmu_mode = kctx->kbdev->mmu_mode; + + /* Early out if there is nothing to do */ + if (nr == 0) + return 0; + + mutex_lock(&kctx->mmu_lock); + + while (remain) { + unsigned int i; + unsigned int vindex = insert_vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - vindex; + struct page *p; + unsigned int cur_level; + + if (count > remain) + count = remain; + + if (!vindex && is_huge_head(*phys)) + cur_level = MIDGARD_MMU_LEVEL(2); + else + cur_level = MIDGARD_MMU_BOTTOMLEVEL; + + /* + * Repeatedly calling mmu_get_pgd_at_level() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + do { + err = mmu_get_pgd_at_level(kctx, insert_vpfn, cur_level, + &pgd); + if (err != -ENOMEM) + break; + /* Fill the memory pool with enough pages for + * the page walk to succeed + */ + mutex_unlock(&kctx->mmu_lock); + err = kbase_mem_pool_grow(&kctx->mem_pool, + cur_level); + mutex_lock(&kctx->mmu_lock); + } while (!err); + + if (err) { + dev_warn(kctx->kbdev->dev, + "%s: mmu_get_bottom_pgd failure\n", __func__); + if (insert_vpfn != start_vpfn) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + start_vpfn, + insert_vpfn); + } + goto fail_unlock; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "%s: kmap failure\n", + __func__); + if (insert_vpfn != start_vpfn) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + start_vpfn, + insert_vpfn); + } + err = -ENOMEM; + goto fail_unlock; + } + + if (cur_level == MIDGARD_MMU_LEVEL(2)) { + unsigned int level_index = (insert_vpfn >> 9) & 0x1FF; + u64 *target = &pgd_page[level_index]; + + if (mmu_mode->pte_is_valid(*target, cur_level)) + cleanup_empty_pte(kctx, target); + mmu_mode->entry_set_ate(target, *phys, flags, + cur_level); + } else { + for (i = 0; i < count; i++) { + unsigned int ofs = vindex + i; + u64 *target = &pgd_page[ofs]; + + /* Fail if the current page is a valid ATE entry + */ + KBASE_DEBUG_ASSERT(0 == (*target & 1UL)); + + kctx->kbdev->mmu_mode->entry_set_ate(target, + phys[i], flags, cur_level); + } + } + + phys += count; + insert_vpfn += count; + remain -= count; + + kbase_mmu_sync_pgd(kctx->kbdev, + kbase_dma_addr(p) + (vindex * sizeof(u64)), + count * sizeof(u64)); + + kunmap(p); + } + + mutex_unlock(&kctx->mmu_lock); + return 0; + +fail_unlock: + mutex_unlock(&kctx->mmu_lock); + return err; +} + +/* + * Map 'nr' pages pointed to by 'phys' at GPU PFN 'vpfn' + */ +int kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags) +{ + int err; + + err = kbase_mmu_insert_pages_no_flush(kctx, vpfn, phys, nr, flags); + kbase_mmu_flush_invalidate(kctx, vpfn, nr, false); + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages); + +/** + * kbase_mmu_flush_invalidate_noretain() - Flush and invalidate the GPU caches + * without retaining the kbase context. + * @kctx: The KBase context. + * @vpfn: The virtual page frame number to start the flush on. + * @nr: The number of pages to flush. + * @sync: Set if the operation should be synchronous or not. + * + * As per kbase_mmu_flush_invalidate but doesn't retain the kctx or do any + * other locking. + */ +static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx, + u64 vpfn, size_t nr, bool sync) +{ + struct kbase_device *kbdev = kctx->kbdev; + int err; + u32 op; + + /* Early out if there is nothing to do */ + if (nr == 0) + return; + + if (sync) + op = AS_COMMAND_FLUSH_MEM; + else + op = AS_COMMAND_FLUSH_PT; + + err = kbase_mmu_hw_do_operation(kbdev, + &kbdev->as[kctx->as_nr], + kctx, vpfn, nr, op, 0); +#if KBASE_GPU_RESET_EN + if (err) { + /* Flush failed to complete, assume the + * GPU has hung and perform a reset to + * recover */ + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n"); + + if (kbase_prepare_to_reset_gpu_locked(kbdev)) + kbase_reset_gpu_locked(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + +#ifndef CONFIG_MALI_NO_MALI + /* + * As this function could be called in interrupt context the sync + * request can't block. Instead log the request and the next flush + * request will pick it up. + */ + if ((!err) && sync && + kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) + atomic_set(&kctx->drain_pending, 1); +#endif /* !CONFIG_MALI_NO_MALI */ +} + +static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, + u64 vpfn, size_t nr, bool sync) +{ + struct kbase_device *kbdev; + bool ctx_is_in_runpool; +#ifndef CONFIG_MALI_NO_MALI + bool drain_pending = false; + + if (atomic_xchg(&kctx->drain_pending, 0)) + drain_pending = true; +#endif /* !CONFIG_MALI_NO_MALI */ + + /* Early out if there is nothing to do */ + if (nr == 0) + return; + + kbdev = kctx->kbdev; + mutex_lock(&kbdev->js_data.queue_mutex); + ctx_is_in_runpool = kbasep_js_runpool_retain_ctx(kbdev, kctx); + mutex_unlock(&kbdev->js_data.queue_mutex); + + if (ctx_is_in_runpool) { + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + if (!kbase_pm_context_active_handle_suspend(kbdev, + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + int err; + u32 op; + + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + + if (sync) + op = AS_COMMAND_FLUSH_MEM; + else + op = AS_COMMAND_FLUSH_PT; + + err = kbase_mmu_hw_do_operation(kbdev, + &kbdev->as[kctx->as_nr], + kctx, vpfn, nr, op, 0); + +#if KBASE_GPU_RESET_EN + if (err) { + /* Flush failed to complete, assume the + * GPU has hung and perform a reset to + * recover */ + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issueing GPU soft-reset to recover\n"); + + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + +#ifndef CONFIG_MALI_NO_MALI + /* + * The transaction lock must be dropped before here + * as kbase_wait_write_flush could take it if + * the GPU was powered down (static analysis doesn't + * know this can't happen). + */ + drain_pending |= (!err) && sync && + kbase_hw_has_issue(kctx->kbdev, + BASE_HW_ISSUE_6367); + if (drain_pending) { + /* Wait for GPU to flush write buffer */ + kbase_wait_write_flush(kctx); + } +#endif /* !CONFIG_MALI_NO_MALI */ + + kbase_pm_context_idle(kbdev); + } + kbasep_js_runpool_release_ctx(kbdev, kctx); + } +} + +void kbase_mmu_update(struct kbase_context *kctx) +{ + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + lockdep_assert_held(&kctx->kbdev->mmu_hw_mutex); + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the hwaccess_lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + kctx->kbdev->mmu_mode->update(kctx); +} +KBASE_EXPORT_TEST_API(kbase_mmu_update); + +void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + lockdep_assert_held(&kbdev->mmu_hw_mutex); + + kbdev->mmu_mode->disable_as(kbdev, as_nr); +} + +void kbase_mmu_disable(struct kbase_context *kctx) +{ + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the hwaccess_lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + + /* + * The address space is being disabled, drain all knowledge of it out + * from the caches as pages and page tables might be freed after this. + * + * The job scheduler code will already be holding the locks and context + * so just do the flush. + */ + kbase_mmu_flush_invalidate_noretain(kctx, 0, ~0, true); + + kctx->kbdev->mmu_mode->disable_as(kctx->kbdev, kctx->as_nr); +} +KBASE_EXPORT_TEST_API(kbase_mmu_disable); + +/* + * We actually only discard the ATE, and not the page table + * pages. There is a potential DoS here, as we'll leak memory by + * having PTEs that are potentially unused. Will require physical + * page accounting, so MMU pages are part of the process allocation. + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +int kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr) +{ + phys_addr_t pgd; + size_t requested_nr = nr; + struct kbase_mmu_mode const *mmu_mode; + int err = -EFAULT; + + KBASE_DEBUG_ASSERT(NULL != kctx); + beenthere(kctx, "kctx %p vpfn %lx nr %zd", (void *)kctx, (unsigned long)vpfn, nr); + + if (0 == nr) { + /* early out if nothing to do */ + return 0; + } + + mutex_lock(&kctx->mmu_lock); + + mmu_mode = kctx->kbdev->mmu_mode; + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + unsigned int pcount; + unsigned int level; + u64 *page; + + if (count > nr) + count = nr; + + /* need to check if this is a 2MB or a 4kB page */ + pgd = kctx->pgd; + + for (level = MIDGARD_MMU_TOPLEVEL; + level <= MIDGARD_MMU_BOTTOMLEVEL; level++) { + phys_addr_t next_pgd; + + index = (vpfn >> ((3 - level) * 9)) & 0x1FF; + page = kmap(phys_to_page(pgd)); + if (mmu_mode->ate_is_valid(page[index], level)) + break; /* keep the mapping */ + else if (!mmu_mode->pte_is_valid(page[index], level)) { + /* nothing here, advance */ + switch (level) { + case MIDGARD_MMU_LEVEL(0): + count = 134217728; + break; + case MIDGARD_MMU_LEVEL(1): + count = 262144; + break; + case MIDGARD_MMU_LEVEL(2): + count = 512; + break; + case MIDGARD_MMU_LEVEL(3): + count = 1; + break; + } + if (count > nr) + count = nr; + goto next; + } + next_pgd = mmu_mode->pte_to_phy_addr(page[index]); + kunmap(phys_to_page(pgd)); + pgd = next_pgd; + } + + switch (level) { + case MIDGARD_MMU_LEVEL(0): + case MIDGARD_MMU_LEVEL(1): + dev_warn(kctx->kbdev->dev, + "%s: No support for ATEs at level %d\n", + __func__, level); + kunmap(phys_to_page(pgd)); + goto out; + case MIDGARD_MMU_LEVEL(2): + /* can only teardown if count >= 512 */ + if (count >= 512) { + pcount = 1; + } else { + dev_warn(kctx->kbdev->dev, + "%s: limiting teardown as it tries to do a partial 2MB teardown, need 512, but have %d to tear down\n", + __func__, count); + pcount = 0; + } + break; + case MIDGARD_MMU_BOTTOMLEVEL: + /* page count is the same as the logical count */ + pcount = count; + break; + default: + dev_err(kctx->kbdev->dev, + "%s: found non-mapped memory, early out\n", + __func__); + vpfn += count; + nr -= count; + continue; + } + + /* Invalidate the entries we added */ + for (i = 0; i < pcount; i++) + mmu_mode->entry_invalidate(&page[index + i]); + + kbase_mmu_sync_pgd(kctx->kbdev, + kbase_dma_addr(phys_to_page(pgd)) + + 8 * index, 8*pcount); + +next: + kunmap(phys_to_page(pgd)); + vpfn += count; + nr -= count; + } + err = 0; +out: + mutex_unlock(&kctx->mmu_lock); + kbase_mmu_flush_invalidate(kctx, vpfn, requested_nr, true); + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_teardown_pages); + +/** + * Update the entries for specified number of pages pointed to by 'phys' at GPU PFN 'vpfn'. + * This call is being triggered as a response to the changes of the mem attributes + * + * @pre : The caller is responsible for validating the memory attributes + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, + struct tagged_addr *phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + size_t requested_nr = nr; + struct kbase_mmu_mode const *mmu_mode; + int err; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + KBASE_DEBUG_ASSERT(vpfn <= (U64_MAX / PAGE_SIZE)); + + /* Early out if there is nothing to do */ + if (nr == 0) + return 0; + + mutex_lock(&kctx->mmu_lock); + + mmu_mode = kctx->kbdev->mmu_mode; + + dev_warn(kctx->kbdev->dev, "kbase_mmu_update_pages(): updating page share flags on GPU PFN 0x%llx from phys %p, %zu pages", + vpfn, phys, nr); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + size_t count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + do { + err = mmu_get_bottom_pgd(kctx, vpfn, &pgd); + if (err != -ENOMEM) + break; + /* Fill the memory pool with enough pages for + * the page walk to succeed + */ + mutex_unlock(&kctx->mmu_lock); + err = kbase_mem_pool_grow(&kctx->mem_pool, + MIDGARD_MMU_BOTTOMLEVEL); + mutex_lock(&kctx->mmu_lock); + } while (!err); + if (err) { + dev_warn(kctx->kbdev->dev, + "mmu_get_bottom_pgd failure\n"); + goto fail_unlock; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kmap failure\n"); + err = -ENOMEM; + goto fail_unlock; + } + + for (i = 0; i < count; i++) + mmu_mode->entry_set_ate(&pgd_page[index + i], phys[i], + flags, MIDGARD_MMU_BOTTOMLEVEL); + + phys += count; + vpfn += count; + nr -= count; + + kbase_mmu_sync_pgd(kctx->kbdev, + kbase_dma_addr(p) + (index * sizeof(u64)), + count * sizeof(u64)); + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + } + + mutex_unlock(&kctx->mmu_lock); + kbase_mmu_flush_invalidate(kctx, vpfn, requested_nr, true); + return 0; + +fail_unlock: + mutex_unlock(&kctx->mmu_lock); + kbase_mmu_flush_invalidate(kctx, vpfn, requested_nr, true); + return err; +} + +static void mmu_teardown_level(struct kbase_context *kctx, phys_addr_t pgd, + int level, u64 *pgd_page_buffer) +{ + phys_addr_t target_pgd; + struct page *p; + u64 *pgd_page; + int i; + struct kbase_mmu_mode const *mmu_mode; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->mmu_lock); + lockdep_assert_held(&kctx->reg_lock); + + pgd_page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail. */ + KBASE_DEBUG_ASSERT(NULL != pgd_page); + /* Copy the page to our preallocated buffer so that we can minimize + * kmap_atomic usage */ + memcpy(pgd_page_buffer, pgd_page, PAGE_SIZE); + kunmap_atomic(pgd_page); + pgd_page = pgd_page_buffer; + + mmu_mode = kctx->kbdev->mmu_mode; + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + target_pgd = mmu_mode->pte_to_phy_addr(pgd_page[i]); + + if (target_pgd) { + if (mmu_mode->pte_is_valid(pgd_page[i], level)) { + mmu_teardown_level(kctx, + target_pgd, + level + 1, + pgd_page_buffer + + (PAGE_SIZE / sizeof(u64))); + } + } + } + + p = pfn_to_page(PFN_DOWN(pgd)); + kbase_mem_pool_free(&kctx->mem_pool, p, true); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); +} + +int kbase_mmu_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL == kctx->mmu_teardown_pages); + + mutex_init(&kctx->mmu_lock); + + /* Preallocate MMU depth of four pages for mmu_teardown_level to use */ + kctx->mmu_teardown_pages = kmalloc(PAGE_SIZE * 4, GFP_KERNEL); + + if (NULL == kctx->mmu_teardown_pages) + return -ENOMEM; + + return 0; +} + +void kbase_mmu_term(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + kfree(kctx->mmu_teardown_pages); + kctx->mmu_teardown_pages = NULL; +} + +void kbase_mmu_free_pgd(struct kbase_context *kctx) +{ + int new_page_count = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + mutex_lock(&kctx->mmu_lock); + mmu_teardown_level(kctx, kctx->pgd, MIDGARD_MMU_TOPLEVEL, + kctx->mmu_teardown_pages); + mutex_unlock(&kctx->mmu_lock); + + KBASE_TLSTREAM_AUX_PAGESALLOC( + kctx->id, + (u64)new_page_count); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_free_pgd); + +static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd, int level, char ** const buffer, size_t *size_left) +{ + phys_addr_t target_pgd; + u64 *pgd_page; + int i; + size_t size = KBASE_MMU_PAGE_ENTRIES * sizeof(u64) + sizeof(u64); + size_t dump_size; + struct kbase_mmu_mode const *mmu_mode; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->mmu_lock); + + mmu_mode = kctx->kbdev->mmu_mode; + + pgd_page = kmap(pfn_to_page(PFN_DOWN(pgd))); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kbasep_mmu_dump_level: kmap failure\n"); + return 0; + } + + if (*size_left >= size) { + /* A modified physical address that contains the page table level */ + u64 m_pgd = pgd | level; + + /* Put the modified physical address in the output buffer */ + memcpy(*buffer, &m_pgd, sizeof(m_pgd)); + *buffer += sizeof(m_pgd); + + /* Followed by the page table itself */ + memcpy(*buffer, pgd_page, sizeof(u64) * KBASE_MMU_PAGE_ENTRIES); + *buffer += sizeof(u64) * KBASE_MMU_PAGE_ENTRIES; + + *size_left -= size; + } + + if (level < MIDGARD_MMU_BOTTOMLEVEL) { + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + if (mmu_mode->pte_is_valid(pgd_page[i], level)) { + target_pgd = mmu_mode->pte_to_phy_addr( + pgd_page[i]); + + dump_size = kbasep_mmu_dump_level(kctx, + target_pgd, level + 1, + buffer, size_left); + if (!dump_size) { + kunmap(pfn_to_page(PFN_DOWN(pgd))); + return 0; + } + size += dump_size; + } + } + } + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + + return size; +} + +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages) +{ + void *kaddr; + size_t size_left; + + KBASE_DEBUG_ASSERT(kctx); + + if (0 == nr_pages) { + /* can't dump in a 0 sized buffer, early out */ + return NULL; + } + + size_left = nr_pages * PAGE_SIZE; + + KBASE_DEBUG_ASSERT(0 != size_left); + kaddr = vmalloc_user(size_left); + + mutex_lock(&kctx->mmu_lock); + + if (kaddr) { + u64 end_marker = 0xFFULL; + char *buffer; + char *mmu_dump_buffer; + u64 config[3]; + size_t dump_size, size = 0; + + buffer = (char *)kaddr; + mmu_dump_buffer = buffer; + + if (kctx->api_version >= KBASE_API_VERSION(8, 4)) { + struct kbase_mmu_setup as_setup; + + kctx->kbdev->mmu_mode->get_as_setup(kctx, &as_setup); + config[0] = as_setup.transtab; + config[1] = as_setup.memattr; + config[2] = as_setup.transcfg; + memcpy(buffer, &config, sizeof(config)); + mmu_dump_buffer += sizeof(config); + size_left -= sizeof(config); + size += sizeof(config); + } + + dump_size = kbasep_mmu_dump_level(kctx, + kctx->pgd, + MIDGARD_MMU_TOPLEVEL, + &mmu_dump_buffer, + &size_left); + + if (!dump_size) + goto fail_free; + + size += dump_size; + + /* Add on the size for the end marker */ + size += sizeof(u64); + + if (size > (nr_pages * PAGE_SIZE)) { + /* The buffer isn't big enough - free the memory and return failure */ + goto fail_free; + } + + /* Add the end marker */ + memcpy(mmu_dump_buffer, &end_marker, sizeof(u64)); + } + + mutex_unlock(&kctx->mmu_lock); + return kaddr; + +fail_free: + vfree(kaddr); + mutex_unlock(&kctx->mmu_lock); + return NULL; +} +KBASE_EXPORT_TEST_API(kbase_mmu_dump); + +void bus_fault_worker(struct work_struct *data) +{ + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; +#if KBASE_GPU_RESET_EN + bool reset_status = false; +#endif /* KBASE_GPU_RESET_EN */ + + faulting_as = container_of(data, struct kbase_as, work_busfault); + + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); + if (WARN_ON(!kctx)) { + atomic_dec(&kbdev->faults_pending); + return; + } + + if (unlikely(faulting_as->protected_mode)) + { + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Permission failure"); + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + kbasep_js_runpool_release_ctx(kbdev, kctx); + atomic_dec(&kbdev->faults_pending); + return; + + } + +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "GPU bus error occurred. For this GPU version we now soft-reset as part of bus error recovery\n"); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* NOTE: If GPU already powered off for suspend, we don't need to switch to unmapped */ + if (!kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + unsigned long flags; + + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + + /* Set the MMU into unmapped mode */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_mmu_disable(kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + + kbase_pm_context_idle(kbdev); + } + +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ + + kbasep_js_runpool_release_ctx(kbdev, kctx); + + atomic_dec(&kbdev->faults_pending); +} + +const char *kbase_exception_name(struct kbase_device *kbdev, u32 exception_code) +{ + const char *e; + + switch (exception_code) { + /* Non-Fault Status code */ + case 0x00: + e = "NOT_STARTED/IDLE/OK"; + break; + case 0x01: + e = "DONE"; + break; + case 0x02: + e = "INTERRUPTED"; + break; + case 0x03: + e = "STOPPED"; + break; + case 0x04: + e = "TERMINATED"; + break; + case 0x08: + e = "ACTIVE"; + break; + /* Job exceptions */ + case 0x40: + e = "JOB_CONFIG_FAULT"; + break; + case 0x41: + e = "JOB_POWER_FAULT"; + break; + case 0x42: + e = "JOB_READ_FAULT"; + break; + case 0x43: + e = "JOB_WRITE_FAULT"; + break; + case 0x44: + e = "JOB_AFFINITY_FAULT"; + break; + case 0x48: + e = "JOB_BUS_FAULT"; + break; + case 0x50: + e = "INSTR_INVALID_PC"; + break; + case 0x51: + e = "INSTR_INVALID_ENC"; + break; + case 0x52: + e = "INSTR_TYPE_MISMATCH"; + break; + case 0x53: + e = "INSTR_OPERAND_FAULT"; + break; + case 0x54: + e = "INSTR_TLS_FAULT"; + break; + case 0x55: + e = "INSTR_BARRIER_FAULT"; + break; + case 0x56: + e = "INSTR_ALIGN_FAULT"; + break; + case 0x58: + e = "DATA_INVALID_FAULT"; + break; + case 0x59: + e = "TILE_RANGE_FAULT"; + break; + case 0x5A: + e = "ADDR_RANGE_FAULT"; + break; + case 0x60: + e = "OUT_OF_MEMORY"; + break; + /* GPU exceptions */ + case 0x80: + e = "DELAYED_BUS_FAULT"; + break; + case 0x88: + e = "SHAREABILITY_FAULT"; + break; + /* MMU exceptions */ + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + e = "TRANSLATION_FAULT"; + break; + case 0xC8: + e = "PERMISSION_FAULT"; + break; + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + e = "PERMISSION_FAULT"; + else + e = "UNKNOWN"; + break; + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + e = "TRANSTAB_BUS_FAULT"; + break; + case 0xD8: + e = "ACCESS_FLAG"; + break; + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + e = "ACCESS_FLAG"; + else + e = "UNKNOWN"; + break; + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + e = "ADDRESS_SIZE_FAULT"; + else + e = "UNKNOWN"; + break; + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + e = "MEMORY_ATTRIBUTES_FAULT"; + else + e = "UNKNOWN"; + break; + default: + e = "UNKNOWN"; + break; + }; + + return e; +} + +static const char *access_type_name(struct kbase_device *kbdev, + u32 fault_status) +{ + switch (fault_status & AS_FAULTSTATUS_ACCESS_TYPE_MASK) { + case AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC: + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + return "ATOMIC"; + else + return "UNKNOWN"; + case AS_FAULTSTATUS_ACCESS_TYPE_READ: + return "READ"; + case AS_FAULTSTATUS_ACCESS_TYPE_WRITE: + return "WRITE"; + case AS_FAULTSTATUS_ACCESS_TYPE_EX: + return "EXECUTE"; + default: + WARN_ON(1); + return NULL; + } +} + +/** + * The caller must ensure it's retained the ctx to prevent it from being scheduled out whilst it's being worked on. + */ +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str) +{ + unsigned long flags; + int exception_type; + int access_type; + int source_id; + int as_no; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + +#if KBASE_GPU_RESET_EN + bool reset_status = false; +#endif + + as_no = as->number; + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + + /* ASSERT that the context won't leave the runpool */ + KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0); + + /* decode the fault status */ + exception_type = as->fault_status & 0xFF; + access_type = (as->fault_status >> 8) & 0x3; + source_id = (as->fault_status >> 16); + + /* terminal fault, print info about the fault */ + dev_err(kbdev->dev, + "Unhandled Page fault in AS%d at VA 0x%016llX\n" + "Reason: %s\n" + "raw fault status: 0x%X\n" + "decoded fault status: %s\n" + "exception type 0x%X: %s\n" + "access type 0x%X: %s\n" + "source id 0x%X\n" + "pid: %d\n", + as_no, as->fault_addr, + reason_str, + as->fault_status, + (as->fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), + exception_type, kbase_exception_name(kbdev, exception_type), + access_type, access_type_name(kbdev, as->fault_status), + source_id, + kctx->pid); + + /* hardware counters dump fault handling */ + if ((kbdev->hwcnt.kctx) && (kbdev->hwcnt.kctx->as_nr == as_no) && + (kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_DUMPING)) { + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + + if ((as->fault_addr >= kbdev->hwcnt.addr) && + (as->fault_addr < (kbdev->hwcnt.addr + + (num_core_groups * 2048)))) + kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_FAULT; + } + + /* Stop the kctx from submitting more jobs and cause it to be scheduled + * out/rescheduled - this will occur on releasing the context's refcount */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + /* Kill any running jobs from the context. Submit is disallowed, so no more jobs from this + * context can appear in the job slots from this point on */ + kbase_backend_jm_kill_jobs_from_kctx(kctx); + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "Unhandled page fault. For this GPU version we now soft-reset the GPU as part of page fault recovery."); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_mmu_disable(kctx); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + /* Clear down the fault */ + kbase_mmu_hw_clear_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); + kbase_mmu_hw_enable_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); + +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ +} + +void kbasep_as_do_poke(struct work_struct *work) +{ + struct kbase_as *as; + struct kbase_device *kbdev; + struct kbase_context *kctx; + unsigned long flags; + + KBASE_DEBUG_ASSERT(work); + as = container_of(work, struct kbase_as, poke_work); + kbdev = container_of(as, struct kbase_device, as[as->number]); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + /* GPU power will already be active by virtue of the caller holding a JS + * reference on the address space, and will not release it until this worker + * has finished */ + + /* Further to the comment above, we know that while this function is running + * the AS will not be released as before the atom is released this workqueue + * is flushed (in kbase_as_poking_timer_release_atom) + */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as->number); + + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + /* Force a uTLB invalidate */ + kbase_mmu_hw_do_operation(kbdev, as, kctx, 0, 0, + AS_COMMAND_UNLOCK, 0); + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (as->poke_refcount && + !(as->poke_state & KBASE_AS_POKE_STATE_KILLING_POKE)) { + /* Only queue up the timer if we need it, and we're not trying to kill it */ + hrtimer_start(&as->poke_timer, HR_TIMER_DELAY_MSEC(5), HRTIMER_MODE_REL); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer) +{ + struct kbase_as *as; + int queue_work_ret; + + KBASE_DEBUG_ASSERT(NULL != timer); + as = container_of(timer, struct kbase_as, poke_timer); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + return HRTIMER_NORESTART; +} + +/** + * Retain the poking timer on an atom's context (if the atom hasn't already + * done so), and start the timer (if it's not already started). + * + * This must only be called on a context that's scheduled in, and an atom + * that's running on the GPU. + * + * The caller must hold hwaccess_lock + * + * This can be called safely from atomic context + */ +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (katom->poking) + return; + + katom->poking = 1; + + /* It's safe to work on the as/as_nr without an explicit reference, + * because the caller holds the hwaccess_lock, and the atom itself + * was also running and had already taken a reference */ + as = &kbdev->as[kctx->as_nr]; + + if (++(as->poke_refcount) == 1) { + /* First refcount for poke needed: check if not already in flight */ + if (!as->poke_state) { + /* need to start poking */ + as->poke_state |= KBASE_AS_POKE_STATE_IN_FLIGHT; + queue_work(as->poke_wq, &as->poke_work); + } + } +} + +/** + * If an atom holds a poking timer, release it and wait for it to finish + * + * This must only be called on a context that's scheduled in, and an atom + * that still has a JS reference on the context + * + * This must \b not be called from atomic context, since it can sleep. + */ +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + if (!katom->poking) + return; + + as = &kbdev->as[kctx->as_nr]; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + KBASE_DEBUG_ASSERT(as->poke_refcount > 0); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + if (--(as->poke_refcount) == 0) { + as->poke_state |= KBASE_AS_POKE_STATE_KILLING_POKE; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + hrtimer_cancel(&as->poke_timer); + flush_workqueue(as->poke_wq); + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Re-check whether it's still needed */ + if (as->poke_refcount) { + int queue_work_ret; + /* Poking still needed: + * - Another retain will not be starting the timer or queueing work, + * because it's still marked as in-flight + * - The hrtimer has finished, and has not started a new timer or + * queued work because it's been marked as killing + * + * So whatever happens now, just queue the work again */ + as->poke_state &= ~((kbase_as_poke_state)KBASE_AS_POKE_STATE_KILLING_POKE); + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + } else { + /* It isn't - so mark it as not in flight, and not killing */ + as->poke_state = 0u; + + /* The poke associated with the atom has now finished. If this is + * also the last atom on the context, then we can guarentee no more + * pokes (and thus no more poking register accesses) will occur on + * the context until new atoms are run */ + } + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + katom->poking = 0; +} + +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_as *as) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (!kctx) { + dev_warn(kbdev->dev, "%s in AS%d at 0x%016llx with no context present! Suprious IRQ or SW Design Error?\n", + kbase_as_has_bus_fault(as) ? "Bus error" : "Page fault", + as->number, as->fault_addr); + + /* Since no ctx was found, the MMU must be disabled. */ + WARN_ON(as->current_setup.transtab); + + if (kbase_as_has_bus_fault(as)) { + kbase_mmu_hw_clear_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + kbase_mmu_hw_enable_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + } else if (kbase_as_has_page_fault(as)) { + kbase_mmu_hw_clear_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); + kbase_mmu_hw_enable_fault(kbdev, as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); + } + +#if KBASE_GPU_RESET_EN + if (kbase_as_has_bus_fault(as) && + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + bool reset_status; + /* + * Reset the GPU, like in bus_fault_worker, in case an + * earlier error hasn't been properly cleared by this + * point. + */ + dev_err(kbdev->dev, "GPU bus error occurred. For this GPU version we now soft-reset as part of bus error recovery\n"); + reset_status = kbase_prepare_to_reset_gpu_locked(kbdev); + if (reset_status) + kbase_reset_gpu_locked(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + + return; + } + + if (kbase_as_has_bus_fault(as)) { + /* + * hw counters dumping in progress, signal the + * other thread that it failed + */ + if ((kbdev->hwcnt.kctx == kctx) && + (kbdev->hwcnt.backend.state == + KBASE_INSTR_STATE_DUMPING)) + kbdev->hwcnt.backend.state = + KBASE_INSTR_STATE_FAULT; + + /* + * Stop the kctx from submitting more jobs and cause it + * to be scheduled out/rescheduled when all references + * to it are released + */ + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) + dev_warn(kbdev->dev, + "Bus error in AS%d at VA=0x%016llx, IPA=0x%016llx\n", + as->number, as->fault_addr, + as->fault_extra_addr); + else + dev_warn(kbdev->dev, "Bus error in AS%d at 0x%016llx\n", + as->number, as->fault_addr); + + /* + * We need to switch to UNMAPPED mode - but we do this in a + * worker so that we can sleep + */ + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_busfault)); + WARN_ON(work_pending(&as->work_busfault)); + queue_work(as->pf_wq, &as->work_busfault); + atomic_inc(&kbdev->faults_pending); + } else { + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_pagefault)); + WARN_ON(work_pending(&as->work_pagefault)); + queue_work(as->pf_wq, &as->work_pagefault); + atomic_inc(&kbdev->faults_pending); + } +} + +void kbase_flush_mmu_wqs(struct kbase_device *kbdev) +{ + int i; + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + struct kbase_as *as = &kbdev->as[i]; + + flush_workqueue(as->pf_wq); + } +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mmu_hw.h b/drivers/gpu/arm/bifrost/mali_kbase_mmu_hw.h new file mode 100644 index 000000000000..986e959e9a0c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mmu_hw.h @@ -0,0 +1,123 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Interface file for accessing MMU hardware functionality + */ + +/** + * @page mali_kbase_mmu_hw_page MMU hardware interface + * + * @section mali_kbase_mmu_hw_intro_sec Introduction + * This module provides an abstraction for accessing the functionality provided + * by the midgard MMU and thus allows all MMU HW access to be contained within + * one common place and allows for different backends (implementations) to + * be provided. + */ + +#ifndef _MALI_KBASE_MMU_HW_H_ +#define _MALI_KBASE_MMU_HW_H_ + +/* Forward declarations */ +struct kbase_device; +struct kbase_as; +struct kbase_context; + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup mali_kbase_mmu_hw MMU access APIs + * @{ + */ + +/** @brief MMU fault type descriptor. + */ +enum kbase_mmu_fault_type { + KBASE_MMU_FAULT_TYPE_UNKNOWN = 0, + KBASE_MMU_FAULT_TYPE_PAGE, + KBASE_MMU_FAULT_TYPE_BUS, + KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED, + KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED +}; + +/** @brief Configure an address space for use. + * + * Configure the MMU using the address space details setup in the + * @ref kbase_context structure. + * + * @param[in] kbdev kbase device to configure. + * @param[in] as address space to configure. + * @param[in] kctx kbase context to configure. + */ +void kbase_mmu_hw_configure(struct kbase_device *kbdev, + struct kbase_as *as, struct kbase_context *kctx); + +/** @brief Issue an operation to the MMU. + * + * Issue an operation (MMU invalidate, MMU flush, etc) on the address space that + * is associated with the provided @ref kbase_context over the specified range + * + * @param[in] kbdev kbase device to issue the MMU operation on. + * @param[in] as address space to issue the MMU operation on. + * @param[in] kctx kbase context to issue the MMU operation on. + * @param[in] vpfn MMU Virtual Page Frame Number to start the + * operation on. + * @param[in] nr Number of pages to work on. + * @param[in] type Operation type (written to ASn_COMMAND). + * @param[in] handling_irq Is this operation being called during the handling + * of an interrupt? + * + * @return Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 type, + unsigned int handling_irq); + +/** @brief Clear a fault that has been previously reported by the MMU. + * + * Clear a bus error or page fault that has been reported by the MMU. + * + * @param[in] kbdev kbase device to clear the fault from. + * @param[in] as address space to clear the fault from. + * @param[in] kctx kbase context to clear the fault from or NULL. + * @param[in] type The type of fault that needs to be cleared. + */ +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @brief Enable fault that has been previously reported by the MMU. + * + * After a page fault or bus error has been reported by the MMU these + * will be disabled. After these are handled this function needs to be + * called to enable the page fault or bus error fault again. + * + * @param[in] kbdev kbase device to again enable the fault from. + * @param[in] as address space to again enable the fault from. + * @param[in] kctx kbase context to again enable the fault from. + * @param[in] type The type of fault that needs to be enabled again. + */ +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @} *//* end group mali_kbase_mmu_hw */ +/** @} *//* end group base_kbase_api */ + +#endif /* _MALI_KBASE_MMU_HW_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_aarch64.c b/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_aarch64.c new file mode 100644 index 000000000000..0fb717b67af9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_aarch64.c @@ -0,0 +1,214 @@ +/* + * + * (C) COPYRIGHT 2010-2014, 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include "mali_kbase.h" +#include "mali_midg_regmap.h" +#include "mali_kbase_defs.h" + +#define ENTRY_TYPE_MASK 3ULL +/* For valid ATEs bit 1 = ((level == 3) ? 1 : 0). + * Valid ATE entries at level 3 are flagged with the value 3. + * Valid ATE entries at level 0-2 are flagged with the value 1. + */ +#define ENTRY_IS_ATE_L3 3ULL +#define ENTRY_IS_ATE_L02 1ULL +#define ENTRY_IS_INVAL 2ULL +#define ENTRY_IS_PTE 3ULL + +#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ +#define ENTRY_ACCESS_RW (1ULL << 6) /* bits 6:7 */ +#define ENTRY_ACCESS_RO (3ULL << 6) +#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ +#define ENTRY_ACCESS_BIT (1ULL << 10) +#define ENTRY_NX_BIT (1ULL << 54) + +/* Helper Function to perform assignment of page table entries, to + * ensure the use of strd, which is required on LPAE systems. + */ +static inline void page_table_entry_set(u64 *pte, u64 phy) +{ +#ifdef CONFIG_64BIT + *pte = phy; +#elif defined(CONFIG_ARM) + /* + * In order to prevent the compiler keeping cached copies of + * memory, we have to explicitly say that we have updated memory. + * + * Note: We could manually move the data ourselves into R0 and + * R1 by specifying register variables that are explicitly + * given registers assignments, the down side of this is that + * we have to assume cpu endianness. To avoid this we can use + * the ldrd to read the data from memory into R0 and R1 which + * will respect the cpu endianness, we then use strd to make + * the 64 bit assignment to the page table entry. + */ + asm volatile("ldrd r0, r1, [%[ptemp]]\n\t" + "strd r0, r1, [%[pte]]\n\t" + : "=m" (*pte) + : [ptemp] "r" (&phy), [pte] "r" (pte), "m" (phy) + : "r0", "r1"); +#else +#error "64-bit atomic write must be implemented for your architecture" +#endif +} + +static void mmu_get_as_setup(struct kbase_context *kctx, + struct kbase_mmu_setup * const setup) +{ + /* Set up the required caching policies at the correct indices + * in the memattr register. + */ + setup->memattr = + (AS_MEMATTR_IMPL_DEF_CACHE_POLICY << + (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) | + (AS_MEMATTR_FORCE_TO_CACHE_ALL << + (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) | + (AS_MEMATTR_WRITE_ALLOC << + (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) | + (AS_MEMATTR_AARCH64_OUTER_IMPL_DEF << + (AS_MEMATTR_INDEX_OUTER_IMPL_DEF * 8)) | + (AS_MEMATTR_AARCH64_OUTER_WA << + (AS_MEMATTR_INDEX_OUTER_WA * 8)); + + setup->transtab = (u64)kctx->pgd & AS_TRANSTAB_BASE_MASK; + setup->transcfg = AS_TRANSCFG_ADRMODE_AARCH64_4K; +} + +static void mmu_update(struct kbase_context *kctx) +{ + struct kbase_device * const kbdev = kctx->kbdev; + struct kbase_as * const as = &kbdev->as[kctx->as_nr]; + struct kbase_mmu_setup * const current_setup = &as->current_setup; + + mmu_get_as_setup(kctx, current_setup); + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +static void mmu_disable_as(struct kbase_device *kbdev, int as_nr) +{ + struct kbase_as * const as = &kbdev->as[as_nr]; + struct kbase_mmu_setup * const current_setup = &as->current_setup; + + current_setup->transtab = 0ULL; + current_setup->transcfg = AS_TRANSCFG_ADRMODE_UNMAPPED; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, NULL); +} + +static phys_addr_t pte_to_phy_addr(u64 entry) +{ + if (!(entry & 1)) + return 0; + + return entry & ~0xFFF; +} + +static int ate_is_valid(u64 ate, unsigned int level) +{ + if (level == MIDGARD_MMU_BOTTOMLEVEL) + return ((ate & ENTRY_TYPE_MASK) == ENTRY_IS_ATE_L3); + else + return ((ate & ENTRY_TYPE_MASK) == ENTRY_IS_ATE_L02); +} + +static int pte_is_valid(u64 pte, unsigned int level) +{ + /* PTEs cannot exist at the bottom level */ + if (level == MIDGARD_MMU_BOTTOMLEVEL) + return false; + return ((pte & ENTRY_TYPE_MASK) == ENTRY_IS_PTE); +} + +/* + * Map KBASE_REG flags to MMU flags + */ +static u64 get_mmu_flags(unsigned long flags) +{ + u64 mmu_flags; + + /* store mem_attr index as 4:2 (macro called ensures 3 bits already) */ + mmu_flags = KBASE_REG_MEMATTR_VALUE(flags) << 2; + + /* Set access flags - note that AArch64 stage 1 does not support + * write-only access, so we use read/write instead + */ + if (flags & KBASE_REG_GPU_WR) + mmu_flags |= ENTRY_ACCESS_RW; + else if (flags & KBASE_REG_GPU_RD) + mmu_flags |= ENTRY_ACCESS_RO; + + /* nx if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_NX) ? ENTRY_NX_BIT : 0; + + if (flags & KBASE_REG_SHARE_BOTH) { + /* inner and outer shareable */ + mmu_flags |= SHARE_BOTH_BITS; + } else if (flags & KBASE_REG_SHARE_IN) { + /* inner shareable coherency */ + mmu_flags |= SHARE_INNER_BITS; + } + + return mmu_flags; +} + +static void entry_set_ate(u64 *entry, + struct tagged_addr phy, + unsigned long flags, + unsigned int level) +{ + if (level == MIDGARD_MMU_BOTTOMLEVEL) + page_table_entry_set(entry, as_phys_addr_t(phy) | + get_mmu_flags(flags) | + ENTRY_ACCESS_BIT | ENTRY_IS_ATE_L3); + else + page_table_entry_set(entry, as_phys_addr_t(phy) | + get_mmu_flags(flags) | + ENTRY_ACCESS_BIT | ENTRY_IS_ATE_L02); +} + +static void entry_set_pte(u64 *entry, phys_addr_t phy) +{ + page_table_entry_set(entry, (phy & PAGE_MASK) | + ENTRY_ACCESS_BIT | ENTRY_IS_PTE); +} + +static void entry_invalidate(u64 *entry) +{ + page_table_entry_set(entry, ENTRY_IS_INVAL); +} + +static struct kbase_mmu_mode const aarch64_mode = { + .update = mmu_update, + .get_as_setup = mmu_get_as_setup, + .disable_as = mmu_disable_as, + .pte_to_phy_addr = pte_to_phy_addr, + .ate_is_valid = ate_is_valid, + .pte_is_valid = pte_is_valid, + .entry_set_ate = entry_set_ate, + .entry_set_pte = entry_set_pte, + .entry_invalidate = entry_invalidate +}; + +struct kbase_mmu_mode const *kbase_mmu_mode_get_aarch64(void) +{ + return &aarch64_mode; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_lpae.c b/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_lpae.c new file mode 100644 index 000000000000..f080fdc0be88 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mmu_mode_lpae.c @@ -0,0 +1,199 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include "mali_kbase.h" +#include "mali_midg_regmap.h" +#include "mali_kbase_defs.h" + +#define ENTRY_TYPE_MASK 3ULL +#define ENTRY_IS_ATE 1ULL +#define ENTRY_IS_INVAL 2ULL +#define ENTRY_IS_PTE 3ULL + +#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ +#define ENTRY_RD_BIT (1ULL << 6) +#define ENTRY_WR_BIT (1ULL << 7) +#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ +#define ENTRY_ACCESS_BIT (1ULL << 10) +#define ENTRY_NX_BIT (1ULL << 54) + +#define ENTRY_FLAGS_MASK (ENTRY_ATTR_BITS | ENTRY_RD_BIT | ENTRY_WR_BIT | \ + ENTRY_SHARE_BITS | ENTRY_ACCESS_BIT | ENTRY_NX_BIT) + +/* Helper Function to perform assignment of page table entries, to + * ensure the use of strd, which is required on LPAE systems. + */ +static inline void page_table_entry_set(u64 *pte, u64 phy) +{ +#ifdef CONFIG_64BIT + *pte = phy; +#elif defined(CONFIG_ARM) + /* + * In order to prevent the compiler keeping cached copies of + * memory, we have to explicitly say that we have updated + * memory. + * + * Note: We could manually move the data ourselves into R0 and + * R1 by specifying register variables that are explicitly + * given registers assignments, the down side of this is that + * we have to assume cpu endianness. To avoid this we can use + * the ldrd to read the data from memory into R0 and R1 which + * will respect the cpu endianness, we then use strd to make + * the 64 bit assignment to the page table entry. + */ + asm volatile("ldrd r0, r1, [%[ptemp]]\n\t" + "strd r0, r1, [%[pte]]\n\t" + : "=m" (*pte) + : [ptemp] "r" (&phy), [pte] "r" (pte), "m" (phy) + : "r0", "r1"); +#else +#error "64-bit atomic write must be implemented for your architecture" +#endif +} + +static void mmu_get_as_setup(struct kbase_context *kctx, + struct kbase_mmu_setup * const setup) +{ + /* Set up the required caching policies at the correct indices + * in the memattr register. */ + setup->memattr = + (AS_MEMATTR_LPAE_IMPL_DEF_CACHE_POLICY << + (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) | + (AS_MEMATTR_LPAE_FORCE_TO_CACHE_ALL << + (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) | + (AS_MEMATTR_LPAE_WRITE_ALLOC << + (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) | + (AS_MEMATTR_LPAE_OUTER_IMPL_DEF << + (AS_MEMATTR_INDEX_OUTER_IMPL_DEF * 8)) | + (AS_MEMATTR_LPAE_OUTER_WA << + (AS_MEMATTR_INDEX_OUTER_WA * 8)) | + 0; /* The other indices are unused for now */ + + setup->transtab = ((u64)kctx->pgd & + ((0xFFFFFFFFULL << 32) | AS_TRANSTAB_LPAE_ADDR_SPACE_MASK)) | + AS_TRANSTAB_LPAE_ADRMODE_TABLE | + AS_TRANSTAB_LPAE_READ_INNER; + + setup->transcfg = 0; +} + +static void mmu_update(struct kbase_context *kctx) +{ + struct kbase_device * const kbdev = kctx->kbdev; + struct kbase_as * const as = &kbdev->as[kctx->as_nr]; + struct kbase_mmu_setup * const current_setup = &as->current_setup; + + mmu_get_as_setup(kctx, current_setup); + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +static void mmu_disable_as(struct kbase_device *kbdev, int as_nr) +{ + struct kbase_as * const as = &kbdev->as[as_nr]; + struct kbase_mmu_setup * const current_setup = &as->current_setup; + + current_setup->transtab = AS_TRANSTAB_LPAE_ADRMODE_UNMAPPED; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, NULL); +} + +static phys_addr_t pte_to_phy_addr(u64 entry) +{ + if (!(entry & 1)) + return 0; + + return entry & ~0xFFF; +} + +static int ate_is_valid(u64 ate, unsigned int level) +{ + return ((ate & ENTRY_TYPE_MASK) == ENTRY_IS_ATE); +} + +static int pte_is_valid(u64 pte, unsigned int level) +{ + return ((pte & ENTRY_TYPE_MASK) == ENTRY_IS_PTE); +} + +/* + * Map KBASE_REG flags to MMU flags + */ +static u64 get_mmu_flags(unsigned long flags) +{ + u64 mmu_flags; + + /* store mem_attr index as 4:2 (macro called ensures 3 bits already) */ + mmu_flags = KBASE_REG_MEMATTR_VALUE(flags) << 2; + + /* write perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_WR) ? ENTRY_WR_BIT : 0; + /* read perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_RD) ? ENTRY_RD_BIT : 0; + /* nx if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_NX) ? ENTRY_NX_BIT : 0; + + if (flags & KBASE_REG_SHARE_BOTH) { + /* inner and outer shareable */ + mmu_flags |= SHARE_BOTH_BITS; + } else if (flags & KBASE_REG_SHARE_IN) { + /* inner shareable coherency */ + mmu_flags |= SHARE_INNER_BITS; + } + + return mmu_flags; +} + +static void entry_set_ate(u64 *entry, + struct tagged_addr phy, + unsigned long flags, + unsigned int level) +{ + page_table_entry_set(entry, as_phys_addr_t(phy) | get_mmu_flags(flags) | + ENTRY_IS_ATE); +} + +static void entry_set_pte(u64 *entry, phys_addr_t phy) +{ + page_table_entry_set(entry, (phy & ~0xFFF) | ENTRY_IS_PTE); +} + +static void entry_invalidate(u64 *entry) +{ + page_table_entry_set(entry, ENTRY_IS_INVAL); +} + +static struct kbase_mmu_mode const lpae_mode = { + .update = mmu_update, + .get_as_setup = mmu_get_as_setup, + .disable_as = mmu_disable_as, + .pte_to_phy_addr = pte_to_phy_addr, + .ate_is_valid = ate_is_valid, + .pte_is_valid = pte_is_valid, + .entry_set_ate = entry_set_ate, + .entry_set_pte = entry_set_pte, + .entry_invalidate = entry_invalidate +}; + +struct kbase_mmu_mode const *kbase_mmu_mode_get_lpae(void) +{ + return &lpae_mode; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c b/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c new file mode 100644 index 000000000000..0152b35f711b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c @@ -0,0 +1,119 @@ +/* + * + * (C) COPYRIGHT 2011-2014, 2016-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include + + +/* + * This file is included only for type definitions and functions belonging to + * specific platform folders. Do not add dependencies with symbols that are + * defined somewhere else. + */ +#include + +#define PLATFORM_CONFIG_RESOURCE_COUNT 4 +#define PLATFORM_CONFIG_IRQ_RES_COUNT 3 + +static struct platform_device *mali_device; + +#ifndef CONFIG_OF +/** + * @brief Convert data in struct kbase_io_resources struct to Linux-specific resources + * + * Function converts data in struct kbase_io_resources struct to an array of Linux resource structures. Note that function + * assumes that size of linux_resource array is at least PLATFORM_CONFIG_RESOURCE_COUNT. + * Resources are put in fixed order: I/O memory region, job IRQ, MMU IRQ, GPU IRQ. + * + * @param[in] io_resource Input IO resource data + * @param[out] linux_resources Pointer to output array of Linux resource structures + */ +static void kbasep_config_parse_io_resources(const struct kbase_io_resources *io_resources, struct resource *const linux_resources) +{ + if (!io_resources || !linux_resources) { + pr_err("%s: couldn't find proper resources\n", __func__); + return; + } + + memset(linux_resources, 0, PLATFORM_CONFIG_RESOURCE_COUNT * sizeof(struct resource)); + + linux_resources[0].start = io_resources->io_memory_region.start; + linux_resources[0].end = io_resources->io_memory_region.end; + linux_resources[0].flags = IORESOURCE_MEM; + + linux_resources[1].start = io_resources->job_irq_number; + linux_resources[1].end = io_resources->job_irq_number; + linux_resources[1].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[2].start = io_resources->mmu_irq_number; + linux_resources[2].end = io_resources->mmu_irq_number; + linux_resources[2].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[3].start = io_resources->gpu_irq_number; + linux_resources[3].end = io_resources->gpu_irq_number; + linux_resources[3].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; +} +#endif /* CONFIG_OF */ + +int kbase_platform_register(void) +{ + struct kbase_platform_config *config; +#ifndef CONFIG_OF + struct resource resources[PLATFORM_CONFIG_RESOURCE_COUNT]; +#endif + int err; + + config = kbase_get_platform_config(); /* declared in midgard/mali_kbase_config.h but defined in platform folder */ + if (config == NULL) { + pr_err("%s: couldn't get platform config\n", __func__); + return -ENODEV; + } + + mali_device = platform_device_alloc("mali", 0); + if (mali_device == NULL) + return -ENOMEM; + +#ifndef CONFIG_OF + kbasep_config_parse_io_resources(config->io_resources, resources); + err = platform_device_add_resources(mali_device, resources, PLATFORM_CONFIG_RESOURCE_COUNT); + if (err) { + platform_device_put(mali_device); + mali_device = NULL; + return err; + } +#endif /* CONFIG_OF */ + + err = platform_device_add(mali_device); + if (err) { + platform_device_unregister(mali_device); + mali_device = NULL; + return err; + } + + return 0; +} +EXPORT_SYMBOL(kbase_platform_register); + +void kbase_platform_unregister(void) +{ + if (mali_device) + platform_device_unregister(mali_device); +} +EXPORT_SYMBOL(kbase_platform_unregister); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pm.c b/drivers/gpu/arm/bifrost/mali_kbase_pm.c new file mode 100644 index 000000000000..97d543464c28 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_pm.c @@ -0,0 +1,205 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.c + * Base kernel power management APIs + */ + +#include +#include +#include + +#include + +int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags) +{ + return kbase_hwaccess_pm_powerup(kbdev, flags); +} + +void kbase_pm_halt(struct kbase_device *kbdev) +{ + kbase_hwaccess_pm_halt(kbdev); +} + +void kbase_pm_context_active(struct kbase_device *kbdev) +{ + (void)kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE); +} + +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerup. Sometimes the event might be missed due to reading the count + * outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + if (kbase_pm_is_suspending(kbdev)) { + switch (suspend_handler) { + case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE: + if (kbdev->pm.active_count != 0) + break; + /* FALLTHROUGH */ + case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE: + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + return 1; + + case KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE: + /* FALLTHROUGH */ + default: + KBASE_DEBUG_ASSERT_MSG(false, "unreachable"); + break; + } + } + c = ++kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_ACTIVE, NULL, NULL, 0u, c); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + if (c == 1) + /* First context active: Power on the GPU and any cores requested by + * the policy */ + kbase_hwaccess_pm_gpu_active(kbdev); + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_active); + +void kbase_pm_context_idle(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerdown. Sometimes the event might be missed due to reading the + * count outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + mutex_lock(&js_devdata->runpool_mutex); + mutex_lock(&kbdev->pm.lock); + + c = --kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_IDLE, NULL, NULL, 0u, c); + + KBASE_DEBUG_ASSERT(c >= 0); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + if (c == 0) { + /* Last context has gone idle */ + kbase_hwaccess_pm_gpu_idle(kbdev); + + /* Wake up anyone waiting for this to become 0 (e.g. suspend). The + * waiters must synchronize with us by locking the pm.lock after + * waiting */ + wake_up(&kbdev->pm.zero_active_count_wait); + } + + mutex_unlock(&kbdev->pm.lock); + mutex_unlock(&js_devdata->runpool_mutex); +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_idle); + +void kbase_pm_suspend(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); + + /* Suspend vinstr. + * This call will block until vinstr is suspended. */ + kbase_vinstr_suspend(kbdev->vinstr_ctx); + + mutex_lock(&kbdev->pm.lock); + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + kbdev->pm.suspending = true; + mutex_unlock(&kbdev->pm.lock); + + /* From now on, the active count will drop towards zero. Sometimes, it'll + * go up briefly before going down again. However, once it reaches zero it + * will stay there - guaranteeing that we've idled all pm references */ + + /* Suspend job scheduler and associated components, so that it releases all + * the PM active count references */ + kbasep_js_suspend(kbdev); + + /* Wait for the active count to reach zero. This is not the same as + * waiting for a power down, since not all policies power down when this + * reaches zero. */ + wait_event(kbdev->pm.zero_active_count_wait, kbdev->pm.active_count == 0); + + /* NOTE: We synchronize with anything that was just finishing a + * kbase_pm_context_idle() call by locking the pm.lock below */ + + kbase_hwaccess_pm_suspend(kbdev); +} + +void kbase_pm_resume(struct kbase_device *kbdev) +{ + /* MUST happen before any pm_context_active calls occur */ + kbase_hwaccess_pm_resume(kbdev); + + /* Initial active call, to power on the GPU/cores if needed */ + kbase_pm_context_active(kbdev); + + /* Resume any blocked atoms (which may cause contexts to be scheduled in + * and dependent atoms to run) */ + kbase_resume_suspended_soft_jobs(kbdev); + + /* Resume the Job Scheduler and associated components, and start running + * atoms */ + kbasep_js_resume(kbdev); + + /* Matching idle call, to power off the GPU/cores if we didn't actually + * need it and the policy doesn't want it on */ + kbase_pm_context_idle(kbdev); + + /* Resume vinstr operation */ + kbase_vinstr_resume(kbdev->vinstr_ctx); +} + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pm.h b/drivers/gpu/arm/bifrost/mali_kbase_pm.h new file mode 100644 index 000000000000..37fa2479df74 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_pm.h @@ -0,0 +1,171 @@ +/* + * + * (C) COPYRIGHT 2010-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.h + * Power management API definitions + */ + +#ifndef _KBASE_PM_H_ +#define _KBASE_PM_H_ + +#include "mali_kbase_hwaccess_pm.h" + +#define PM_ENABLE_IRQS 0x01 +#define PM_HW_ISSUES_DETECT 0x02 + + +/** Initialize the power management framework. + * + * Must be called before any other power management function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return 0 if the power management framework was successfully initialized. + */ +int kbase_pm_init(struct kbase_device *kbdev); + +/** Power up GPU after all modules have been initialized and interrupt handlers installed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @param flags Flags to pass on to kbase_pm_init_hw + * + * @return 0 if powerup was successful. + */ +int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags); + +/** + * Halt the power management framework. + * Should ensure that no new interrupts are generated, + * but allow any currently running interrupt handlers to complete successfully. + * The GPU is forced off by the time this function returns, regardless of + * whether or not the active power policy asks for the GPU to be powered off. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_halt(struct kbase_device *kbdev); + +/** Terminate the power management framework. + * + * No power management functions may be called after this + * (except @ref kbase_pm_init) + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_term(struct kbase_device *kbdev); + +/** Increment the count of active contexts. + * + * This function should be called when a context is about to submit a job. It informs the active power policy that the + * GPU is going to be in use shortly and the policy is expected to start turning on the GPU. + * + * This function will block until the GPU is available. + * + * This function ASSERTS if a suspend is occuring/has occurred whilst this is + * in use. Use kbase_pm_contect_active_unless_suspending() instead. + * + * @note a Suspend is only visible to Kernel threads; user-space threads in a + * syscall cannot witness a suspend, because they are frozen before the suspend + * begins. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_active(struct kbase_device *kbdev); + + +/** Handler codes for doing kbase_pm_context_active_handle_suspend() */ +enum kbase_pm_suspend_handler { + /** A suspend is not expected/not possible - this is the same as + * kbase_pm_context_active() */ + KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE, + /** If we're suspending, fail and don't increase the active count */ + KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE, + /** If we're suspending, succeed and allow the active count to increase iff + * it didn't go from 0->1 (i.e., we didn't re-activate the GPU). + * + * This should only be used when there is a bounded time on the activation + * (e.g. guarantee it's going to be idled very soon after) */ + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE +}; + +/** Suspend 'safe' variant of kbase_pm_context_active() + * + * If a suspend is in progress, this allows for various different ways of + * handling the suspend. Refer to @ref enum kbase_pm_suspend_handler for details. + * + * We returns a status code indicating whether we're allowed to keep the GPU + * active during the suspend, depending on the handler code. If the status code + * indicates a failure, the caller must abort whatever operation it was + * attempting, and potentially queue it up for after the OS has resumed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param suspend_handler The handler code for how to handle a suspend that might occur + * @return zero Indicates success + * @return non-zero Indicates failure due to the system being suspending/suspended. + */ +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler); + +/** Decrement the reference count of active contexts. + * + * This function should be called when a context becomes idle. After this call the GPU may be turned off by the power + * policy so the calling code should ensure that it does not access the GPU's registers. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_idle(struct kbase_device *kbdev); + +/** + * Suspend the GPU and prevent any further register accesses to it from Kernel + * threads. + * + * This is called in response to an OS suspend event, and calls into the various + * kbase components to complete the suspend. + * + * @note the mechanisms used here rely on all user-space threads being frozen + * by the OS before we suspend. Otherwise, an IOCTL could occur that powers up + * the GPU e.g. via atom submission. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_suspend(struct kbase_device *kbdev); + +/** + * Resume the GPU, allow register accesses to it, and resume running atoms on + * the GPU. + * + * This is called in response to an OS resume event, and calls into the various + * kbase components to complete the resume. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_resume(struct kbase_device *kbdev); + +/** + * kbase_pm_vsync_callback - vsync callback + * + * @buffer_updated: 1 if a new frame was displayed, 0 otherwise + * @data: Pointer to the kbase device as returned by kbase_find_device() + * + * Callback function used to notify the power management code that a vsync has + * occurred on the display. + */ +void kbase_pm_vsync_callback(int buffer_updated, void *data); + +#endif /* _KBASE_PM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_profiling_gator_api.h b/drivers/gpu/arm/bifrost/mali_kbase_profiling_gator_api.h new file mode 100644 index 000000000000..7fb674eded37 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_profiling_gator_api.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2010, 2013 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_profiling_gator_api.h + * Model interface + */ + +#ifndef _KBASE_PROFILING_GATOR_API_H_ +#define _KBASE_PROFILING_GATOR_API_H_ + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control + * the frame buffer dumping and s/w counter reporting. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) +#define FBDUMP_CONTROL_MAX (5) +#define FBDUMP_CONTROL_MIN FBDUMP_CONTROL_ENABLE + +void _mali_profiling_control(u32 action, u32 value); + +#endif /* _KBASE_PROFILING_GATOR_API */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c new file mode 100644 index 000000000000..c970650069cd --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c @@ -0,0 +1,130 @@ +/* + * + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" + +#include "mali_kbase_regs_history_debugfs.h" + +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) + +#include + + +static int regs_history_size_get(void *data, u64 *val) +{ + struct kbase_io_history *const h = data; + + *val = h->size; + + return 0; +} + +static int regs_history_size_set(void *data, u64 val) +{ + struct kbase_io_history *const h = data; + + return kbase_io_history_resize(h, (u16)val); +} + + +DEFINE_SIMPLE_ATTRIBUTE(regs_history_size_fops, + regs_history_size_get, + regs_history_size_set, + "%llu\n"); + + +/** + * regs_history_show - show callback for the register access history file. + * + * @sfile: The debugfs entry + * @data: Data associated with the entry + * + * This function is called to dump all recent accesses to the GPU registers. + * + * @return 0 if successfully prints data in debugfs entry file, failure + * otherwise + */ +static int regs_history_show(struct seq_file *sfile, void *data) +{ + struct kbase_io_history *const h = sfile->private; + u16 i; + size_t iters; + unsigned long flags; + + if (!h->enabled) { + seq_puts(sfile, "The register access history is disabled\n"); + goto out; + } + + spin_lock_irqsave(&h->lock, flags); + + iters = (h->size > h->count) ? h->count : h->size; + seq_printf(sfile, "Last %zu register accesses of %zu total:\n", iters, + h->count); + for (i = 0; i < iters; ++i) { + struct kbase_io_access *io = + &h->buf[(h->count - iters + i) % h->size]; + char const access = (io->addr & 1) ? 'w' : 'r'; + + seq_printf(sfile, "%6i: %c: reg 0x%p val %08x\n", i, access, + (void *)(io->addr & ~0x1), io->value); + } + + spin_unlock_irqrestore(&h->lock, flags); + +out: + return 0; +} + + +/** + * regs_history_open - open operation for regs_history debugfs file + * + * @in: &struct inode pointer + * @file: &struct file pointer + * + * @return file descriptor + */ +static int regs_history_open(struct inode *in, struct file *file) +{ + return single_open(file, ®s_history_show, in->i_private); +} + + +static const struct file_operations regs_history_fops = { + .open = ®s_history_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +void kbasep_regs_history_debugfs_init(struct kbase_device *kbdev) +{ + debugfs_create_bool("regs_history_enabled", S_IRUGO | S_IWUSR, + kbdev->mali_debugfs_directory, + &kbdev->io_history.enabled); + debugfs_create_file("regs_history_size", S_IRUGO | S_IWUSR, + kbdev->mali_debugfs_directory, + &kbdev->io_history, ®s_history_size_fops); + debugfs_create_file("regs_history", S_IRUGO, + kbdev->mali_debugfs_directory, &kbdev->io_history, + ®s_history_fops); +} + + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h new file mode 100644 index 000000000000..f10837002330 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h @@ -0,0 +1,50 @@ +/* + * + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Header file for register access history support via debugfs + * + * This interface is made available via /sys/kernel/debug/mali#/regs_history*. + * + * Usage: + * - regs_history_enabled: whether recording of register accesses is enabled. + * Write 'y' to enable, 'n' to disable. + * - regs_history_size: size of the register history buffer, must be > 0 + * - regs_history: return the information about last accesses to the registers. + */ + +#ifndef _KBASE_REGS_HISTORY_DEBUGFS_H +#define _KBASE_REGS_HISTORY_DEBUGFS_H + +struct kbase_device; + +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) + +/** + * kbasep_regs_history_debugfs_init - add debugfs entries for register history + * + * @kbdev: Pointer to kbase_device containing the register history + */ +void kbasep_regs_history_debugfs_init(struct kbase_device *kbdev); + +#else /* CONFIG_DEBUG_FS */ + +#define kbasep_regs_history_debugfs_init CSTD_NOP + +#endif /* CONFIG_DEBUG_FS */ + +#endif /*_KBASE_REGS_HISTORY_DEBUGFS_H*/ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_replay.c b/drivers/gpu/arm/bifrost/mali_kbase_replay.c new file mode 100644 index 000000000000..2f8eccfc1757 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_replay.c @@ -0,0 +1,1166 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_replay.c + * Replay soft job handlers + */ + +#include +#include +#include +#include +#include + +#define JOB_NOT_STARTED 0 +#define JOB_TYPE_NULL (1) +#define JOB_TYPE_VERTEX (5) +#define JOB_TYPE_TILER (7) +#define JOB_TYPE_FUSED (8) +#define JOB_TYPE_FRAGMENT (9) + +#define JOB_HEADER_32_FBD_OFFSET (31*4) +#define JOB_HEADER_64_FBD_OFFSET (44*4) + +#define FBD_POINTER_MASK (~0x3f) + +#define SFBD_TILER_OFFSET (48*4) + +#define MFBD_TILER_OFFSET (14*4) + +#define FBD_HIERARCHY_WEIGHTS 8 +#define FBD_HIERARCHY_MASK_MASK 0x1fff + +#define FBD_TYPE 1 + +#define HIERARCHY_WEIGHTS 13 + +#define JOB_HEADER_ID_MAX 0xffff + +#define JOB_SOURCE_ID(status) (((status) >> 16) & 0xFFFF) +#define JOB_POLYGON_LIST (0x03) + +struct fragment_job { + struct job_descriptor_header header; + + u32 x[2]; + union { + u64 _64; + u32 _32; + } fragment_fbd; +}; + +static void dump_job_head(struct kbase_context *kctx, char *head_str, + struct job_descriptor_header *job) +{ +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "%s\n", head_str); + dev_dbg(kctx->kbdev->dev, + "addr = %p\n" + "exception_status = %x (Source ID: 0x%x Access: 0x%x Exception: 0x%x)\n" + "first_incomplete_task = %x\n" + "fault_pointer = %llx\n" + "job_descriptor_size = %x\n" + "job_type = %x\n" + "job_barrier = %x\n" + "_reserved_01 = %x\n" + "_reserved_02 = %x\n" + "_reserved_03 = %x\n" + "_reserved_04/05 = %x,%x\n" + "job_index = %x\n" + "dependencies = %x,%x\n", + job, job->exception_status, + JOB_SOURCE_ID(job->exception_status), + (job->exception_status >> 8) & 0x3, + job->exception_status & 0xFF, + job->first_incomplete_task, + job->fault_pointer, job->job_descriptor_size, + job->job_type, job->job_barrier, job->_reserved_01, + job->_reserved_02, job->_reserved_03, + job->_reserved_04, job->_reserved_05, + job->job_index, + job->job_dependency_index_1, + job->job_dependency_index_2); + + if (job->job_descriptor_size) + dev_dbg(kctx->kbdev->dev, "next = %llx\n", + job->next_job._64); + else + dev_dbg(kctx->kbdev->dev, "next = %x\n", + job->next_job._32); +#endif +} + +static int kbasep_replay_reset_sfbd(struct kbase_context *kctx, + u64 fbd_address, u64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct { + u32 padding_1[1]; + u32 flags; + u64 padding_2[2]; + u64 heap_free_address; + u32 padding[8]; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + struct kbase_vmap_struct map; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbase_vmap(kctx, fbd_address + SFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_fbd: failed to map fbd\n"); + return -EINVAL; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, + "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = fbd_tiler->flags & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + dev_dbg(kctx->kbdev->dev, "heap_free_address=%llx flags=%x\n", + fbd_tiler->heap_free_address, fbd_tiler->flags); + + kbase_vunmap(kctx, &map); + + return 0; +} + +static int kbasep_replay_reset_mfbd(struct kbase_context *kctx, + u64 fbd_address, u64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct kbase_vmap_struct map; + struct { + u32 padding_0; + u32 flags; + u64 padding_1[2]; + u64 heap_free_address; + u64 padding_2; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbase_vmap(kctx, fbd_address + MFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_reset_fbd: failed to map fbd\n"); + return -EINVAL; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, + fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = (fbd_tiler->flags) & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, + " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + kbase_vunmap(kctx, &map); + + return 0; +} + +/** + * @brief Reset the status of an FBD pointed to by a tiler job + * + * This performs two functions : + * - Set the hierarchy mask + * - Reset the tiler free heap address + * + * @param[in] kctx Context pointer + * @param[in] job_header Address of job header to reset. + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] job_64 true if this job is using 64-bit + * descriptors + * + * @return 0 on success, error code on failure + */ +static int kbasep_replay_reset_tiler_job(struct kbase_context *kctx, + u64 job_header, u64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight, bool job_64) +{ + struct kbase_vmap_struct map; + u64 fbd_address; + + if (job_64) { + u64 *job_ext; + + job_ext = kbase_vmap(kctx, + job_header + JOB_HEADER_64_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return -EINVAL; + } + + fbd_address = *job_ext; + + kbase_vunmap(kctx, &map); + } else { + u32 *job_ext; + + job_ext = kbase_vmap(kctx, + job_header + JOB_HEADER_32_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return -EINVAL; + } + + fbd_address = *job_ext; + + kbase_vunmap(kctx, &map); + } + + if (fbd_address & FBD_TYPE) { + return kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } else { + return kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } +} + +/** + * @brief Reset the status of a job + * + * This performs the following functions : + * + * - Reset the Job Status field of each job to NOT_STARTED. + * - Set the Job Type field of any Vertex Jobs to Null Job. + * - For any jobs using an FBD, set the Tiler Heap Free field to the value of + * the tiler_heap_free parameter, and set the hierarchy level mask to the + * hier_mask parameter. + * - Offset HW dependencies by the hw_job_id_offset parameter + * - Set the Perform Job Barrier flag if this job is the first in the chain + * - Read the address of the next job header + * + * @param[in] kctx Context pointer + * @param[in,out] job_header Address of job header to reset. Set to address + * of next job header on exit. + * @param[in] prev_jc Previous job chain to link to, if this job is + * the last in the chain. + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] first_in_chain true if this job is the first in the chain + * @param[in] fragment_chain true if this job is in the fragment chain + * + * @return 0 on success, error code on failure + */ +static int kbasep_replay_reset_job(struct kbase_context *kctx, + u64 *job_header, u64 prev_jc, + u64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + bool first_in_chain, bool fragment_chain) +{ + struct fragment_job *frag_job; + struct job_descriptor_header *job; + u64 new_job_header; + struct kbase_vmap_struct map; + + frag_job = kbase_vmap(kctx, *job_header, sizeof(*frag_job), &map); + if (!frag_job) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_parse_jc: failed to map jc\n"); + return -EINVAL; + } + job = &frag_job->header; + + dump_job_head(kctx, "Job header:", job); + + if (job->exception_status == JOB_NOT_STARTED && !fragment_chain) { + dev_err(kctx->kbdev->dev, "Job already not started\n"); + goto out_unmap; + } + job->exception_status = JOB_NOT_STARTED; + + if (job->job_type == JOB_TYPE_VERTEX) + job->job_type = JOB_TYPE_NULL; + + if (job->job_type == JOB_TYPE_FUSED) { + dev_err(kctx->kbdev->dev, "Fused jobs can not be replayed\n"); + goto out_unmap; + } + + if (first_in_chain) + job->job_barrier = 1; + + if ((job->job_dependency_index_1 + hw_job_id_offset) > + JOB_HEADER_ID_MAX || + (job->job_dependency_index_2 + hw_job_id_offset) > + JOB_HEADER_ID_MAX || + (job->job_index + hw_job_id_offset) > JOB_HEADER_ID_MAX) { + dev_err(kctx->kbdev->dev, + "Job indicies/dependencies out of valid range\n"); + goto out_unmap; + } + + if (job->job_dependency_index_1) + job->job_dependency_index_1 += hw_job_id_offset; + if (job->job_dependency_index_2) + job->job_dependency_index_2 += hw_job_id_offset; + + job->job_index += hw_job_id_offset; + + if (job->job_descriptor_size) { + new_job_header = job->next_job._64; + if (!job->next_job._64) + job->next_job._64 = prev_jc; + } else { + new_job_header = job->next_job._32; + if (!job->next_job._32) + job->next_job._32 = prev_jc; + } + dump_job_head(kctx, "Updated to:", job); + + if (job->job_type == JOB_TYPE_TILER) { + bool job_64 = job->job_descriptor_size != 0; + + if (kbasep_replay_reset_tiler_job(kctx, *job_header, + tiler_heap_free, hierarchy_mask, + default_weight, job_64) != 0) + goto out_unmap; + + } else if (job->job_type == JOB_TYPE_FRAGMENT) { + u64 fbd_address; + + if (job->job_descriptor_size) + fbd_address = frag_job->fragment_fbd._64; + else + fbd_address = (u64)frag_job->fragment_fbd._32; + + if (fbd_address & FBD_TYPE) { + if (kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != 0) + goto out_unmap; + } else { + if (kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != 0) + goto out_unmap; + } + } + + kbase_vunmap(kctx, &map); + + *job_header = new_job_header; + + return 0; + +out_unmap: + kbase_vunmap(kctx, &map); + return -EINVAL; +} + +/** + * @brief Find the highest job ID in a job chain + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain start address + * @param[out] hw_job_id Highest job ID in chain + * + * @return 0 on success, error code on failure + */ +static int kbasep_replay_find_hw_job_id(struct kbase_context *kctx, + u64 jc, u16 *hw_job_id) +{ + while (jc) { + struct job_descriptor_header *job; + struct kbase_vmap_struct map; + + dev_dbg(kctx->kbdev->dev, + "kbasep_replay_find_hw_job_id: parsing jc=%llx\n", jc); + + job = kbase_vmap(kctx, jc, sizeof(*job), &map); + if (!job) { + dev_err(kctx->kbdev->dev, "failed to map jc\n"); + + return -EINVAL; + } + + if (job->job_index > *hw_job_id) + *hw_job_id = job->job_index; + + if (job->job_descriptor_size) + jc = job->next_job._64; + else + jc = job->next_job._32; + + kbase_vunmap(kctx, &map); + } + + return 0; +} + +/** + * @brief Reset the status of a number of jobs + * + * This function walks the provided job chain, and calls + * kbasep_replay_reset_job for each job. It also links the job chain to the + * provided previous job chain. + * + * The function will fail if any of the jobs passed already have status of + * NOT_STARTED. + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain to be processed + * @param[in] prev_jc Job chain to be added to. May be NULL + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] fragment_chain true if this chain is the fragment chain + * + * @return 0 on success, error code otherwise + */ +static int kbasep_replay_parse_jc(struct kbase_context *kctx, + u64 jc, u64 prev_jc, + u64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + bool fragment_chain) +{ + bool first_in_chain = true; + int nr_jobs = 0; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: jc=%llx hw_job_id=%x\n", + jc, hw_job_id_offset); + + while (jc) { + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: parsing jc=%llx\n", jc); + + if (kbasep_replay_reset_job(kctx, &jc, prev_jc, + tiler_heap_free, hierarchy_mask, + default_weight, hw_job_id_offset, + first_in_chain, fragment_chain) != 0) + return -EINVAL; + + first_in_chain = false; + + nr_jobs++; + if (fragment_chain && + nr_jobs >= BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT) { + dev_err(kctx->kbdev->dev, + "Exceeded maximum number of jobs in fragment chain\n"); + return -EINVAL; + } + } + + return 0; +} + +/** + * @brief Reset the status of a replay job, and set up dependencies + * + * This performs the actions to allow the replay job to be re-run following + * completion of the passed dependency. + * + * @param[in] katom The atom to be reset + * @param[in] dep_atom The dependency to be attached to the atom + */ +static void kbasep_replay_reset_softjob(struct kbase_jd_atom *katom, + struct kbase_jd_atom *dep_atom) +{ + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + kbase_jd_katom_dep_set(&katom->dep[0], dep_atom, BASE_JD_DEP_TYPE_DATA); + list_add_tail(&katom->dep_item[0], &dep_atom->dep_head[0]); +} + +/** + * @brief Allocate an unused katom + * + * This will search the provided context for an unused katom, and will mark it + * as KBASE_JD_ATOM_STATE_QUEUED. + * + * If no atoms are available then the function will fail. + * + * @param[in] kctx Context pointer + * @return An atom ID, or -1 on failure + */ +static int kbasep_allocate_katom(struct kbase_context *kctx) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + int i; + + for (i = BASE_JD_ATOM_COUNT-1; i > 0; i--) { + if (jctx->atoms[i].status == KBASE_JD_ATOM_STATE_UNUSED) { + jctx->atoms[i].status = KBASE_JD_ATOM_STATE_QUEUED; + dev_dbg(kctx->kbdev->dev, + "kbasep_allocate_katom: Allocated atom %d\n", + i); + return i; + } + } + + return -1; +} + +/** + * @brief Release a katom + * + * This will mark the provided atom as available, and remove any dependencies. + * + * For use on error path. + * + * @param[in] kctx Context pointer + * @param[in] atom_id ID of atom to release + */ +static void kbasep_release_katom(struct kbase_context *kctx, int atom_id) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + + dev_dbg(kctx->kbdev->dev, "kbasep_release_katom: Released atom %d\n", + atom_id); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[0])) + list_del(jctx->atoms[atom_id].dep_head[0].next); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[1])) + list_del(jctx->atoms[atom_id].dep_head[1].next); + + jctx->atoms[atom_id].status = KBASE_JD_ATOM_STATE_UNUSED; +} + +static void kbasep_replay_create_atom(struct kbase_context *kctx, + struct base_jd_atom_v2 *atom, + int atom_nr, + base_jd_prio prio) +{ + atom->nr_extres = 0; + atom->extres_list = 0; + atom->device_nr = 0; + atom->prio = prio; + atom->atom_number = atom_nr; + + base_jd_atom_dep_set(&atom->pre_dep[0], 0 , BASE_JD_DEP_TYPE_INVALID); + base_jd_atom_dep_set(&atom->pre_dep[1], 0 , BASE_JD_DEP_TYPE_INVALID); + + atom->udata.blob[0] = 0; + atom->udata.blob[1] = 0; +} + +/** + * @brief Create two atoms for the purpose of replaying jobs + * + * Two atoms are allocated and created. The jc pointer is not set at this + * stage. The second atom has a dependency on the first. The remaining fields + * are set up as follows : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + * + * @param[out] t_atom Atom to use for tiler jobs + * @param[out] f_atom Atom to use for fragment jobs + * @param[in] prio Priority of new atom (inherited from replay soft + * job) + * @return 0 on success, error code on failure + */ +static int kbasep_replay_create_atoms(struct kbase_context *kctx, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom, + base_jd_prio prio) +{ + int t_atom_nr, f_atom_nr; + + t_atom_nr = kbasep_allocate_katom(kctx); + if (t_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + return -EINVAL; + } + + f_atom_nr = kbasep_allocate_katom(kctx); + if (f_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + kbasep_release_katom(kctx, t_atom_nr); + return -EINVAL; + } + + kbasep_replay_create_atom(kctx, t_atom, t_atom_nr, prio); + kbasep_replay_create_atom(kctx, f_atom, f_atom_nr, prio); + + base_jd_atom_dep_set(&f_atom->pre_dep[0], t_atom_nr , BASE_JD_DEP_TYPE_DATA); + + return 0; +} + +#ifdef CONFIG_MALI_DEBUG +static void payload_dump(struct kbase_context *kctx, base_jd_replay_payload *payload) +{ + u64 next; + + dev_dbg(kctx->kbdev->dev, "Tiler jc list :\n"); + next = payload->tiler_jc_list; + + while (next) { + struct kbase_vmap_struct map; + base_jd_replay_jc *jc_struct; + + jc_struct = kbase_vmap(kctx, next, sizeof(*jc_struct), &map); + + if (!jc_struct) + return; + + dev_dbg(kctx->kbdev->dev, "* jc_struct=%p jc=%llx next=%llx\n", + jc_struct, jc_struct->jc, jc_struct->next); + + next = jc_struct->next; + + kbase_vunmap(kctx, &map); + } +} +#endif + +/** + * @brief Parse a base_jd_replay_payload provided by userspace + * + * This will read the payload from userspace, and parse the job chains. + * + * @param[in] kctx Context pointer + * @param[in] replay_atom Replay soft job atom + * @param[in] t_atom Atom to use for tiler jobs + * @param[in] f_atom Atom to use for fragment jobs + * @return 0 on success, error code on failure + */ +static int kbasep_replay_parse_payload(struct kbase_context *kctx, + struct kbase_jd_atom *replay_atom, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom) +{ + base_jd_replay_payload *payload = NULL; + u64 next; + u64 prev_jc = 0; + u16 hw_job_id_offset = 0; + int ret = -EINVAL; + struct kbase_vmap_struct map; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: replay_atom->jc = %llx sizeof(payload) = %zu\n", + replay_atom->jc, sizeof(payload)); + + payload = kbase_vmap(kctx, replay_atom->jc, sizeof(*payload), &map); + if (!payload) { + dev_err(kctx->kbdev->dev, "kbasep_replay_parse_payload: failed to map payload into kernel space\n"); + return -EINVAL; + } + +#ifdef BASE_LEGACY_UK10_2_SUPPORT + if (KBASE_API_VERSION(10, 3) > replay_atom->kctx->api_version) { + base_jd_replay_payload_uk10_2 *payload_uk10_2; + u16 tiler_core_req; + u16 fragment_core_req; + + payload_uk10_2 = (base_jd_replay_payload_uk10_2 *) payload; + memcpy(&tiler_core_req, &payload_uk10_2->tiler_core_req, + sizeof(tiler_core_req)); + memcpy(&fragment_core_req, &payload_uk10_2->fragment_core_req, + sizeof(fragment_core_req)); + payload->tiler_core_req = (u32)(tiler_core_req & 0x7fff); + payload->fragment_core_req = (u32)(fragment_core_req & 0x7fff); + } +#endif /* BASE_LEGACY_UK10_2_SUPPORT */ + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: payload=%p\n", payload); + dev_dbg(kctx->kbdev->dev, "Payload structure:\n" + "tiler_jc_list = %llx\n" + "fragment_jc = %llx\n" + "tiler_heap_free = %llx\n" + "fragment_hierarchy_mask = %x\n" + "tiler_hierarchy_mask = %x\n" + "hierarchy_default_weight = %x\n" + "tiler_core_req = %x\n" + "fragment_core_req = %x\n", + payload->tiler_jc_list, + payload->fragment_jc, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + payload->tiler_core_req, + payload->fragment_core_req); + payload_dump(kctx, payload); +#endif + t_atom->core_req = payload->tiler_core_req | BASEP_JD_REQ_EVENT_NEVER; + f_atom->core_req = payload->fragment_core_req | BASEP_JD_REQ_EVENT_NEVER; + + /* Sanity check core requirements*/ + if ((t_atom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_T || + (f_atom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_FS || + t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES || + f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + + int t_atom_type = t_atom->core_req & BASE_JD_REQ_ATOM_TYPE & ~BASE_JD_REQ_COHERENT_GROUP; + int f_atom_type = f_atom->core_req & BASE_JD_REQ_ATOM_TYPE & ~BASE_JD_REQ_COHERENT_GROUP & ~BASE_JD_REQ_FS_AFBC; + int t_has_ex_res = t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES; + int f_has_ex_res = f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES; + + if (t_atom_type != BASE_JD_REQ_T) { + dev_err(kctx->kbdev->dev, "Invalid core requirement: Tiler atom not a tiler job. Was: 0x%x\n Expected: 0x%x", + t_atom_type, BASE_JD_REQ_T); + } + if (f_atom_type != BASE_JD_REQ_FS) { + dev_err(kctx->kbdev->dev, "Invalid core requirement: Fragment shader atom not a fragment shader. Was 0x%x Expected: 0x%x\n", + f_atom_type, BASE_JD_REQ_FS); + } + if (t_has_ex_res) { + dev_err(kctx->kbdev->dev, "Invalid core requirement: Tiler atom has external resources.\n"); + } + if (f_has_ex_res) { + dev_err(kctx->kbdev->dev, "Invalid core requirement: Fragment shader atom has external resources.\n"); + } + + goto out; + } + + /* Process tiler job chains */ + next = payload->tiler_jc_list; + if (!next) { + dev_err(kctx->kbdev->dev, "Invalid tiler JC list\n"); + goto out; + } + + while (next) { + base_jd_replay_jc *jc_struct; + struct kbase_vmap_struct jc_map; + u64 jc; + + jc_struct = kbase_vmap(kctx, next, sizeof(*jc_struct), &jc_map); + + if (!jc_struct) { + dev_err(kctx->kbdev->dev, "Failed to map jc struct\n"); + goto out; + } + + jc = jc_struct->jc; + next = jc_struct->next; + if (next) + jc_struct->jc = 0; + + kbase_vunmap(kctx, &jc_map); + + if (jc) { + u16 max_hw_job_id = 0; + + if (kbasep_replay_find_hw_job_id(kctx, jc, + &max_hw_job_id) != 0) + goto out; + + if (kbasep_replay_parse_jc(kctx, jc, prev_jc, + payload->tiler_heap_free, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + hw_job_id_offset, false) != 0) { + goto out; + } + + hw_job_id_offset += max_hw_job_id; + + prev_jc = jc; + } + } + t_atom->jc = prev_jc; + + /* Process fragment job chain */ + f_atom->jc = payload->fragment_jc; + if (kbasep_replay_parse_jc(kctx, payload->fragment_jc, 0, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->hierarchy_default_weight, 0, + true) != 0) { + goto out; + } + + if (!t_atom->jc || !f_atom->jc) { + dev_err(kctx->kbdev->dev, "Invalid payload\n"); + goto out; + } + + dev_dbg(kctx->kbdev->dev, "t_atom->jc=%llx f_atom->jc=%llx\n", + t_atom->jc, f_atom->jc); + ret = 0; + +out: + kbase_vunmap(kctx, &map); + + return ret; +} + +static void kbase_replay_process_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + struct kbase_context *kctx; + struct kbase_jd_context *jctx; + bool need_to_try_schedule_context = false; + + struct base_jd_atom_v2 t_atom, f_atom; + struct kbase_jd_atom *t_katom, *f_katom; + base_jd_prio atom_prio; + + katom = container_of(data, struct kbase_jd_atom, work); + kctx = katom->kctx; + jctx = &kctx->jctx; + + mutex_lock(&jctx->lock); + + atom_prio = kbasep_js_sched_prio_to_atom_prio(katom->sched_priority); + + if (kbasep_replay_create_atoms( + kctx, &t_atom, &f_atom, atom_prio) != 0) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + t_katom = &jctx->atoms[t_atom.atom_number]; + f_katom = &jctx->atoms[f_atom.atom_number]; + + if (kbasep_replay_parse_payload(kctx, katom, &t_atom, &f_atom) != 0) { + kbasep_release_katom(kctx, t_atom.atom_number); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + kbasep_replay_reset_softjob(katom, f_katom); + + need_to_try_schedule_context |= jd_submit_atom(kctx, &t_atom, t_katom); + if (t_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + need_to_try_schedule_context |= jd_submit_atom(kctx, &f_atom, f_katom); + if (f_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + katom->event_code = BASE_JD_EVENT_DONE; + +out: + if (katom->event_code != BASE_JD_EVENT_DONE) { + kbase_disjoint_state_down(kctx->kbdev); + + need_to_try_schedule_context |= jd_done_nolock(katom, NULL); + } + + if (need_to_try_schedule_context) + kbase_js_sched_all(kctx->kbdev); + + mutex_unlock(&jctx->lock); +} + +/** + * @brief Check job replay fault + * + * This will read the job payload, checks fault type and source, then decides + * whether replay is required. + * + * @param[in] katom The atom to be processed + * @return true (success) if replay required or false on failure. + */ +static bool kbase_replay_fault_check(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct device *dev = kctx->kbdev->dev; + base_jd_replay_payload *payload; + u64 job_header; + u64 job_loop_detect; + struct job_descriptor_header *job; + struct kbase_vmap_struct job_map; + struct kbase_vmap_struct map; + bool err = false; + + /* Replay job if fault is of type BASE_JD_EVENT_JOB_WRITE_FAULT or + * if force_replay is enabled. + */ + if (BASE_JD_EVENT_TERMINATED == katom->event_code) { + return false; + } else if (BASE_JD_EVENT_JOB_WRITE_FAULT == katom->event_code) { + return true; + } else if (BASE_JD_EVENT_FORCE_REPLAY == katom->event_code) { + katom->event_code = BASE_JD_EVENT_DATA_INVALID_FAULT; + return true; + } else if (BASE_JD_EVENT_DATA_INVALID_FAULT != katom->event_code) { + /* No replay for faults of type other than + * BASE_JD_EVENT_DATA_INVALID_FAULT. + */ + return false; + } + + /* Job fault is BASE_JD_EVENT_DATA_INVALID_FAULT, now scan fragment jc + * to find out whether the source of exception is POLYGON_LIST. Replay + * is required if the source of fault is POLYGON_LIST. + */ + payload = kbase_vmap(kctx, katom->jc, sizeof(*payload), &map); + if (!payload) { + dev_err(dev, "kbase_replay_fault_check: failed to map payload.\n"); + return false; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(dev, "kbase_replay_fault_check: payload=%p\n", payload); + dev_dbg(dev, "\nPayload structure:\n" + "fragment_jc = 0x%llx\n" + "fragment_hierarchy_mask = 0x%x\n" + "fragment_core_req = 0x%x\n", + payload->fragment_jc, + payload->fragment_hierarchy_mask, + payload->fragment_core_req); +#endif + /* Process fragment job chain */ + job_header = (u64) payload->fragment_jc; + job_loop_detect = job_header; + while (job_header) { + job = kbase_vmap(kctx, job_header, sizeof(*job), &job_map); + if (!job) { + dev_err(dev, "failed to map jc\n"); + /* unmap payload*/ + kbase_vunmap(kctx, &map); + return false; + } + + + dump_job_head(kctx, "\njob_head structure:\n", job); + + /* Replay only when the polygon list reader caused the + * DATA_INVALID_FAULT */ + if ((BASE_JD_EVENT_DATA_INVALID_FAULT == katom->event_code) && + (JOB_POLYGON_LIST == JOB_SOURCE_ID(job->exception_status))) { + err = true; + kbase_vunmap(kctx, &job_map); + break; + } + + /* Move on to next fragment job in the list */ + if (job->job_descriptor_size) + job_header = job->next_job._64; + else + job_header = job->next_job._32; + + kbase_vunmap(kctx, &job_map); + + /* Job chain loop detected */ + if (job_header == job_loop_detect) + break; + } + + /* unmap payload*/ + kbase_vunmap(kctx, &map); + + return err; +} + + +/** + * @brief Process a replay job + * + * Called from kbase_process_soft_job. + * + * On exit, if the job has completed, katom->event_code will have been updated. + * If the job has not completed, and is replaying jobs, then the atom status + * will have been reset to KBASE_JD_ATOM_STATE_QUEUED. + * + * @param[in] katom The atom to be processed + * @return false if the atom has completed + * true if the atom is replaying jobs + */ +bool kbase_replay_process(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + + /* Don't replay this atom if these issues are not present in the + * hardware */ + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_11020) && + !kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_11024)) { + dev_dbg(kbdev->dev, "Hardware does not need replay workaround"); + + /* Signal failure to userspace */ + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + + return false; + } + + if (katom->event_code == BASE_JD_EVENT_DONE) { + dev_dbg(kbdev->dev, "Previous job succeeded - not replaying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kbdev); + + return false; + } + + if (kbase_ctx_flag(kctx, KCTX_DYING)) { + dev_dbg(kbdev->dev, "Not replaying; context is dying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kbdev); + + return false; + } + + /* Check job exception type and source before replaying. */ + if (!kbase_replay_fault_check(katom)) { + dev_dbg(kbdev->dev, + "Replay cancelled on event %x\n", katom->event_code); + /* katom->event_code is already set to the failure code of the + * previous job. + */ + return false; + } + + dev_warn(kbdev->dev, "Replaying jobs retry=%d\n", + katom->retry_count); + + katom->retry_count++; + + if (katom->retry_count > BASEP_JD_REPLAY_LIMIT) { + dev_err(kbdev->dev, "Replay exceeded limit - failing jobs\n"); + + kbase_disjoint_state_down(kbdev); + + /* katom->event_code is already set to the failure code of the + previous job */ + return false; + } + + /* only enter the disjoint state once for the whole time while the replay is ongoing */ + if (katom->retry_count == 1) + kbase_disjoint_state_up(kbdev); + + INIT_WORK(&katom->work, kbase_replay_process_worker); + queue_work(kctx->event_workq, &katom->work); + + return true; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_smc.c b/drivers/gpu/arm/bifrost/mali_kbase_smc.c new file mode 100644 index 000000000000..43175c85988f --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_smc.c @@ -0,0 +1,74 @@ +/* + * + * (C) COPYRIGHT 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifdef CONFIG_ARM64 + +#include +#include + +#include + +static noinline u64 invoke_smc_fid(u64 function_id, + u64 arg0, u64 arg1, u64 arg2) +{ + register u64 x0 asm("x0") = function_id; + register u64 x1 asm("x1") = arg0; + register u64 x2 asm("x2") = arg1; + register u64 x3 asm("x3") = arg2; + + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + __asmeq("%3", "x3") + "smc #0\n" + : "+r" (x0) + : "r" (x1), "r" (x2), "r" (x3)); + + return x0; +} + +u64 kbase_invoke_smc_fid(u32 fid, u64 arg0, u64 arg1, u64 arg2) +{ + /* Is fast call (bit 31 set) */ + KBASE_DEBUG_ASSERT(fid & ~SMC_FAST_CALL); + /* bits 16-23 must be zero for fast calls */ + KBASE_DEBUG_ASSERT((fid & (0xFF << 16)) == 0); + + return invoke_smc_fid(fid, arg0, arg1, arg2); +} + +u64 kbase_invoke_smc(u32 oen, u16 function_number, bool smc64, + u64 arg0, u64 arg1, u64 arg2) +{ + u32 fid = 0; + + /* Only the six bits allowed should be used. */ + KBASE_DEBUG_ASSERT((oen & ~SMC_OEN_MASK) == 0); + + fid |= SMC_FAST_CALL; /* Bit 31: Fast call */ + if (smc64) + fid |= SMC_64; /* Bit 30: 1=SMC64, 0=SMC32 */ + fid |= oen; /* Bit 29:24: OEN */ + /* Bit 23:16: Must be zero for fast calls */ + fid |= (function_number); /* Bit 15:0: function number */ + + return kbase_invoke_smc_fid(fid, arg0, arg1, arg2); +} + +#endif /* CONFIG_ARM64 */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_smc.h b/drivers/gpu/arm/bifrost/mali_kbase_smc.h new file mode 100644 index 000000000000..9bff3d2e8b4d --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_smc.h @@ -0,0 +1,67 @@ +/* + * + * (C) COPYRIGHT 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_SMC_H_ +#define _KBASE_SMC_H_ + +#ifdef CONFIG_ARM64 + +#include + +#define SMC_FAST_CALL (1 << 31) +#define SMC_64 (1 << 30) + +#define SMC_OEN_OFFSET 24 +#define SMC_OEN_MASK (0x3F << SMC_OEN_OFFSET) /* 6 bits */ +#define SMC_OEN_SIP (2 << SMC_OEN_OFFSET) +#define SMC_OEN_STD (4 << SMC_OEN_OFFSET) + + +/** + * kbase_invoke_smc_fid - Perform a secure monitor call + * @fid: The SMC function to call, see SMC Calling convention. + * @arg0: First argument to the SMC. + * @arg1: Second argument to the SMC. + * @arg2: Third argument to the SMC. + * + * See SMC Calling Convention for details. + * + * Return: the return value from the SMC. + */ +u64 kbase_invoke_smc_fid(u32 fid, u64 arg0, u64 arg1, u64 arg2); + +/** + * kbase_invoke_smc_fid - Perform a secure monitor call + * @oen: Owning Entity number (SIP, STD etc). + * @function_number: The function number within the OEN. + * @smc64: use SMC64 calling convention instead of SMC32. + * @arg0: First argument to the SMC. + * @arg1: Second argument to the SMC. + * @arg2: Third argument to the SMC. + * + * See SMC Calling Convention for details. + * + * Return: the return value from the SMC call. + */ +u64 kbase_invoke_smc(u32 oen, u16 function_number, bool smc64, + u64 arg0, u64 arg1, u64 arg2); + +#endif /* CONFIG_ARM64 */ + +#endif /* _KBASE_SMC_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c new file mode 100644 index 000000000000..cd86b983028b --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c @@ -0,0 +1,1513 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @file mali_kbase_softjobs.c + * + * This file implements the logic behind software only jobs that are + * executed within the driver rather than being handed over to the GPU. + */ + +static void kbasep_add_waiting_soft_job(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + unsigned long lflags; + + spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); + list_add_tail(&katom->queue, &kctx->waiting_soft_jobs); + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); +} + +void kbasep_remove_waiting_soft_job(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + unsigned long lflags; + + spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); + list_del(&katom->queue); + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); +} + +static void kbasep_add_waiting_with_timeout(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + /* Record the start time of this atom so we could cancel it at + * the right time. + */ + katom->start_timestamp = ktime_get(); + + /* Add the atom to the waiting list before the timer is + * (re)started to make sure that it gets processed. + */ + kbasep_add_waiting_soft_job(katom); + + /* Schedule timeout of this atom after a period if it is not active */ + if (!timer_pending(&kctx->soft_job_timeout)) { + int timeout_ms = atomic_read( + &kctx->kbdev->js_data.soft_job_timeout_ms); + mod_timer(&kctx->soft_job_timeout, + jiffies + msecs_to_jiffies(timeout_ms)); + } +} + +static int kbasep_read_soft_event_status( + struct kbase_context *kctx, u64 evt, unsigned char *status) +{ + unsigned char *mapped_evt; + struct kbase_vmap_struct map; + + mapped_evt = kbase_vmap(kctx, evt, sizeof(*mapped_evt), &map); + if (!mapped_evt) + return -EFAULT; + + *status = *mapped_evt; + + kbase_vunmap(kctx, &map); + + return 0; +} + +static int kbasep_write_soft_event_status( + struct kbase_context *kctx, u64 evt, unsigned char new_status) +{ + unsigned char *mapped_evt; + struct kbase_vmap_struct map; + + if ((new_status != BASE_JD_SOFT_EVENT_SET) && + (new_status != BASE_JD_SOFT_EVENT_RESET)) + return -EINVAL; + + mapped_evt = kbase_vmap(kctx, evt, sizeof(*mapped_evt), &map); + if (!mapped_evt) + return -EFAULT; + + *mapped_evt = new_status; + + kbase_vunmap(kctx, &map); + + return 0; +} + +static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) +{ + struct kbase_vmap_struct map; + void *user_result; + struct timespec ts; + struct base_dump_cpu_gpu_counters data; + u64 system_time; + u64 cycle_counter; + u64 jc = katom->jc; + struct kbase_context *kctx = katom->kctx; + int pm_active_err; + + memset(&data, 0, sizeof(data)); + + /* Take the PM active reference as late as possible - otherwise, it could + * delay suspend until we process the atom (which may be at the end of a + * long chain of dependencies */ + pm_active_err = kbase_pm_context_active_handle_suspend(kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); + if (pm_active_err) { + struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data; + + /* We're suspended - queue this on the list of suspended jobs + * Use dep_item[1], because dep_item[0] was previously in use + * for 'waiting_soft_jobs'. + */ + mutex_lock(&js_devdata->runpool_mutex); + list_add_tail(&katom->dep_item[1], &js_devdata->suspended_soft_jobs_list); + mutex_unlock(&js_devdata->runpool_mutex); + + /* Also adding this to the list of waiting soft job */ + kbasep_add_waiting_soft_job(katom); + + return pm_active_err; + } + + kbase_backend_get_gpu_time(kctx->kbdev, &cycle_counter, &system_time, + &ts); + + kbase_pm_context_idle(kctx->kbdev); + + data.sec = ts.tv_sec; + data.usec = ts.tv_nsec / 1000; + data.system_time = system_time; + data.cycle_counter = cycle_counter; + + /* Assume this atom will be cancelled until we know otherwise */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* GPU_WR access is checked on the range for returning the result to + * userspace for the following reasons: + * - security, this is currently how imported user bufs are checked. + * - userspace ddk guaranteed to assume region was mapped as GPU_WR */ + user_result = kbase_vmap_prot(kctx, jc, sizeof(data), KBASE_REG_GPU_WR, &map); + if (!user_result) + return 0; + + memcpy(user_result, &data, sizeof(data)); + + kbase_vunmap(kctx, &map); + + /* Atom was fine - mark it as done */ + katom->event_code = BASE_JD_EVENT_DONE; + + return 0; +} + +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +/* Called by the explicit fence mechanism when a fence wait has completed */ +void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + mutex_lock(&kctx->jctx.lock); + kbasep_remove_waiting_soft_job(katom); + kbase_finish_soft_job(katom); + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(kctx->kbdev); + mutex_unlock(&kctx->jctx.lock); +} +#endif + +static void kbasep_soft_event_complete_job(struct work_struct *work) +{ + struct kbase_jd_atom *katom = container_of(work, struct kbase_jd_atom, + work); + struct kbase_context *kctx = katom->kctx; + int resched; + + mutex_lock(&kctx->jctx.lock); + resched = jd_done_nolock(katom, NULL); + mutex_unlock(&kctx->jctx.lock); + + if (resched) + kbase_js_sched_all(kctx->kbdev); +} + +void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt) +{ + int cancel_timer = 1; + struct list_head *entry, *tmp; + unsigned long lflags; + + spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); + list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { + struct kbase_jd_atom *katom = list_entry( + entry, struct kbase_jd_atom, queue); + + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_EVENT_WAIT: + if (katom->jc == evt) { + list_del(&katom->queue); + + katom->event_code = BASE_JD_EVENT_DONE; + INIT_WORK(&katom->work, + kbasep_soft_event_complete_job); + queue_work(kctx->jctx.job_done_wq, + &katom->work); + } else { + /* There are still other waiting jobs, we cannot + * cancel the timer yet. + */ + cancel_timer = 0; + } + break; +#ifdef CONFIG_MALI_FENCE_DEBUG + case BASE_JD_REQ_SOFT_FENCE_WAIT: + /* Keep the timer running if fence debug is enabled and + * there are waiting fence jobs. + */ + cancel_timer = 0; + break; +#endif + } + } + + if (cancel_timer) + del_timer(&kctx->soft_job_timeout); + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); +} + +#ifdef CONFIG_MALI_FENCE_DEBUG +static void kbase_fence_debug_check_atom(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct device *dev = kctx->kbdev->dev; + int i; + + for (i = 0; i < 2; i++) { + struct kbase_jd_atom *dep; + + list_for_each_entry(dep, &katom->dep_head[i], dep_item[i]) { + if (dep->status == KBASE_JD_ATOM_STATE_UNUSED || + dep->status == KBASE_JD_ATOM_STATE_COMPLETED) + continue; + + if ((dep->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) + == BASE_JD_REQ_SOFT_FENCE_TRIGGER) { + /* Found blocked trigger fence. */ + struct kbase_sync_fence_info info; + + if (!kbase_sync_fence_in_info_get(dep, &info)) { + dev_warn(dev, + "\tVictim trigger atom %d fence [%p] %s: %s\n", + kbase_jd_atom_id(kctx, dep), + info.fence, + info.name, + kbase_sync_status_string(info.status)); + } + } + + kbase_fence_debug_check_atom(dep); + } + } +} + +static void kbase_fence_debug_wait_timeout(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct device *dev = katom->kctx->kbdev->dev; + int timeout_ms = atomic_read(&kctx->kbdev->js_data.soft_job_timeout_ms); + unsigned long lflags; + struct kbase_sync_fence_info info; + + spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); + + if (kbase_sync_fence_in_info_get(katom, &info)) { + /* Fence must have signaled just after timeout. */ + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); + return; + } + + dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%p] after %dms\n", + kctx->tgid, kctx->id, + kbase_jd_atom_id(kctx, katom), + info.fence, timeout_ms); + dev_warn(dev, "\tGuilty fence [%p] %s: %s\n", + info.fence, info.name, + kbase_sync_status_string(info.status)); + + /* Search for blocked trigger atoms */ + kbase_fence_debug_check_atom(katom); + + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); + + kbase_sync_fence_in_dump(katom); +} + +struct kbase_fence_debug_work { + struct kbase_jd_atom *katom; + struct work_struct work; +}; + +static void kbase_fence_debug_wait_timeout_worker(struct work_struct *work) +{ + struct kbase_fence_debug_work *w = container_of(work, + struct kbase_fence_debug_work, work); + struct kbase_jd_atom *katom = w->katom; + struct kbase_context *kctx = katom->kctx; + + mutex_lock(&kctx->jctx.lock); + kbase_fence_debug_wait_timeout(katom); + mutex_unlock(&kctx->jctx.lock); + + kfree(w); +} + +static void kbase_fence_debug_timeout(struct kbase_jd_atom *katom) +{ + struct kbase_fence_debug_work *work; + struct kbase_context *kctx = katom->kctx; + + /* Enqueue fence debug worker. Use job_done_wq to get + * debug print ordered with job completion. + */ + work = kzalloc(sizeof(struct kbase_fence_debug_work), GFP_ATOMIC); + /* Ignore allocation failure. */ + if (work) { + work->katom = katom; + INIT_WORK(&work->work, kbase_fence_debug_wait_timeout_worker); + queue_work(kctx->jctx.job_done_wq, &work->work); + } +} +#endif /* CONFIG_MALI_FENCE_DEBUG */ + +void kbasep_soft_job_timeout_worker(unsigned long data) +{ + struct kbase_context *kctx = (struct kbase_context *)data; + u32 timeout_ms = (u32)atomic_read( + &kctx->kbdev->js_data.soft_job_timeout_ms); + struct timer_list *timer = &kctx->soft_job_timeout; + ktime_t cur_time = ktime_get(); + bool restarting = false; + unsigned long lflags; + struct list_head *entry, *tmp; + + spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); + list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { + struct kbase_jd_atom *katom = list_entry(entry, + struct kbase_jd_atom, queue); + s64 elapsed_time = ktime_to_ms(ktime_sub(cur_time, + katom->start_timestamp)); + + if (elapsed_time < (s64)timeout_ms) { + restarting = true; + continue; + } + + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_EVENT_WAIT: + /* Take it out of the list to ensure that it + * will be cancelled in all cases + */ + list_del(&katom->queue); + + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + INIT_WORK(&katom->work, kbasep_soft_event_complete_job); + queue_work(kctx->jctx.job_done_wq, &katom->work); + break; +#ifdef CONFIG_MALI_FENCE_DEBUG + case BASE_JD_REQ_SOFT_FENCE_WAIT: + kbase_fence_debug_timeout(katom); + break; +#endif + } + } + + if (restarting) + mod_timer(timer, jiffies + msecs_to_jiffies(timeout_ms)); + spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); +} + +static int kbasep_soft_event_wait(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + unsigned char status; + + /* The status of this soft-job is stored in jc */ + if (kbasep_read_soft_event_status(kctx, katom->jc, &status)) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + return 0; + } + + if (status == BASE_JD_SOFT_EVENT_SET) + return 0; /* Event already set, nothing to do */ + + kbasep_add_waiting_with_timeout(katom); + + return 1; +} + +static void kbasep_soft_event_update_locked(struct kbase_jd_atom *katom, + unsigned char new_status) +{ + /* Complete jobs waiting on the same event */ + struct kbase_context *kctx = katom->kctx; + + if (kbasep_write_soft_event_status(kctx, katom->jc, new_status) != 0) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + return; + } + + if (new_status == BASE_JD_SOFT_EVENT_SET) + kbasep_complete_triggered_soft_events(kctx, katom->jc); +} + +/** + * kbase_soft_event_update() - Update soft event state + * @kctx: Pointer to context + * @event: Event to update + * @new_status: New status value of event + * + * Update the event, and wake up any atoms waiting for the event. + * + * Return: 0 on success, a negative error code on failure. + */ +int kbase_soft_event_update(struct kbase_context *kctx, + u64 event, + unsigned char new_status) +{ + int err = 0; + + mutex_lock(&kctx->jctx.lock); + + if (kbasep_write_soft_event_status(kctx, event, new_status)) { + err = -ENOENT; + goto out; + } + + if (new_status == BASE_JD_SOFT_EVENT_SET) + kbasep_complete_triggered_soft_events(kctx, event); + +out: + mutex_unlock(&kctx->jctx.lock); + + return err; +} + +static void kbasep_soft_event_cancel_job(struct kbase_jd_atom *katom) +{ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(katom->kctx->kbdev); +} + +struct kbase_debug_copy_buffer { + size_t size; + struct page **pages; + int nr_pages; + size_t offset; + struct kbase_mem_phy_alloc *gpu_alloc; + + struct page **extres_pages; + int nr_extres_pages; +}; + +static inline void free_user_buffer(struct kbase_debug_copy_buffer *buffer) +{ + struct page **pages = buffer->extres_pages; + int nr_pages = buffer->nr_extres_pages; + + if (pages) { + int i; + + for (i = 0; i < nr_pages; i++) { + struct page *pg = pages[i]; + + if (pg) + put_page(pg); + } + kfree(pages); + } +} + +static void kbase_debug_copy_finish(struct kbase_jd_atom *katom) +{ + struct kbase_debug_copy_buffer *buffers = + (struct kbase_debug_copy_buffer *)(uintptr_t)katom->jc; + unsigned int i; + unsigned int nr = katom->nr_extres; + + if (!buffers) + return; + + kbase_gpu_vm_lock(katom->kctx); + for (i = 0; i < nr; i++) { + int p; + struct kbase_mem_phy_alloc *gpu_alloc = buffers[i].gpu_alloc; + + if (!buffers[i].pages) + break; + for (p = 0; p < buffers[i].nr_pages; p++) { + struct page *pg = buffers[i].pages[p]; + + if (pg) + put_page(pg); + } + kfree(buffers[i].pages); + if (gpu_alloc) { + switch (gpu_alloc->type) { + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: + { + free_user_buffer(&buffers[i]); + break; + } + default: + /* Nothing to be done. */ + break; + } + kbase_mem_phy_alloc_put(gpu_alloc); + } + } + kbase_gpu_vm_unlock(katom->kctx); + kfree(buffers); + + katom->jc = 0; +} + +static int kbase_debug_copy_prepare(struct kbase_jd_atom *katom) +{ + struct kbase_debug_copy_buffer *buffers; + struct base_jd_debug_copy_buffer *user_buffers = NULL; + unsigned int i; + unsigned int nr = katom->nr_extres; + int ret = 0; + void __user *user_structs = (void __user *)(uintptr_t)katom->jc; + + if (!user_structs) + return -EINVAL; + + buffers = kcalloc(nr, sizeof(*buffers), GFP_KERNEL); + if (!buffers) { + ret = -ENOMEM; + katom->jc = 0; + goto out_cleanup; + } + katom->jc = (u64)(uintptr_t)buffers; + + user_buffers = kmalloc_array(nr, sizeof(*user_buffers), GFP_KERNEL); + + if (!user_buffers) { + ret = -ENOMEM; + goto out_cleanup; + } + + ret = copy_from_user(user_buffers, user_structs, + sizeof(*user_buffers)*nr); + if (ret) { + ret = -EFAULT; + goto out_cleanup; + } + + for (i = 0; i < nr; i++) { + u64 addr = user_buffers[i].address; + u64 page_addr = addr & PAGE_MASK; + u64 end_page_addr = addr + user_buffers[i].size - 1; + u64 last_page_addr = end_page_addr & PAGE_MASK; + int nr_pages = (last_page_addr-page_addr)/PAGE_SIZE+1; + int pinned_pages; + struct kbase_va_region *reg; + struct base_external_resource user_extres; + + if (!addr) + continue; + + buffers[i].nr_pages = nr_pages; + buffers[i].offset = addr & ~PAGE_MASK; + if (buffers[i].offset >= PAGE_SIZE) { + ret = -EINVAL; + goto out_cleanup; + } + buffers[i].size = user_buffers[i].size; + + buffers[i].pages = kcalloc(nr_pages, sizeof(struct page *), + GFP_KERNEL); + if (!buffers[i].pages) { + ret = -ENOMEM; + goto out_cleanup; + } + + pinned_pages = get_user_pages_fast(page_addr, + nr_pages, + 1, /* Write */ + buffers[i].pages); + if (pinned_pages < 0) { + ret = pinned_pages; + goto out_cleanup; + } + if (pinned_pages != nr_pages) { + ret = -EINVAL; + goto out_cleanup; + } + + user_extres = user_buffers[i].extres; + if (user_extres.ext_resource == 0ULL) { + ret = -EINVAL; + goto out_cleanup; + } + + kbase_gpu_vm_lock(katom->kctx); + reg = kbase_region_tracker_find_region_enclosing_address( + katom->kctx, user_extres.ext_resource & + ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + + if (NULL == reg || NULL == reg->gpu_alloc || + (reg->flags & KBASE_REG_FREE)) { + ret = -EINVAL; + goto out_unlock; + } + + buffers[i].gpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + buffers[i].nr_extres_pages = reg->nr_pages; + + if (reg->nr_pages*PAGE_SIZE != buffers[i].size) + dev_warn(katom->kctx->kbdev->dev, "Copy buffer is not of same size as the external resource to copy.\n"); + + switch (reg->gpu_alloc->type) { + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: + { + struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; + unsigned long nr_pages = + alloc->imported.user_buf.nr_pages; + + if (alloc->imported.user_buf.mm != current->mm) { + ret = -EINVAL; + goto out_unlock; + } + buffers[i].extres_pages = kcalloc(nr_pages, + sizeof(struct page *), GFP_KERNEL); + if (!buffers[i].extres_pages) { + ret = -ENOMEM; + goto out_unlock; + } + + ret = get_user_pages_fast( + alloc->imported.user_buf.address, + nr_pages, 0, + buffers[i].extres_pages); + if (ret != nr_pages) + goto out_unlock; + ret = 0; + break; + } + case KBASE_MEM_TYPE_IMPORTED_UMP: + { + dev_warn(katom->kctx->kbdev->dev, + "UMP is not supported for debug_copy jobs\n"); + ret = -EINVAL; + goto out_unlock; + } + default: + /* Nothing to be done. */ + break; + } + kbase_gpu_vm_unlock(katom->kctx); + } + kfree(user_buffers); + + return ret; + +out_unlock: + kbase_gpu_vm_unlock(katom->kctx); + +out_cleanup: + /* Frees allocated memory for kbase_debug_copy_job struct, including + * members, and sets jc to 0 */ + kbase_debug_copy_finish(katom); + kfree(user_buffers); + + return ret; +} + +static void kbase_mem_copy_from_extres_page(struct kbase_context *kctx, + void *extres_page, struct page **pages, unsigned int nr_pages, + unsigned int *target_page_nr, size_t offset, size_t *to_copy) +{ + void *target_page = kmap(pages[*target_page_nr]); + size_t chunk = PAGE_SIZE-offset; + + lockdep_assert_held(&kctx->reg_lock); + + if (!target_page) { + *target_page_nr += 1; + dev_warn(kctx->kbdev->dev, "kmap failed in debug_copy job."); + return; + } + + chunk = min(chunk, *to_copy); + + memcpy(target_page + offset, extres_page, chunk); + *to_copy -= chunk; + + kunmap(pages[*target_page_nr]); + + *target_page_nr += 1; + if (*target_page_nr >= nr_pages) + return; + + target_page = kmap(pages[*target_page_nr]); + if (!target_page) { + *target_page_nr += 1; + dev_warn(kctx->kbdev->dev, "kmap failed in debug_copy job."); + return; + } + + KBASE_DEBUG_ASSERT(target_page); + + chunk = min(offset, *to_copy); + memcpy(target_page, extres_page + PAGE_SIZE-offset, chunk); + *to_copy -= chunk; + + kunmap(pages[*target_page_nr]); +} + +static int kbase_mem_copy_from_extres(struct kbase_context *kctx, + struct kbase_debug_copy_buffer *buf_data) +{ + unsigned int i; + unsigned int target_page_nr = 0; + struct page **pages = buf_data->pages; + u64 offset = buf_data->offset; + size_t extres_size = buf_data->nr_extres_pages*PAGE_SIZE; + size_t to_copy = min(extres_size, buf_data->size); + size_t dma_to_copy; + struct kbase_mem_phy_alloc *gpu_alloc = buf_data->gpu_alloc; + int ret = 0; + + KBASE_DEBUG_ASSERT(pages != NULL); + + kbase_gpu_vm_lock(kctx); + if (!gpu_alloc) { + ret = -EINVAL; + goto out_unlock; + } + + switch (gpu_alloc->type) { + case KBASE_MEM_TYPE_IMPORTED_USER_BUF: + { + for (i = 0; i < buf_data->nr_extres_pages; i++) { + struct page *pg = buf_data->extres_pages[i]; + void *extres_page = kmap(pg); + + if (extres_page) + kbase_mem_copy_from_extres_page(kctx, + extres_page, pages, + buf_data->nr_pages, + &target_page_nr, + offset, &to_copy); + + kunmap(pg); + if (target_page_nr >= buf_data->nr_pages) + break; + } + break; + } + break; +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: { + struct dma_buf *dma_buf = gpu_alloc->imported.umm.dma_buf; + + KBASE_DEBUG_ASSERT(dma_buf != NULL); + if (dma_buf->size > buf_data->nr_extres_pages * PAGE_SIZE) + dev_warn(kctx->kbdev->dev, "External resources buffer size mismatch"); + + dma_to_copy = min(dma_buf->size, + (size_t)(buf_data->nr_extres_pages * PAGE_SIZE)); + ret = dma_buf_begin_cpu_access(dma_buf, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS) + 0, dma_to_copy, +#endif + DMA_FROM_DEVICE); + if (ret) + goto out_unlock; + + for (i = 0; i < dma_to_copy/PAGE_SIZE; i++) { + + void *extres_page = dma_buf_kmap(dma_buf, i); + + if (extres_page) + kbase_mem_copy_from_extres_page(kctx, + extres_page, pages, + buf_data->nr_pages, + &target_page_nr, + offset, &to_copy); + + dma_buf_kunmap(dma_buf, i, extres_page); + if (target_page_nr >= buf_data->nr_pages) + break; + } + dma_buf_end_cpu_access(dma_buf, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS) + 0, dma_to_copy, +#endif + DMA_FROM_DEVICE); + break; + } +#endif + default: + ret = -EINVAL; + } +out_unlock: + kbase_gpu_vm_unlock(kctx); + return ret; + +} + +static int kbase_debug_copy(struct kbase_jd_atom *katom) +{ + struct kbase_debug_copy_buffer *buffers = + (struct kbase_debug_copy_buffer *)(uintptr_t)katom->jc; + unsigned int i; + + for (i = 0; i < katom->nr_extres; i++) { + int res = kbase_mem_copy_from_extres(katom->kctx, &buffers[i]); + + if (res) + return res; + } + + return 0; +} + +static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) +{ + __user void *data = (__user void *)(uintptr_t) katom->jc; + struct base_jit_alloc_info *info; + struct kbase_context *kctx = katom->kctx; + int ret; + + /* Fail the job if there is no info structure */ + if (!data) { + ret = -EINVAL; + goto fail; + } + + /* Copy the information for safe access and future storage */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto fail; + } + + if (copy_from_user(info, data, sizeof(*info)) != 0) { + ret = -EINVAL; + goto free_info; + } + + /* If the ID is zero then fail the job */ + if (info->id == 0) { + ret = -EINVAL; + goto free_info; + } + + /* Sanity check that the PA fits within the VA */ + if (info->va_pages < info->commit_pages) { + ret = -EINVAL; + goto free_info; + } + + /* Ensure the GPU address is correctly aligned */ + if ((info->gpu_alloc_addr & 0x7) != 0) { + ret = -EINVAL; + goto free_info; + } + + /* Replace the user pointer with our kernel allocated info structure */ + katom->jc = (u64)(uintptr_t) info; + katom->jit_blocked = false; + + lockdep_assert_held(&kctx->jctx.lock); + list_add_tail(&katom->jit_node, &kctx->jit_atoms_head); + + /* + * Note: + * The provided info->gpu_alloc_addr isn't validated here as + * userland can cache allocations which means that even + * though the region is valid it doesn't represent the + * same thing it used to. + * + * Complete validation of va_pages, commit_pages and extent + * isn't done here as it will be done during the call to + * kbase_mem_alloc. + */ + return 0; + +free_info: + kfree(info); +fail: + katom->jc = 0; + return ret; +} + +static u8 kbase_jit_free_get_id(struct kbase_jd_atom *katom) +{ + if (WARN_ON(katom->core_req != BASE_JD_REQ_SOFT_JIT_FREE)) + return 0; + + return (u8) katom->jc; +} + +static int kbase_jit_allocate_process(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct base_jit_alloc_info *info; + struct kbase_va_region *reg; + struct kbase_vmap_struct mapping; + u64 *ptr, new_addr; + + if (katom->jit_blocked) { + list_del(&katom->queue); + katom->jit_blocked = false; + } + + info = (struct base_jit_alloc_info *) (uintptr_t) katom->jc; + + /* The JIT ID is still in use so fail the allocation */ + if (kctx->jit_alloc[info->id]) { + katom->event_code = BASE_JD_EVENT_MEM_GROWTH_FAILED; + return 0; + } + + /* Create a JIT allocation */ + reg = kbase_jit_allocate(kctx, info); + if (!reg) { + struct kbase_jd_atom *jit_atom; + bool can_block = false; + + lockdep_assert_held(&kctx->jctx.lock); + + jit_atom = list_first_entry(&kctx->jit_atoms_head, + struct kbase_jd_atom, jit_node); + + list_for_each_entry(jit_atom, &kctx->jit_atoms_head, jit_node) { + if (jit_atom == katom) + break; + if (jit_atom->core_req == BASE_JD_REQ_SOFT_JIT_FREE) { + u8 free_id = kbase_jit_free_get_id(jit_atom); + + if (free_id && kctx->jit_alloc[free_id]) { + /* A JIT free which is active and + * submitted before this atom + */ + can_block = true; + break; + } + } + } + + if (!can_block) { + /* Mark the allocation so we know it's in use even if + * the allocation itself fails. + */ + kctx->jit_alloc[info->id] = + (struct kbase_va_region *) -1; + + katom->event_code = BASE_JD_EVENT_MEM_GROWTH_FAILED; + return 0; + } + + /* There are pending frees for an active allocation + * so we should wait to see whether they free the memory. + * Add to the beginning of the list to ensure that the atom is + * processed only once in kbase_jit_free_finish + */ + list_add(&katom->queue, &kctx->jit_pending_alloc); + katom->jit_blocked = true; + + return 1; + } + + /* + * Write the address of the JIT allocation to the user provided + * GPU allocation. + */ + ptr = kbase_vmap(kctx, info->gpu_alloc_addr, sizeof(*ptr), + &mapping); + if (!ptr) { + /* + * Leave the allocation "live" as the JIT free jit will be + * submitted anyway. + */ + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + return 0; + } + + new_addr = reg->start_pfn << PAGE_SHIFT; + *ptr = new_addr; + KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT( + katom, info->gpu_alloc_addr, new_addr); + kbase_vunmap(kctx, &mapping); + + katom->event_code = BASE_JD_EVENT_DONE; + + /* + * Bind it to the user provided ID. Do this last so we can check for + * the JIT free racing this JIT alloc job. + */ + kctx->jit_alloc[info->id] = reg; + + return 0; +} + +static void kbase_jit_allocate_finish(struct kbase_jd_atom *katom) +{ + struct base_jit_alloc_info *info; + + lockdep_assert_held(&katom->kctx->jctx.lock); + + /* Remove atom from jit_atoms_head list */ + list_del(&katom->jit_node); + + if (katom->jit_blocked) { + list_del(&katom->queue); + katom->jit_blocked = false; + } + + info = (struct base_jit_alloc_info *) (uintptr_t) katom->jc; + /* Free the info structure */ + kfree(info); +} + +static int kbase_jit_free_prepare(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + lockdep_assert_held(&kctx->jctx.lock); + list_add_tail(&katom->jit_node, &kctx->jit_atoms_head); + + return 0; +} + +static void kbase_jit_free_process(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + u8 id = kbase_jit_free_get_id(katom); + + /* + * If the ID is zero or it is not in use yet then fail the job. + */ + if ((id == 0) || (kctx->jit_alloc[id] == NULL)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + return; + } + + /* + * If the ID is valid but the allocation request failed still succeed + * this soft job but don't try and free the allocation. + */ + if (kctx->jit_alloc[id] != (struct kbase_va_region *) -1) + kbase_jit_free(kctx, kctx->jit_alloc[id]); + + kctx->jit_alloc[id] = NULL; +} + +static void kbasep_jit_free_finish_worker(struct work_struct *work) +{ + struct kbase_jd_atom *katom = container_of(work, struct kbase_jd_atom, + work); + struct kbase_context *kctx = katom->kctx; + int resched; + + mutex_lock(&kctx->jctx.lock); + kbase_finish_soft_job(katom); + resched = jd_done_nolock(katom, NULL); + mutex_unlock(&kctx->jctx.lock); + + if (resched) + kbase_js_sched_all(kctx->kbdev); +} + +static void kbase_jit_free_finish(struct kbase_jd_atom *katom) +{ + struct list_head *i, *tmp; + struct kbase_context *kctx = katom->kctx; + + lockdep_assert_held(&kctx->jctx.lock); + /* Remove this atom from the kctx->jit_atoms_head list */ + list_del(&katom->jit_node); + + list_for_each_safe(i, tmp, &kctx->jit_pending_alloc) { + struct kbase_jd_atom *pending_atom = list_entry(i, + struct kbase_jd_atom, queue); + if (kbase_jit_allocate_process(pending_atom) == 0) { + /* Atom has completed */ + INIT_WORK(&pending_atom->work, + kbasep_jit_free_finish_worker); + queue_work(kctx->jctx.job_done_wq, &pending_atom->work); + } + } +} + +static int kbase_ext_res_prepare(struct kbase_jd_atom *katom) +{ + __user struct base_external_resource_list *user_ext_res; + struct base_external_resource_list *ext_res; + u64 count = 0; + size_t copy_size; + int ret; + + user_ext_res = (__user struct base_external_resource_list *) + (uintptr_t) katom->jc; + + /* Fail the job if there is no info structure */ + if (!user_ext_res) { + ret = -EINVAL; + goto fail; + } + + if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0) { + ret = -EINVAL; + goto fail; + } + + /* Is the number of external resources in range? */ + if (!count || count > BASE_EXT_RES_COUNT_MAX) { + ret = -EINVAL; + goto fail; + } + + /* Copy the information for safe access and future storage */ + copy_size = sizeof(*ext_res); + copy_size += sizeof(struct base_external_resource) * (count - 1); + ext_res = kzalloc(copy_size, GFP_KERNEL); + if (!ext_res) { + ret = -ENOMEM; + goto fail; + } + + if (copy_from_user(ext_res, user_ext_res, copy_size) != 0) { + ret = -EINVAL; + goto free_info; + } + + /* + * Overwrite the count with the first value incase it was changed + * after the fact. + */ + ext_res->count = count; + + /* + * Replace the user pointer with our kernel allocated + * ext_res structure. + */ + katom->jc = (u64)(uintptr_t) ext_res; + + return 0; + +free_info: + kfree(ext_res); +fail: + return ret; +} + +static void kbase_ext_res_process(struct kbase_jd_atom *katom, bool map) +{ + struct base_external_resource_list *ext_res; + int i; + bool failed = false; + + ext_res = (struct base_external_resource_list *) (uintptr_t) katom->jc; + if (!ext_res) + goto failed_jc; + + kbase_gpu_vm_lock(katom->kctx); + + for (i = 0; i < ext_res->count; i++) { + u64 gpu_addr; + + gpu_addr = ext_res->ext_res[i].ext_resource & + ~BASE_EXT_RES_ACCESS_EXCLUSIVE; + if (map) { + if (!kbase_sticky_resource_acquire(katom->kctx, + gpu_addr)) + goto failed_loop; + } else + if (!kbase_sticky_resource_release(katom->kctx, NULL, + gpu_addr)) + failed = true; + } + + /* + * In the case of unmap we continue unmapping other resources in the + * case of failure but will always report failure if _any_ unmap + * request fails. + */ + if (failed) + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + else + katom->event_code = BASE_JD_EVENT_DONE; + + kbase_gpu_vm_unlock(katom->kctx); + + return; + +failed_loop: + while (--i > 0) { + u64 gpu_addr; + + gpu_addr = ext_res->ext_res[i].ext_resource & + ~BASE_EXT_RES_ACCESS_EXCLUSIVE; + + kbase_sticky_resource_release(katom->kctx, NULL, gpu_addr); + } + + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + kbase_gpu_vm_unlock(katom->kctx); + +failed_jc: + return; +} + +static void kbase_ext_res_finish(struct kbase_jd_atom *katom) +{ + struct base_external_resource_list *ext_res; + + ext_res = (struct base_external_resource_list *) (uintptr_t) katom->jc; + /* Free the info structure */ + kfree(ext_res); +} + +int kbase_process_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + return kbase_dump_cpu_gpu_time(katom); + +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + katom->event_code = kbase_sync_fence_out_trigger(katom, + katom->event_code == BASE_JD_EVENT_DONE ? + 0 : -EFAULT); + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + { + int ret = kbase_sync_fence_in_wait(katom); + + if (ret == 1) { +#ifdef CONFIG_MALI_FENCE_DEBUG + kbasep_add_waiting_with_timeout(katom); +#else + kbasep_add_waiting_soft_job(katom); +#endif + } + return ret; + } +#endif + + case BASE_JD_REQ_SOFT_REPLAY: + return kbase_replay_process(katom); + case BASE_JD_REQ_SOFT_EVENT_WAIT: + return kbasep_soft_event_wait(katom); + case BASE_JD_REQ_SOFT_EVENT_SET: + kbasep_soft_event_update_locked(katom, BASE_JD_SOFT_EVENT_SET); + break; + case BASE_JD_REQ_SOFT_EVENT_RESET: + kbasep_soft_event_update_locked(katom, BASE_JD_SOFT_EVENT_RESET); + break; + case BASE_JD_REQ_SOFT_DEBUG_COPY: + { + int res = kbase_debug_copy(katom); + + if (res) + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + break; + } + case BASE_JD_REQ_SOFT_JIT_ALLOC: + return kbase_jit_allocate_process(katom); + case BASE_JD_REQ_SOFT_JIT_FREE: + kbase_jit_free_process(katom); + break; + case BASE_JD_REQ_SOFT_EXT_RES_MAP: + kbase_ext_res_process(katom, true); + break; + case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: + kbase_ext_res_process(katom, false); + break; + } + + /* Atom is complete */ + return 0; +} + +void kbase_cancel_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + case BASE_JD_REQ_SOFT_FENCE_WAIT: + kbase_sync_fence_in_cancel_wait(katom); + break; +#endif + case BASE_JD_REQ_SOFT_EVENT_WAIT: + kbasep_soft_event_cancel_job(katom); + break; + default: + /* This soft-job doesn't support cancellation! */ + KBASE_DEBUG_ASSERT(0); + } +} + +int kbase_prepare_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + { + if (!IS_ALIGNED(katom->jc, cache_line_size())) + return -EINVAL; + } + break; +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + { + struct base_fence fence; + int fd; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return -EINVAL; + + fd = kbase_sync_fence_out_create(katom, + fence.basep.stream_fd); + if (fd < 0) + return -EINVAL; + + fence.basep.fd = fd; + if (0 != copy_to_user((__user void *)(uintptr_t) katom->jc, &fence, sizeof(fence))) { + kbase_sync_fence_out_remove(katom); + kbase_sync_fence_close_fd(fd); + fence.basep.fd = -EINVAL; + return -EINVAL; + } + } + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + { + struct base_fence fence; + int ret; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return -EINVAL; + + /* Get a reference to the fence object */ + ret = kbase_sync_fence_in_from_fd(katom, + fence.basep.fd); + if (ret < 0) + return ret; + +#ifdef CONFIG_MALI_DMA_FENCE + /* + * Set KCTX_NO_IMPLICIT_FENCE in the context the first + * time a soft fence wait job is observed. This will + * prevent the implicit dma-buf fence to conflict with + * the Android native sync fences. + */ + if (!kbase_ctx_flag(katom->kctx, KCTX_NO_IMPLICIT_SYNC)) + kbase_ctx_flag_set(katom->kctx, KCTX_NO_IMPLICIT_SYNC); +#endif /* CONFIG_MALI_DMA_FENCE */ + } + break; +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + case BASE_JD_REQ_SOFT_JIT_ALLOC: + return kbase_jit_allocate_prepare(katom); + case BASE_JD_REQ_SOFT_REPLAY: + break; + case BASE_JD_REQ_SOFT_JIT_FREE: + return kbase_jit_free_prepare(katom); + case BASE_JD_REQ_SOFT_EVENT_WAIT: + case BASE_JD_REQ_SOFT_EVENT_SET: + case BASE_JD_REQ_SOFT_EVENT_RESET: + if (katom->jc == 0) + return -EINVAL; + break; + case BASE_JD_REQ_SOFT_DEBUG_COPY: + return kbase_debug_copy_prepare(katom); + case BASE_JD_REQ_SOFT_EXT_RES_MAP: + return kbase_ext_res_prepare(katom); + case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: + return kbase_ext_res_prepare(katom); + default: + /* Unsupported soft-job */ + return -EINVAL; + } + return 0; +} + +void kbase_finish_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + /* Nothing to do */ + break; +#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + /* If fence has not yet been signaled, do it now */ + kbase_sync_fence_out_trigger(katom, katom->event_code == + BASE_JD_EVENT_DONE ? 0 : -EFAULT); + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + /* Release katom's reference to fence object */ + kbase_sync_fence_in_remove(katom); + break; +#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ + case BASE_JD_REQ_SOFT_DEBUG_COPY: + kbase_debug_copy_finish(katom); + break; + case BASE_JD_REQ_SOFT_JIT_ALLOC: + kbase_jit_allocate_finish(katom); + break; + case BASE_JD_REQ_SOFT_EXT_RES_MAP: + kbase_ext_res_finish(katom); + break; + case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: + kbase_ext_res_finish(katom); + break; + case BASE_JD_REQ_SOFT_JIT_FREE: + kbase_jit_free_finish(katom); + break; + } +} + +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) +{ + LIST_HEAD(local_suspended_soft_jobs); + struct kbase_jd_atom *tmp_iter; + struct kbase_jd_atom *katom_iter; + struct kbasep_js_device_data *js_devdata; + bool resched = false; + + KBASE_DEBUG_ASSERT(kbdev); + + js_devdata = &kbdev->js_data; + + /* Move out the entire list */ + mutex_lock(&js_devdata->runpool_mutex); + list_splice_init(&js_devdata->suspended_soft_jobs_list, + &local_suspended_soft_jobs); + mutex_unlock(&js_devdata->runpool_mutex); + + /* + * Each atom must be detached from the list and ran separately - + * it could be re-added to the old list, but this is unlikely + */ + list_for_each_entry_safe(katom_iter, tmp_iter, + &local_suspended_soft_jobs, dep_item[1]) { + struct kbase_context *kctx = katom_iter->kctx; + + mutex_lock(&kctx->jctx.lock); + + /* Remove from the global list */ + list_del(&katom_iter->dep_item[1]); + /* Remove from the context's list of waiting soft jobs */ + kbasep_remove_waiting_soft_job(katom_iter); + + if (kbase_process_soft_job(katom_iter) == 0) { + kbase_finish_soft_job(katom_iter); + resched |= jd_done_nolock(katom_iter, NULL); + } else { + KBASE_DEBUG_ASSERT((katom_iter->core_req & + BASE_JD_REQ_SOFT_JOB_TYPE) + != BASE_JD_REQ_SOFT_REPLAY); + } + + mutex_unlock(&kctx->jctx.lock); + } + + if (resched) + kbase_js_sched_all(kbdev); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_strings.c b/drivers/gpu/arm/bifrost/mali_kbase_strings.c new file mode 100644 index 000000000000..c98762cec244 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_strings.c @@ -0,0 +1,23 @@ + /* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include "mali_kbase_strings.h" + +#define KBASE_DRV_NAME "mali" +#define KBASE_TIMELINE_NAME KBASE_DRV_NAME ".timeline" + +const char kbase_drv_name[] = KBASE_DRV_NAME; +const char kbase_timeline_name[] = KBASE_TIMELINE_NAME; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_strings.h b/drivers/gpu/arm/bifrost/mali_kbase_strings.h new file mode 100644 index 000000000000..41b8fdbec6a4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_strings.h @@ -0,0 +1,19 @@ +/* + * + * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +extern const char kbase_drv_name[]; +extern const char kbase_timeline_name[]; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync.h b/drivers/gpu/arm/bifrost/mali_kbase_sync.h new file mode 100644 index 000000000000..de72147d67ad --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync.h @@ -0,0 +1,203 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_sync.h + * + * This file contains our internal "API" for explicit fences. + * It hides the implementation details of the actual explicit fence mechanism + * used (Android fences or sync file with DMA fences). + */ + +#ifndef MALI_KBASE_SYNC_H +#define MALI_KBASE_SYNC_H + +#include +#ifdef CONFIG_SYNC +#include +#endif +#ifdef CONFIG_SYNC_FILE +#include "mali_kbase_fence_defs.h" +#include +#endif + +#include "mali_kbase.h" + +/** + * struct kbase_sync_fence_info - Information about a fence + * @fence: Pointer to fence (type is void*, as underlaying struct can differ) + * @name: The name given to this fence when it was created + * @status: < 0 means error, 0 means active, 1 means signaled + * + * Use kbase_sync_fence_in_info_get() or kbase_sync_fence_out_info_get() + * to get the information. + */ +struct kbase_sync_fence_info { + void *fence; + char name[32]; + int status; +}; + +/** + * kbase_sync_fence_stream_create() - Create a stream object + * @name: Name of stream (only used to ease debugging/visualization) + * @out_fd: A file descriptor representing the created stream object + * + * Can map down to a timeline implementation in some implementations. + * Exposed as a file descriptor. + * Life-time controlled via the file descriptor: + * - dup to add a ref + * - close to remove a ref + * + * return: 0 on success, < 0 on error + */ +int kbase_sync_fence_stream_create(const char *name, int *const out_fd); + +/** + * kbase_sync_fence_out_create Create an explicit output fence to specified atom + * @katom: Atom to assign the new explicit fence to + * @stream_fd: File descriptor for stream object to create fence on + * + * return: Valid file descriptor to fence or < 0 on error + */ +int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd); + +/** + * kbase_sync_fence_in_from_fd() Assigns an existing fence to specified atom + * @katom: Atom to assign the existing explicit fence to + * @fd: File descriptor to an existing fence + * + * Assigns an explicit input fence to atom. + * This can later be waited for by calling @kbase_sync_fence_in_wait + * + * return: 0 on success, < 0 on error + */ +int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd); + +/** + * kbase_sync_fence_validate() - Validate a fd to be a valid fence + * @fd: File descriptor to check + * + * This function is only usable to catch unintentional user errors early, + * it does not stop malicious code changing the fd after this function returns. + * + * return 0: if fd is for a valid fence, < 0 if invalid + */ +int kbase_sync_fence_validate(int fd); + +/** + * kbase_sync_fence_out_trigger - Signal explicit output fence attached on katom + * @katom: Atom with an explicit fence to signal + * @result: < 0 means signal with error, 0 >= indicates success + * + * Signal output fence attached on katom and remove the fence from the atom. + * + * return: The "next" event code for atom, typically JOB_CANCELLED or EVENT_DONE + */ +enum base_jd_event_code +kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result); + +/** + * kbase_sync_fence_in_wait() - Wait for explicit input fence to be signaled + * @katom: Atom with explicit fence to wait for + * + * If the fence is already signaled, then 0 is returned, and the caller must + * continue processing of the katom. + * + * If the fence isn't already signaled, then this kbase_sync framework will + * take responsibility to continue the processing once the fence is signaled. + * + * return: 0 if already signaled, otherwise 1 + */ +int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom); + +/** + * kbase_sync_fence_in_cancel_wait() - Cancel explicit input fence waits + * @katom: Atom to cancel wait for + * + * This function is fully responsible for continuing processing of this atom + * (remove_waiting_soft_job + finish_soft_job + jd_done + js_sched_all) + */ +void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom); + +/** + * kbase_sync_fence_in_remove() - Remove the input fence from the katom + * @katom: Atom to remove explicit input fence for + * + * This will also release the corresponding reference. + */ +void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom); + +/** + * kbase_sync_fence_out_remove() - Remove the output fence from the katom + * @katom: Atom to remove explicit output fence for + * + * This will also release the corresponding reference. + */ +void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom); + +/** + * kbase_sync_fence_close_fd() - Close a file descriptor representing a fence + * @fd: File descriptor to close + */ +static inline void kbase_sync_fence_close_fd(int fd) +{ + sys_close(fd); +} + +/** + * kbase_sync_fence_in_info_get() - Retrieves information about input fence + * @katom: Atom to get fence information from + * @info: Struct to be filled with fence information + * + * return: 0 on success, < 0 on error + */ +int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info); + +/** + * kbase_sync_fence_out_info_get() - Retrieves information about output fence + * @katom: Atom to get fence information from + * @info: Struct to be filled with fence information + * + * return: 0 on success, < 0 on error + */ +int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info); + +/** + * kbase_sync_status_string() - Get string matching @status + * @status: Value of fence status. + * + * return: Pointer to string describing @status. + */ +const char *kbase_sync_status_string(int status); + +/* + * Internal worker used to continue processing of atom. + */ +void kbase_sync_fence_wait_worker(struct work_struct *data); + +#ifdef CONFIG_MALI_FENCE_DEBUG +/** + * kbase_sync_fence_in_dump() Trigger a debug dump of atoms input fence state + * @katom: Atom to trigger fence debug dump for + */ +void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom); +#endif + +#endif /* MALI_KBASE_SYNC_H */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c new file mode 100644 index 000000000000..d7349dcae69a --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c @@ -0,0 +1,537 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Code for supporting explicit Android fences (CONFIG_SYNC) + * Known to be good for kernels 4.5 and earlier. + * Replaced with CONFIG_SYNC_FILE for 4.9 and later kernels + * (see mali_kbase_sync_file.c) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sync.h" +#include +#include + +struct mali_sync_timeline { + struct sync_timeline timeline; + atomic_t counter; + atomic_t signaled; +}; + +struct mali_sync_pt { + struct sync_pt pt; + int order; + int result; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +/* For backwards compatibility with kernels before 3.17. After 3.17 + * sync_pt_parent is included in the kernel. */ +static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) +{ + return pt->parent; +} +#endif + +static struct mali_sync_timeline *to_mali_sync_timeline( + struct sync_timeline *timeline) +{ + return container_of(timeline, struct mali_sync_timeline, timeline); +} + +static struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) +{ + return container_of(pt, struct mali_sync_pt, pt); +} + +static struct sync_pt *timeline_dup(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_pt *new_mpt; + struct sync_pt *new_pt = sync_pt_create(sync_pt_parent(pt), + sizeof(struct mali_sync_pt)); + + if (!new_pt) + return NULL; + + new_mpt = to_mali_sync_pt(new_pt); + new_mpt->order = mpt->order; + new_mpt->result = mpt->result; + + return new_pt; +} + +static int timeline_has_signaled(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline( + sync_pt_parent(pt)); + int result = mpt->result; + + int diff = atomic_read(&mtl->signaled) - mpt->order; + + if (diff >= 0) + return (result < 0) ? result : 1; + + return 0; +} + +static int timeline_compare(struct sync_pt *a, struct sync_pt *b) +{ + struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); + struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); + + int diff = ma->order - mb->order; + + if (diff == 0) + return 0; + + return (diff < 0) ? -1 : 1; +} + +static void timeline_value_str(struct sync_timeline *timeline, char *str, + int size) +{ + struct mali_sync_timeline *mtl = to_mali_sync_timeline(timeline); + + snprintf(str, size, "%d", atomic_read(&mtl->signaled)); +} + +static void pt_value_str(struct sync_pt *pt, char *str, int size) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + + snprintf(str, size, "%d(%d)", mpt->order, mpt->result); +} + +static struct sync_timeline_ops mali_timeline_ops = { + .driver_name = "Mali", + .dup = timeline_dup, + .has_signaled = timeline_has_signaled, + .compare = timeline_compare, + .timeline_value_str = timeline_value_str, + .pt_value_str = pt_value_str, +}; + +/* Allocates a timeline for Mali + * + * One timeline should be allocated per API context. + */ +static struct sync_timeline *mali_sync_timeline_alloc(const char *name) +{ + struct sync_timeline *tl; + struct mali_sync_timeline *mtl; + + tl = sync_timeline_create(&mali_timeline_ops, + sizeof(struct mali_sync_timeline), name); + if (!tl) + return NULL; + + /* Set the counter in our private struct */ + mtl = to_mali_sync_timeline(tl); + atomic_set(&mtl->counter, 0); + atomic_set(&mtl->signaled, 0); + + return tl; +} + +static int kbase_stream_close(struct inode *inode, struct file *file) +{ + struct sync_timeline *tl; + + tl = (struct sync_timeline *)file->private_data; + sync_timeline_destroy(tl); + return 0; +} + +static const struct file_operations stream_fops = { + .owner = THIS_MODULE, + .release = kbase_stream_close, +}; + +int kbase_sync_fence_stream_create(const char *name, int *const out_fd) +{ + struct sync_timeline *tl; + + if (!out_fd) + return -EINVAL; + + tl = mali_sync_timeline_alloc(name); + if (!tl) + return -EINVAL; + + *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY|O_CLOEXEC); + + if (*out_fd < 0) { + sync_timeline_destroy(tl); + return -EINVAL; + } + + return 0; +} + +/* Allocates a sync point within the timeline. + * + * The timeline must be the one allocated by kbase_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are + * allocated. + */ +static struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt = sync_pt_create(parent, + sizeof(struct mali_sync_pt)); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); + struct mali_sync_pt *mpt; + + if (!pt) + return NULL; + + mpt = to_mali_sync_pt(pt); + mpt->order = atomic_inc_return(&mtl->counter); + mpt->result = 0; + + return pt; +} + +int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd) +{ + struct sync_timeline *tl; + struct sync_pt *pt; + struct sync_fence *fence; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + struct files_struct *files; + struct fdtable *fdt; +#endif + int fd; + struct file *tl_file; + + tl_file = fget(tl_fd); + if (tl_file == NULL) + return -EBADF; + + if (tl_file->f_op != &stream_fops) { + fd = -EBADF; + goto out; + } + + tl = tl_file->private_data; + + pt = kbase_sync_pt_alloc(tl); + if (!pt) { + fd = -EFAULT; + goto out; + } + + fence = sync_fence_create("mali_fence", pt); + if (!fence) { + sync_pt_free(pt); + fd = -EFAULT; + goto out; + } + + /* from here the fence owns the sync_pt */ + + /* create a fd representing the fence */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } +#else + fd = get_unused_fd(); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + __set_close_on_exec(fd, fdt); +#else + FD_SET(fd, fdt->close_on_exec); +#endif + spin_unlock(&files->file_lock); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */ + + /* bind fence to the new fd */ + sync_fence_install(fence, fd); + + katom->fence = sync_fence_fdget(fd); + if (katom->fence == NULL) { + /* The only way the fence can be NULL is if userspace closed it + * for us, so we don't need to clear it up */ + fd = -EINVAL; + goto out; + } + +out: + fput(tl_file); + + return fd; +} + +int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd) +{ + katom->fence = sync_fence_fdget(fd); + return katom->fence ? 0 : -ENOENT; +} + +int kbase_sync_fence_validate(int fd) +{ + struct sync_fence *fence; + + fence = sync_fence_fdget(fd); + if (!fence) + return -EINVAL; + + sync_fence_put(fence); + return 0; +} + +/* Returns true if the specified timeline is allocated by Mali */ +static int kbase_sync_timeline_is_ours(struct sync_timeline *timeline) +{ + return timeline->ops == &mali_timeline_ops; +} + +/* Signals a particular sync point + * + * Sync points must be triggered in *exactly* the same order as they are + * allocated. + * + * If they are signaled in the wrong order then a message will be printed in + * debug builds and otherwise attempts to signal order sync_pts will be ignored. + * + * result can be negative to indicate error, any other value is interpreted as + * success. + */ +static void kbase_sync_signal_pt(struct sync_pt *pt, int result) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline( + sync_pt_parent(pt)); + int signaled; + int diff; + + mpt->result = result; + + do { + signaled = atomic_read(&mtl->signaled); + + diff = signaled - mpt->order; + + if (diff > 0) { + /* The timeline is already at or ahead of this point. + * This should not happen unless userspace has been + * signaling fences out of order, so warn but don't + * violate the sync_pt API. + * The warning is only in debug builds to prevent + * a malicious user being able to spam dmesg. + */ +#ifdef CONFIG_MALI_DEBUG + pr_err("Fences were triggered in a different order to allocation!"); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + } while (atomic_cmpxchg(&mtl->signaled, + signaled, mpt->order) != signaled); +} + +enum base_jd_event_code +kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result) +{ + struct sync_pt *pt; + struct sync_timeline *timeline; + + if (!katom->fence) + return BASE_JD_EVENT_JOB_CANCELLED; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) + if (!list_is_singular(&katom->fence->pt_list_head)) { +#else + if (katom->fence->num_fences != 1) { +#endif + /* Not exactly one item in the list - so it didn't (directly) + * come from us */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) + pt = list_first_entry(&katom->fence->pt_list_head, + struct sync_pt, pt_list); +#else + pt = container_of(katom->fence->cbs[0].sync_pt, struct sync_pt, base); +#endif + timeline = sync_pt_parent(pt); + + if (!kbase_sync_timeline_is_ours(timeline)) { + /* Fence has a sync_pt which isn't ours! */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + kbase_sync_signal_pt(pt, result); + + sync_timeline_signal(timeline); + + kbase_sync_fence_out_remove(katom); + + return (result < 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; +} + +static inline int kbase_fence_get_status(struct sync_fence *fence) +{ + if (!fence) + return -ENOENT; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) + return fence->status; +#else + return atomic_read(&fence->status); +#endif +} + +static void kbase_fence_wait_callback(struct sync_fence *fence, + struct sync_fence_waiter *waiter) +{ + struct kbase_jd_atom *katom = container_of(waiter, + struct kbase_jd_atom, sync_waiter); + struct kbase_context *kctx = katom->kctx; + + /* Propagate the fence status to the atom. + * If negative then cancel this atom and its dependencies. + */ + if (kbase_fence_get_status(fence) < 0) + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* To prevent a potential deadlock we schedule the work onto the + * job_done_wq workqueue + * + * The issue is that we may signal the timeline while holding + * kctx->jctx.lock and the callbacks are run synchronously from + * sync_timeline_signal. So we simply defer the work. + */ + + INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) +{ + int ret; + + sync_fence_waiter_init(&katom->sync_waiter, kbase_fence_wait_callback); + + ret = sync_fence_wait_async(katom->fence, &katom->sync_waiter); + + if (ret == 1) { + /* Already signaled */ + return 0; + } + + if (ret < 0) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + /* We should cause the dependent jobs in the bag to be failed, + * to do this we schedule the work queue to complete this job */ + INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); + queue_work(katom->kctx->jctx.job_done_wq, &katom->work); + } + + return 1; +} + +void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) +{ + if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0) { + /* The wait wasn't cancelled - leave the cleanup for + * kbase_fence_wait_callback */ + return; + } + + /* Wait was cancelled - zap the atoms */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + kbasep_remove_waiting_soft_job(katom); + kbase_finish_soft_job(katom); + + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(katom->kctx->kbdev); +} + +void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom) +{ + if (katom->fence) { + sync_fence_put(katom->fence); + katom->fence = NULL; + } +} + +void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom) +{ + if (katom->fence) { + sync_fence_put(katom->fence); + katom->fence = NULL; + } +} + +int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info) +{ + if (!katom->fence) + return -ENOENT; + + info->fence = katom->fence; + info->status = kbase_fence_get_status(katom->fence); + strlcpy(info->name, katom->fence->name, sizeof(info->name)); + + return 0; +} + +int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info) +{ + if (!katom->fence) + return -ENOENT; + + info->fence = katom->fence; + info->status = kbase_fence_get_status(katom->fence); + strlcpy(info->name, katom->fence->name, sizeof(info->name)); + + return 0; +} + +#ifdef CONFIG_MALI_FENCE_DEBUG +void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) +{ + /* Dump out the full state of all the Android sync fences. + * The function sync_dump() isn't exported to modules, so force + * sync_fence_wait() to time out to trigger sync_dump(). + */ + if (katom->fence) + sync_fence_wait(katom->fence, 1); +} +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_common.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_common.c new file mode 100644 index 000000000000..457def296684 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_common.c @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * @file mali_kbase_sync_common.c + * + * Common code for our explicit fence functionality + */ + +#include +#include "mali_kbase.h" + +void kbase_sync_fence_wait_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + + katom = container_of(data, struct kbase_jd_atom, work); + kbase_soft_event_wait_callback(katom); +} + +const char *kbase_sync_status_string(int status) +{ + if (status == 0) + return "signaled"; + else if (status > 0) + return "active"; + else + return "error"; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c new file mode 100644 index 000000000000..ef5b7ce478b4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c @@ -0,0 +1,348 @@ +/* + * + * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* + * Code for supporting explicit Linux fences (CONFIG_SYNC_FILE) + * Introduced in kernel 4.9. + * Android explicit fences (CONFIG_SYNC) can be used for older kernels + * (see mali_kbase_sync_android.c) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mali_kbase_fence_defs.h" +#include "mali_kbase_sync.h" +#include "mali_kbase_fence.h" +#include "mali_kbase.h" + +static const struct file_operations stream_fops = { + .owner = THIS_MODULE +}; + +int kbase_sync_fence_stream_create(const char *name, int *const out_fd) +{ + if (!out_fd) + return -EINVAL; + + *out_fd = anon_inode_getfd(name, &stream_fops, NULL, + O_RDONLY | O_CLOEXEC); + if (*out_fd < 0) + return -EINVAL; + + return 0; +} + +int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + struct sync_file *sync_file; + int fd; + + fence = kbase_fence_out_new(katom); + if (!fence) + return -ENOMEM; + + /* Take an extra reference to the fence on behalf of the katom. + * This is needed because sync_file_create() will take ownership of + * one of these refs */ + dma_fence_get(fence); + + /* create a sync_file fd representing the fence */ + sync_file = sync_file_create(fence); + if (!sync_file) { + dma_fence_put(fence); + kbase_fence_out_remove(katom); + return -ENOMEM; + } + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) { + fput(sync_file->file); + kbase_fence_out_remove(katom); + return fd; + } + + fd_install(fd, sync_file->file); + + return fd; +} + +int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence = sync_file_get_fence(fd); +#else + struct dma_fence *fence = sync_file_get_fence(fd); +#endif + + if (!fence) + return -ENOENT; + + kbase_fence_fence_in_set(katom, fence); + + return 0; +} + +int kbase_sync_fence_validate(int fd) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence = sync_file_get_fence(fd); +#else + struct dma_fence *fence = sync_file_get_fence(fd); +#endif + + if (!fence) + return -EINVAL; + + dma_fence_put(fence); + + return 0; /* valid */ +} + +enum base_jd_event_code +kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result) +{ + int res; + + if (!kbase_fence_out_is_ours(katom)) { + /* Not our fence */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + res = kbase_fence_out_signal(katom, result); + if (unlikely(res < 0)) { + dev_warn(katom->kctx->kbdev->dev, + "fence_signal() failed with %d\n", res); + } + + kbase_sync_fence_out_remove(katom); + + return (result != 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +static void kbase_fence_wait_callback(struct fence *fence, + struct fence_cb *cb) +#else +static void kbase_fence_wait_callback(struct dma_fence *fence, + struct dma_fence_cb *cb) +#endif +{ + struct kbase_fence_cb *kcb = container_of(cb, + struct kbase_fence_cb, + fence_cb); + struct kbase_jd_atom *katom = kcb->katom; + struct kbase_context *kctx = katom->kctx; + + /* Cancel atom if fence is erroneous */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) + if (dma_fence_is_signaled(kcb->fence) && kcb->fence->error) +#else + if (dma_fence_is_signaled(kcb->fence) && kcb->fence->status < 0) +#endif + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + if (kbase_fence_dep_count_dec_and_test(katom)) { + /* We take responsibility of handling this */ + kbase_fence_dep_count_set(katom, -1); + + /* To prevent a potential deadlock we schedule the work onto the + * job_done_wq workqueue + * + * The issue is that we may signal the timeline while holding + * kctx->jctx.lock and the callbacks are run synchronously from + * sync_timeline_signal. So we simply defer the work. + */ + INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); + } +} + +int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) +{ + int err; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + + fence = kbase_fence_in_get(katom); + if (!fence) + return 0; /* no input fence to wait for, good to go! */ + + kbase_fence_dep_count_set(katom, 1); + + err = kbase_fence_add_callback(katom, fence, kbase_fence_wait_callback); + + kbase_fence_put(fence); + + if (likely(!err)) { + /* Test if the callbacks are already triggered */ + if (kbase_fence_dep_count_dec_and_test(katom)) { + kbase_fence_free_callbacks(katom); + kbase_fence_dep_count_set(katom, -1); + return 0; /* Already signaled, good to go right now */ + } + + /* Callback installed, so we just need to wait for it... */ + } else { + /* Failure */ + kbase_fence_free_callbacks(katom); + kbase_fence_dep_count_set(katom, -1); + + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* We should cause the dependent jobs in the bag to be failed, + * to do this we schedule the work queue to complete this job */ + + INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); + queue_work(katom->kctx->jctx.job_done_wq, &katom->work); + } + + return 1; /* completion to be done later by callback/worker */ +} + +void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) +{ + if (!kbase_fence_free_callbacks(katom)) { + /* The wait wasn't cancelled - + * leave the cleanup for kbase_fence_wait_callback */ + return; + } + + /* Take responsibility of completion */ + kbase_fence_dep_count_set(katom, -1); + + /* Wait was cancelled - zap the atoms */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + kbasep_remove_waiting_soft_job(katom); + kbase_finish_soft_job(katom); + + if (jd_done_nolock(katom, NULL)) + kbase_js_sched_all(katom->kctx->kbdev); +} + +void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom) +{ + kbase_fence_out_remove(katom); +} + +void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom) +{ + kbase_fence_free_callbacks(katom); + kbase_fence_in_remove(katom); +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) +static void kbase_sync_fence_info_get(struct fence *fence, + struct kbase_sync_fence_info *info) +#else +static void kbase_sync_fence_info_get(struct dma_fence *fence, + struct kbase_sync_fence_info *info) +#endif +{ + info->fence = fence; + + /* translate into CONFIG_SYNC status: + * < 0 : error + * 0 : active + * 1 : signaled + */ + if (dma_fence_is_signaled(fence)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) + int status = fence->error; +#else + int status = fence->status; +#endif + if (status < 0) + info->status = status; /* signaled with error */ + else + info->status = 1; /* signaled with success */ + } else { + info->status = 0; /* still active (unsignaled) */ + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) + scnprintf(info->name, sizeof(info->name), "%u#%u", + fence->context, fence->seqno); +#else + scnprintf(info->name, sizeof(info->name), "%llu#%u", + fence->context, fence->seqno); +#endif +} + +int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + + fence = kbase_fence_in_get(katom); + if (!fence) + return -ENOENT; + + kbase_sync_fence_info_get(fence, info); + + kbase_fence_put(fence); + + return 0; +} + +int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, + struct kbase_sync_fence_info *info) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + + fence = kbase_fence_out_get(katom); + if (!fence) + return -ENOENT; + + kbase_sync_fence_info_get(fence, info); + + kbase_fence_put(fence); + + return 0; +} + + +#ifdef CONFIG_MALI_FENCE_DEBUG +void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) +{ + /* Not implemented */ +} +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_tlstream.c b/drivers/gpu/arm/bifrost/mali_kbase_tlstream.c new file mode 100644 index 000000000000..d01aa23b206e --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_tlstream.c @@ -0,0 +1,2572 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*****************************************************************************/ + +/* The version of swtrace protocol used in timeline stream. */ +#define SWTRACE_VERSION 3 + +/* The maximum expected length of string in tracepoint descriptor. */ +#define STRLEN_MAX 64 /* bytes */ + +/* The number of nanoseconds in a second. */ +#define NSECS_IN_SEC 1000000000ull /* ns */ + +/* The period of autoflush checker execution in milliseconds. */ +#define AUTOFLUSH_INTERVAL 1000 /* ms */ + +/* The maximum size of a single packet used by timeline. */ +#define PACKET_SIZE 4096 /* bytes */ + +/* The number of packets used by one timeline stream. */ +#define PACKET_COUNT 16 + +/* The number of bytes reserved for packet header. + * These value must be defined according to MIPE documentation. */ +#define PACKET_HEADER_SIZE 8 /* bytes */ + +/* The number of bytes reserved for packet sequence number. + * These value must be defined according to MIPE documentation. */ +#define PACKET_NUMBER_SIZE 4 /* bytes */ + +/* Packet header - first word. + * These values must be defined according to MIPE documentation. */ +#define PACKET_STREAMID_POS 0 +#define PACKET_STREAMID_LEN 8 +#define PACKET_RSVD1_POS (PACKET_STREAMID_POS + PACKET_STREAMID_LEN) +#define PACKET_RSVD1_LEN 8 +#define PACKET_TYPE_POS (PACKET_RSVD1_POS + PACKET_RSVD1_LEN) +#define PACKET_TYPE_LEN 3 +#define PACKET_CLASS_POS (PACKET_TYPE_POS + PACKET_TYPE_LEN) +#define PACKET_CLASS_LEN 7 +#define PACKET_FAMILY_POS (PACKET_CLASS_POS + PACKET_CLASS_LEN) +#define PACKET_FAMILY_LEN 6 + +/* Packet header - second word + * These values must be defined according to MIPE documentation. */ +#define PACKET_LENGTH_POS 0 +#define PACKET_LENGTH_LEN 24 +#define PACKET_SEQBIT_POS (PACKET_LENGTH_POS + PACKET_LENGTH_LEN) +#define PACKET_SEQBIT_LEN 1 +#define PACKET_RSVD2_POS (PACKET_SEQBIT_POS + PACKET_SEQBIT_LEN) +#define PACKET_RSVD2_LEN 7 + +/* Types of streams generated by timeline. + * Order is significant! Header streams must precede respective body streams. */ +enum tl_stream_type { + TL_STREAM_TYPE_OBJ_HEADER, + TL_STREAM_TYPE_OBJ_SUMMARY, + TL_STREAM_TYPE_OBJ, + TL_STREAM_TYPE_AUX_HEADER, + TL_STREAM_TYPE_AUX, + + TL_STREAM_TYPE_COUNT +}; + +/* Timeline packet family ids. + * Values are significant! Check MIPE documentation. */ +enum tl_packet_family { + TL_PACKET_FAMILY_CTRL = 0, /* control packets */ + TL_PACKET_FAMILY_TL = 1, /* timeline packets */ + + TL_PACKET_FAMILY_COUNT +}; + +/* Packet classes used in timeline streams. + * Values are significant! Check MIPE documentation. */ +enum tl_packet_class { + TL_PACKET_CLASS_OBJ = 0, /* timeline objects packet */ + TL_PACKET_CLASS_AUX = 1, /* auxiliary events packet */ +}; + +/* Packet types used in timeline streams. + * Values are significant! Check MIPE documentation. */ +enum tl_packet_type { + TL_PACKET_TYPE_HEADER = 0, /* stream's header/directory */ + TL_PACKET_TYPE_BODY = 1, /* stream's body */ + TL_PACKET_TYPE_SUMMARY = 2, /* stream's summary */ +}; + +/* Message ids of trace events that are recorded in the timeline stream. */ +enum tl_msg_id_obj { + /* Timeline object events. */ + KBASE_TL_NEW_CTX, + KBASE_TL_NEW_GPU, + KBASE_TL_NEW_LPU, + KBASE_TL_NEW_ATOM, + KBASE_TL_NEW_AS, + KBASE_TL_DEL_CTX, + KBASE_TL_DEL_ATOM, + KBASE_TL_LIFELINK_LPU_GPU, + KBASE_TL_LIFELINK_AS_GPU, + KBASE_TL_RET_CTX_LPU, + KBASE_TL_RET_ATOM_CTX, + KBASE_TL_RET_ATOM_LPU, + KBASE_TL_NRET_CTX_LPU, + KBASE_TL_NRET_ATOM_CTX, + KBASE_TL_NRET_ATOM_LPU, + KBASE_TL_RET_AS_CTX, + KBASE_TL_NRET_AS_CTX, + KBASE_TL_RET_ATOM_AS, + KBASE_TL_NRET_ATOM_AS, + KBASE_TL_DEP_ATOM_ATOM, + KBASE_TL_NDEP_ATOM_ATOM, + KBASE_TL_RDEP_ATOM_ATOM, + KBASE_TL_ATTRIB_ATOM_CONFIG, + KBASE_TL_ATTRIB_ATOM_PRIORITY, + KBASE_TL_ATTRIB_ATOM_STATE, + KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE, + KBASE_TL_ATTRIB_ATOM_JIT, + KBASE_TL_ATTRIB_AS_CONFIG, + KBASE_TL_EVENT_LPU_SOFTSTOP, + KBASE_TL_EVENT_ATOM_SOFTSTOP_EX, + KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE, + + /* Job dump specific events. */ + KBASE_JD_GPU_SOFT_RESET +}; + +/* Message ids of trace events that are recorded in the auxiliary stream. */ +enum tl_msg_id_aux { + KBASE_AUX_PM_STATE, + KBASE_AUX_PAGEFAULT, + KBASE_AUX_PAGESALLOC, + KBASE_AUX_DEVFREQ_TARGET, + KBASE_AUX_PROTECTED_ENTER_START, + KBASE_AUX_PROTECTED_ENTER_END, + KBASE_AUX_PROTECTED_LEAVE_START, + KBASE_AUX_PROTECTED_LEAVE_END +}; + +/*****************************************************************************/ + +/** + * struct tl_stream - timeline stream structure + * @lock: message order lock + * @buffer: array of buffers + * @wbi: write buffer index + * @rbi: read buffer index + * @numbered: if non-zero stream's packets are sequentially numbered + * @autoflush_counter: counter tracking stream's autoflush state + * + * This structure holds information needed to construct proper packets in the + * timeline stream. Each message in sequence must bear timestamp that is greater + * to one in previous message in the same stream. For this reason lock is held + * throughout the process of message creation. Each stream contains set of + * buffers. Each buffer will hold one MIPE packet. In case there is no free + * space required to store incoming message the oldest buffer is discarded. + * Each packet in timeline body stream has sequence number embedded (this value + * must increment monotonically and is used by packets receiver to discover + * buffer overflows. + * Autoflush counter is set to negative number when there is no data pending + * for flush and it is set to zero on every update of the buffer. Autoflush + * timer will increment the counter by one on every expiry. In case there will + * be no activity on the buffer during two consecutive timer expiries, stream + * buffer will be flushed. + */ +struct tl_stream { + spinlock_t lock; + + struct { + atomic_t size; /* number of bytes in buffer */ + char data[PACKET_SIZE]; /* buffer's data */ + } buffer[PACKET_COUNT]; + + atomic_t wbi; + atomic_t rbi; + + int numbered; + atomic_t autoflush_counter; +}; + +/** + * struct tp_desc - tracepoint message descriptor structure + * @id: tracepoint ID identifying message in stream + * @id_str: human readable version of tracepoint ID + * @name: tracepoint description + * @arg_types: tracepoint's arguments types declaration + * @arg_names: comma separated list of tracepoint's arguments names + */ +struct tp_desc { + u32 id; + const char *id_str; + const char *name; + const char *arg_types; + const char *arg_names; +}; + +/*****************************************************************************/ + +/* Configuration of timeline streams generated by kernel. + * Kernel emit only streams containing either timeline object events or + * auxiliary events. All streams have stream id value of 1 (as opposed to user + * space streams that have value of 0). */ +static const struct { + enum tl_packet_family pkt_family; + enum tl_packet_class pkt_class; + enum tl_packet_type pkt_type; + unsigned int stream_id; +} tl_stream_cfg[TL_STREAM_TYPE_COUNT] = { + {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_HEADER, 1}, + {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_SUMMARY, 1}, + {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_BODY, 1}, + {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_AUX, TL_PACKET_TYPE_HEADER, 1}, + {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_AUX, TL_PACKET_TYPE_BODY, 1} +}; + +/* The timeline streams generated by kernel. */ +static struct tl_stream *tl_stream[TL_STREAM_TYPE_COUNT]; + +/* Autoflush timer. */ +static struct timer_list autoflush_timer; + +/* If non-zero autoflush timer is active. */ +static atomic_t autoflush_timer_active; + +/* Reader lock. Only one reader is allowed to have access to the timeline + * streams at any given time. */ +static DEFINE_MUTEX(tl_reader_lock); + +/* Timeline stream event queue. */ +static DECLARE_WAIT_QUEUE_HEAD(tl_event_queue); + +/* The timeline stream file operations functions. */ +static ssize_t kbasep_tlstream_read( + struct file *filp, + char __user *buffer, + size_t size, + loff_t *f_pos); +static unsigned int kbasep_tlstream_poll(struct file *filp, poll_table *wait); +static int kbasep_tlstream_release(struct inode *inode, struct file *filp); + +/* The timeline stream file operations structure. */ +static const struct file_operations kbasep_tlstream_fops = { + .release = kbasep_tlstream_release, + .read = kbasep_tlstream_read, + .poll = kbasep_tlstream_poll, +}; + +/* Descriptors of timeline messages transmitted in object events stream. */ +static const struct tp_desc tp_desc_obj[] = { + { + KBASE_TL_NEW_CTX, + __stringify(KBASE_TL_NEW_CTX), + "object ctx is created", + "@pII", + "ctx,ctx_nr,tgid" + }, + { + KBASE_TL_NEW_GPU, + __stringify(KBASE_TL_NEW_GPU), + "object gpu is created", + "@pII", + "gpu,gpu_id,core_count" + }, + { + KBASE_TL_NEW_LPU, + __stringify(KBASE_TL_NEW_LPU), + "object lpu is created", + "@pII", + "lpu,lpu_nr,lpu_fn" + }, + { + KBASE_TL_NEW_ATOM, + __stringify(KBASE_TL_NEW_ATOM), + "object atom is created", + "@pI", + "atom,atom_nr" + }, + { + KBASE_TL_NEW_AS, + __stringify(KBASE_TL_NEW_AS), + "address space object is created", + "@pI", + "address_space,as_nr" + }, + { + KBASE_TL_DEL_CTX, + __stringify(KBASE_TL_DEL_CTX), + "context is destroyed", + "@p", + "ctx" + }, + { + KBASE_TL_DEL_ATOM, + __stringify(KBASE_TL_DEL_ATOM), + "atom is destroyed", + "@p", + "atom" + }, + { + KBASE_TL_LIFELINK_LPU_GPU, + __stringify(KBASE_TL_LIFELINK_LPU_GPU), + "lpu is deleted with gpu", + "@pp", + "lpu,gpu" + }, + { + KBASE_TL_LIFELINK_AS_GPU, + __stringify(KBASE_TL_LIFELINK_AS_GPU), + "address space is deleted with gpu", + "@pp", + "address_space,gpu" + }, + { + KBASE_TL_RET_CTX_LPU, + __stringify(KBASE_TL_RET_CTX_LPU), + "context is retained by lpu", + "@pp", + "ctx,lpu" + }, + { + KBASE_TL_RET_ATOM_CTX, + __stringify(KBASE_TL_RET_ATOM_CTX), + "atom is retained by context", + "@pp", + "atom,ctx" + }, + { + KBASE_TL_RET_ATOM_LPU, + __stringify(KBASE_TL_RET_ATOM_LPU), + "atom is retained by lpu", + "@pps", + "atom,lpu,attrib_match_list" + }, + { + KBASE_TL_NRET_CTX_LPU, + __stringify(KBASE_TL_NRET_CTX_LPU), + "context is released by lpu", + "@pp", + "ctx,lpu" + }, + { + KBASE_TL_NRET_ATOM_CTX, + __stringify(KBASE_TL_NRET_ATOM_CTX), + "atom is released by context", + "@pp", + "atom,ctx" + }, + { + KBASE_TL_NRET_ATOM_LPU, + __stringify(KBASE_TL_NRET_ATOM_LPU), + "atom is released by lpu", + "@pp", + "atom,lpu" + }, + { + KBASE_TL_RET_AS_CTX, + __stringify(KBASE_TL_RET_AS_CTX), + "address space is retained by context", + "@pp", + "address_space,ctx" + }, + { + KBASE_TL_NRET_AS_CTX, + __stringify(KBASE_TL_NRET_AS_CTX), + "address space is released by context", + "@pp", + "address_space,ctx" + }, + { + KBASE_TL_RET_ATOM_AS, + __stringify(KBASE_TL_RET_ATOM_AS), + "atom is retained by address space", + "@pp", + "atom,address_space" + }, + { + KBASE_TL_NRET_ATOM_AS, + __stringify(KBASE_TL_NRET_ATOM_AS), + "atom is released by address space", + "@pp", + "atom,address_space" + }, + { + KBASE_TL_DEP_ATOM_ATOM, + __stringify(KBASE_TL_DEP_ATOM_ATOM), + "atom2 depends on atom1", + "@pp", + "atom1,atom2" + }, + { + KBASE_TL_NDEP_ATOM_ATOM, + __stringify(KBASE_TL_NDEP_ATOM_ATOM), + "atom2 no longer depends on atom1", + "@pp", + "atom1,atom2" + }, + { + KBASE_TL_RDEP_ATOM_ATOM, + __stringify(KBASE_TL_RDEP_ATOM_ATOM), + "resolved dependecy of atom2 depending on atom1", + "@pp", + "atom1,atom2" + }, + { + KBASE_TL_ATTRIB_ATOM_CONFIG, + __stringify(KBASE_TL_ATTRIB_ATOM_CONFIG), + "atom job slot attributes", + "@pLLI", + "atom,descriptor,affinity,config" + }, + { + KBASE_TL_ATTRIB_ATOM_PRIORITY, + __stringify(KBASE_TL_ATTRIB_ATOM_PRIORITY), + "atom priority", + "@pI", + "atom,prio" + }, + { + KBASE_TL_ATTRIB_ATOM_STATE, + __stringify(KBASE_TL_ATTRIB_ATOM_STATE), + "atom state", + "@pI", + "atom,state" + }, + { + KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE, + __stringify(KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE), + "atom caused priority change", + "@p", + "atom" + }, + { + KBASE_TL_ATTRIB_ATOM_JIT, + __stringify(KBASE_TL_ATTRIB_ATOM_JIT), + "jit done for atom", + "@pLL", + "atom,edit_addr,new_addr" + }, + { + KBASE_TL_ATTRIB_AS_CONFIG, + __stringify(KBASE_TL_ATTRIB_AS_CONFIG), + "address space attributes", + "@pLLL", + "address_space,transtab,memattr,transcfg" + }, + { + KBASE_TL_EVENT_LPU_SOFTSTOP, + __stringify(KBASE_TL_EVENT_LPU_SOFTSTOP), + "softstop event on given lpu", + "@p", + "lpu" + }, + { + KBASE_TL_EVENT_ATOM_SOFTSTOP_EX, + __stringify(KBASE_TL_EVENT_ATOM_SOFTSTOP_EX), + "atom softstopped", + "@p", + "atom" + }, + { + KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE, + __stringify(KBASE_TL_EVENT_SOFTSTOP_ISSUE), + "atom softstop issued", + "@p", + "atom" + }, + { + KBASE_JD_GPU_SOFT_RESET, + __stringify(KBASE_JD_GPU_SOFT_RESET), + "gpu soft reset", + "@p", + "gpu" + }, +}; + +/* Descriptors of timeline messages transmitted in auxiliary events stream. */ +static const struct tp_desc tp_desc_aux[] = { + { + KBASE_AUX_PM_STATE, + __stringify(KBASE_AUX_PM_STATE), + "PM state", + "@IL", + "core_type,core_state_bitset" + }, + { + KBASE_AUX_PAGEFAULT, + __stringify(KBASE_AUX_PAGEFAULT), + "Page fault", + "@IL", + "ctx_nr,page_cnt_change" + }, + { + KBASE_AUX_PAGESALLOC, + __stringify(KBASE_AUX_PAGESALLOC), + "Total alloc pages change", + "@IL", + "ctx_nr,page_cnt" + }, + { + KBASE_AUX_DEVFREQ_TARGET, + __stringify(KBASE_AUX_DEVFREQ_TARGET), + "New device frequency target", + "@L", + "target_freq" + }, + { + KBASE_AUX_PROTECTED_ENTER_START, + __stringify(KBASE_AUX_PROTECTED_ENTER_START), + "enter protected mode start", + "@p", + "gpu" + }, + { + KBASE_AUX_PROTECTED_ENTER_END, + __stringify(KBASE_AUX_PROTECTED_ENTER_END), + "enter protected mode end", + "@p", + "gpu" + }, + { + KBASE_AUX_PROTECTED_LEAVE_START, + __stringify(KBASE_AUX_PROTECTED_LEAVE_START), + "leave protected mode start", + "@p", + "gpu" + }, + { + KBASE_AUX_PROTECTED_LEAVE_END, + __stringify(KBASE_AUX_PROTECTED_LEAVE_END), + "leave protected mode end", + "@p", + "gpu" + } +}; + +#if MALI_UNIT_TEST +/* Number of bytes read by user. */ +static atomic_t tlstream_bytes_collected = {0}; + +/* Number of bytes generated by tracepoint messages. */ +static atomic_t tlstream_bytes_generated = {0}; +#endif /* MALI_UNIT_TEST */ + +/*****************************************************************************/ + +/* Indicator of whether the timeline stream file descriptor is used. */ +atomic_t kbase_tlstream_enabled = {0}; + +/*****************************************************************************/ + +/** + * kbasep_tlstream_get_timestamp - return timestamp + * + * Function returns timestamp value based on raw monotonic timer. Value will + * wrap around zero in case of overflow. + * Return: timestamp value + */ +static u64 kbasep_tlstream_get_timestamp(void) +{ + struct timespec ts; + u64 timestamp; + + getrawmonotonic(&ts); + timestamp = (u64)ts.tv_sec * NSECS_IN_SEC + ts.tv_nsec; + return timestamp; +} + +/** + * kbasep_tlstream_write_bytes - write data to message buffer + * @buffer: buffer where data will be written + * @pos: position in the buffer where to place data + * @bytes: pointer to buffer holding data + * @len: length of data to be written + * + * Return: updated position in the buffer + */ +static size_t kbasep_tlstream_write_bytes( + char *buffer, + size_t pos, + const void *bytes, + size_t len) +{ + KBASE_DEBUG_ASSERT(buffer); + KBASE_DEBUG_ASSERT(bytes); + + memcpy(&buffer[pos], bytes, len); + + return pos + len; +} + +/** + * kbasep_tlstream_write_string - write string to message buffer + * @buffer: buffer where data will be written + * @pos: position in the buffer where to place data + * @string: pointer to buffer holding the source string + * @max_write_size: number of bytes that can be stored in buffer + * + * Return: updated position in the buffer + */ +static size_t kbasep_tlstream_write_string( + char *buffer, + size_t pos, + const char *string, + size_t max_write_size) +{ + u32 string_len; + + KBASE_DEBUG_ASSERT(buffer); + KBASE_DEBUG_ASSERT(string); + /* Timeline string consists of at least string length and nul + * terminator. */ + KBASE_DEBUG_ASSERT(max_write_size >= sizeof(string_len) + sizeof(char)); + max_write_size -= sizeof(string_len); + + string_len = strlcpy( + &buffer[pos + sizeof(string_len)], + string, + max_write_size); + string_len += sizeof(char); + + /* Make sure that the source string fit into the buffer. */ + KBASE_DEBUG_ASSERT(string_len <= max_write_size); + + /* Update string length. */ + memcpy(&buffer[pos], &string_len, sizeof(string_len)); + + return pos + sizeof(string_len) + string_len; +} + +/** + * kbasep_tlstream_write_timestamp - write timestamp to message buffer + * @buffer: buffer where data will be written + * @pos: position in the buffer where to place data + * + * Return: updated position in the buffer + */ +static size_t kbasep_tlstream_write_timestamp(void *buffer, size_t pos) +{ + u64 timestamp = kbasep_tlstream_get_timestamp(); + + return kbasep_tlstream_write_bytes( + buffer, pos, + ×tamp, sizeof(timestamp)); +} + +/** + * kbasep_tlstream_put_bits - put bits in a word + * @word: pointer to the words being modified + * @value: value that shall be written to given position + * @bitpos: position where value shall be written (in bits) + * @bitlen: length of value (in bits) + */ +static void kbasep_tlstream_put_bits( + u32 *word, + u32 value, + unsigned int bitpos, + unsigned int bitlen) +{ + const u32 mask = ((1 << bitlen) - 1) << bitpos; + + KBASE_DEBUG_ASSERT(word); + KBASE_DEBUG_ASSERT((0 != bitlen) && (32 >= bitlen)); + KBASE_DEBUG_ASSERT((bitpos + bitlen) <= 32); + + *word &= ~mask; + *word |= ((value << bitpos) & mask); +} + +/** + * kbasep_tlstream_packet_header_setup - setup the packet header + * @buffer: pointer to the buffer + * @pkt_family: packet's family + * @pkt_type: packet's type + * @pkt_class: packet's class + * @stream_id: stream id + * @numbered: non-zero if this stream is numbered + * + * Function sets up immutable part of packet header in the given buffer. + */ +static void kbasep_tlstream_packet_header_setup( + char *buffer, + enum tl_packet_family pkt_family, + enum tl_packet_class pkt_class, + enum tl_packet_type pkt_type, + unsigned int stream_id, + int numbered) +{ + u32 word0 = 0; + u32 word1 = 0; + + KBASE_DEBUG_ASSERT(buffer); + KBASE_DEBUG_ASSERT(pkt_family == TL_PACKET_FAMILY_TL); + KBASE_DEBUG_ASSERT( + (pkt_type == TL_PACKET_TYPE_HEADER) || + (pkt_type == TL_PACKET_TYPE_SUMMARY) || + (pkt_type == TL_PACKET_TYPE_BODY)); + KBASE_DEBUG_ASSERT( + (pkt_class == TL_PACKET_CLASS_OBJ) || + (pkt_class == TL_PACKET_CLASS_AUX)); + + kbasep_tlstream_put_bits( + &word0, pkt_family, + PACKET_FAMILY_POS, PACKET_FAMILY_LEN); + kbasep_tlstream_put_bits( + &word0, pkt_class, + PACKET_CLASS_POS, PACKET_CLASS_LEN); + kbasep_tlstream_put_bits( + &word0, pkt_type, + PACKET_TYPE_POS, PACKET_TYPE_LEN); + kbasep_tlstream_put_bits( + &word0, stream_id, + PACKET_STREAMID_POS, PACKET_STREAMID_LEN); + + if (numbered) + kbasep_tlstream_put_bits( + &word1, 1, + PACKET_SEQBIT_POS, PACKET_SEQBIT_LEN); + + memcpy(&buffer[0], &word0, sizeof(word0)); + memcpy(&buffer[sizeof(word0)], &word1, sizeof(word1)); +} + +/** + * kbasep_tlstream_packet_header_update - update the packet header + * @buffer: pointer to the buffer + * @data_size: amount of data carried in this packet + * + * Function updates mutable part of packet header in the given buffer. + * Note that value of data_size must not including size of the header. + */ +static void kbasep_tlstream_packet_header_update( + char *buffer, + size_t data_size) +{ + u32 word0; + u32 word1; + + KBASE_DEBUG_ASSERT(buffer); + CSTD_UNUSED(word0); + + memcpy(&word1, &buffer[sizeof(word0)], sizeof(word1)); + + kbasep_tlstream_put_bits( + &word1, data_size, + PACKET_LENGTH_POS, PACKET_LENGTH_LEN); + + memcpy(&buffer[sizeof(word0)], &word1, sizeof(word1)); +} + +/** + * kbasep_tlstream_packet_number_update - update the packet number + * @buffer: pointer to the buffer + * @counter: value of packet counter for this packet's stream + * + * Function updates packet number embedded within the packet placed in the + * given buffer. + */ +static void kbasep_tlstream_packet_number_update(char *buffer, u32 counter) +{ + KBASE_DEBUG_ASSERT(buffer); + + memcpy(&buffer[PACKET_HEADER_SIZE], &counter, sizeof(counter)); +} + +/** + * kbasep_timeline_stream_reset - reset stream + * @stream: pointer to the stream structure + * + * Function discards all pending messages and resets packet counters. + */ +static void kbasep_timeline_stream_reset(struct tl_stream *stream) +{ + unsigned int i; + + for (i = 0; i < PACKET_COUNT; i++) { + if (stream->numbered) + atomic_set( + &stream->buffer[i].size, + PACKET_HEADER_SIZE + + PACKET_NUMBER_SIZE); + else + atomic_set(&stream->buffer[i].size, PACKET_HEADER_SIZE); + } + + atomic_set(&stream->wbi, 0); + atomic_set(&stream->rbi, 0); +} + +/** + * kbasep_timeline_stream_init - initialize timeline stream + * @stream: pointer to the stream structure + * @stream_type: stream type + */ +static void kbasep_timeline_stream_init( + struct tl_stream *stream, + enum tl_stream_type stream_type) +{ + unsigned int i; + + KBASE_DEBUG_ASSERT(stream); + KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); + + spin_lock_init(&stream->lock); + + /* All packets carrying tracepoints shall be numbered. */ + if (TL_PACKET_TYPE_BODY == tl_stream_cfg[stream_type].pkt_type) + stream->numbered = 1; + else + stream->numbered = 0; + + for (i = 0; i < PACKET_COUNT; i++) + kbasep_tlstream_packet_header_setup( + stream->buffer[i].data, + tl_stream_cfg[stream_type].pkt_family, + tl_stream_cfg[stream_type].pkt_class, + tl_stream_cfg[stream_type].pkt_type, + tl_stream_cfg[stream_type].stream_id, + stream->numbered); + + kbasep_timeline_stream_reset(tl_stream[stream_type]); +} + +/** + * kbasep_timeline_stream_term - terminate timeline stream + * @stream: pointer to the stream structure + */ +static void kbasep_timeline_stream_term(struct tl_stream *stream) +{ + KBASE_DEBUG_ASSERT(stream); +} + +/** + * kbasep_tlstream_msgbuf_submit - submit packet to the user space + * @stream: pointer to the stream structure + * @wb_idx_raw: write buffer index + * @wb_size: length of data stored in current buffer + * + * Function updates currently written buffer with packet header. Then write + * index is incremented and buffer is handled to user space. Parameters + * of new buffer are returned using provided arguments. + * + * Return: length of data in new buffer + * + * Warning: User must update the stream structure with returned value. + */ +static size_t kbasep_tlstream_msgbuf_submit( + struct tl_stream *stream, + unsigned int wb_idx_raw, + unsigned int wb_size) +{ + unsigned int rb_idx_raw = atomic_read(&stream->rbi); + unsigned int wb_idx = wb_idx_raw % PACKET_COUNT; + + /* Set stream as flushed. */ + atomic_set(&stream->autoflush_counter, -1); + + kbasep_tlstream_packet_header_update( + stream->buffer[wb_idx].data, + wb_size - PACKET_HEADER_SIZE); + + if (stream->numbered) + kbasep_tlstream_packet_number_update( + stream->buffer[wb_idx].data, + wb_idx_raw); + + /* Increasing write buffer index will expose this packet to the reader. + * As stream->lock is not taken on reader side we must make sure memory + * is updated correctly before this will happen. */ + smp_wmb(); + wb_idx_raw++; + atomic_set(&stream->wbi, wb_idx_raw); + + /* Inform user that packets are ready for reading. */ + wake_up_interruptible(&tl_event_queue); + + /* Detect and mark overflow in this stream. */ + if (PACKET_COUNT == wb_idx_raw - rb_idx_raw) { + /* Reader side depends on this increment to correctly handle + * overflows. The value shall be updated only if it was not + * modified by the reader. The data holding buffer will not be + * updated before stream->lock is released, however size of the + * buffer will. Make sure this increment is globally visible + * before information about selected write buffer size. */ + atomic_cmpxchg(&stream->rbi, rb_idx_raw, rb_idx_raw + 1); + } + + wb_size = PACKET_HEADER_SIZE; + if (stream->numbered) + wb_size += PACKET_NUMBER_SIZE; + + return wb_size; +} + +/** + * kbasep_tlstream_msgbuf_acquire - lock selected stream and reserves buffer + * @stream_type: type of the stream that shall be locked + * @msg_size: message size + * @flags: pointer to store flags passed back on stream release + * + * Function will lock the stream and reserve the number of bytes requested + * in msg_size for the user. + * + * Return: pointer to the buffer where message can be stored + * + * Warning: Stream must be released with kbasep_tlstream_msgbuf_release(). + * Only atomic operations are allowed while stream is locked + * (i.e. do not use any operation that may sleep). + */ +static char *kbasep_tlstream_msgbuf_acquire( + enum tl_stream_type stream_type, + size_t msg_size, + unsigned long *flags) __acquires(&stream->lock) +{ + struct tl_stream *stream; + unsigned int wb_idx_raw; + unsigned int wb_idx; + size_t wb_size; + + KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); + KBASE_DEBUG_ASSERT( + PACKET_SIZE - PACKET_HEADER_SIZE - PACKET_NUMBER_SIZE >= + msg_size); + + stream = tl_stream[stream_type]; + + spin_lock_irqsave(&stream->lock, *flags); + + wb_idx_raw = atomic_read(&stream->wbi); + wb_idx = wb_idx_raw % PACKET_COUNT; + wb_size = atomic_read(&stream->buffer[wb_idx].size); + + /* Select next buffer if data will not fit into current one. */ + if (PACKET_SIZE < wb_size + msg_size) { + wb_size = kbasep_tlstream_msgbuf_submit( + stream, wb_idx_raw, wb_size); + wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; + } + + /* Reserve space in selected buffer. */ + atomic_set(&stream->buffer[wb_idx].size, wb_size + msg_size); + +#if MALI_UNIT_TEST + atomic_add(msg_size, &tlstream_bytes_generated); +#endif /* MALI_UNIT_TEST */ + + return &stream->buffer[wb_idx].data[wb_size]; +} + +/** + * kbasep_tlstream_msgbuf_release - unlock selected stream + * @stream_type: type of the stream that shall be locked + * @flags: value obtained during stream acquire + * + * Function releases stream that has been previously locked with a call to + * kbasep_tlstream_msgbuf_acquire(). + */ +static void kbasep_tlstream_msgbuf_release( + enum tl_stream_type stream_type, + unsigned long flags) __releases(&stream->lock) +{ + struct tl_stream *stream; + + KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); + + stream = tl_stream[stream_type]; + + /* Mark stream as containing unflushed data. */ + atomic_set(&stream->autoflush_counter, 0); + + spin_unlock_irqrestore(&stream->lock, flags); +} + +/*****************************************************************************/ + +/** + * kbasep_tlstream_flush_stream - flush stream + * @stype: type of stream to be flushed + * + * Flush pending data in timeline stream. + */ +static void kbasep_tlstream_flush_stream(enum tl_stream_type stype) +{ + struct tl_stream *stream = tl_stream[stype]; + unsigned long flags; + unsigned int wb_idx_raw; + unsigned int wb_idx; + size_t wb_size; + size_t min_size = PACKET_HEADER_SIZE; + + if (stream->numbered) + min_size += PACKET_NUMBER_SIZE; + + spin_lock_irqsave(&stream->lock, flags); + + wb_idx_raw = atomic_read(&stream->wbi); + wb_idx = wb_idx_raw % PACKET_COUNT; + wb_size = atomic_read(&stream->buffer[wb_idx].size); + + if (wb_size > min_size) { + wb_size = kbasep_tlstream_msgbuf_submit( + stream, wb_idx_raw, wb_size); + wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; + atomic_set(&stream->buffer[wb_idx].size, wb_size); + } + spin_unlock_irqrestore(&stream->lock, flags); +} + +/** + * kbasep_tlstream_autoflush_timer_callback - autoflush timer callback + * @data: unused + * + * Timer is executed periodically to check if any of the stream contains + * buffer ready to be submitted to user space. + */ +static void kbasep_tlstream_autoflush_timer_callback(unsigned long data) +{ + enum tl_stream_type stype; + int rcode; + + CSTD_UNUSED(data); + + for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) { + struct tl_stream *stream = tl_stream[stype]; + unsigned long flags; + unsigned int wb_idx_raw; + unsigned int wb_idx; + size_t wb_size; + size_t min_size = PACKET_HEADER_SIZE; + + int af_cnt = atomic_read(&stream->autoflush_counter); + + /* Check if stream contain unflushed data. */ + if (0 > af_cnt) + continue; + + /* Check if stream should be flushed now. */ + if (af_cnt != atomic_cmpxchg( + &stream->autoflush_counter, + af_cnt, + af_cnt + 1)) + continue; + if (!af_cnt) + continue; + + /* Autoflush this stream. */ + if (stream->numbered) + min_size += PACKET_NUMBER_SIZE; + + spin_lock_irqsave(&stream->lock, flags); + + wb_idx_raw = atomic_read(&stream->wbi); + wb_idx = wb_idx_raw % PACKET_COUNT; + wb_size = atomic_read(&stream->buffer[wb_idx].size); + + if (wb_size > min_size) { + wb_size = kbasep_tlstream_msgbuf_submit( + stream, wb_idx_raw, wb_size); + wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; + atomic_set(&stream->buffer[wb_idx].size, + wb_size); + } + spin_unlock_irqrestore(&stream->lock, flags); + } + + if (atomic_read(&autoflush_timer_active)) + rcode = mod_timer( + &autoflush_timer, + jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); + CSTD_UNUSED(rcode); +} + +/** + * kbasep_tlstream_packet_pending - check timeline streams for pending packets + * @stype: pointer to variable where stream type will be placed + * @rb_idx_raw: pointer to variable where read buffer index will be placed + * + * Function checks all streams for pending packets. It will stop as soon as + * packet ready to be submitted to user space is detected. Variables under + * pointers, passed as the parameters to this function will be updated with + * values pointing to right stream and buffer. + * + * Return: non-zero if any of timeline streams has at last one packet ready + */ +static int kbasep_tlstream_packet_pending( + enum tl_stream_type *stype, + unsigned int *rb_idx_raw) +{ + int pending = 0; + + KBASE_DEBUG_ASSERT(stype); + KBASE_DEBUG_ASSERT(rb_idx_raw); + + for ( + *stype = 0; + (*stype < TL_STREAM_TYPE_COUNT) && !pending; + (*stype)++) { + if (NULL != tl_stream[*stype]) { + *rb_idx_raw = atomic_read(&tl_stream[*stype]->rbi); + /* Read buffer index may be updated by writer in case of + * overflow. Read and write buffer indexes must be + * loaded in correct order. */ + smp_rmb(); + if (atomic_read(&tl_stream[*stype]->wbi) != *rb_idx_raw) + pending = 1; + } + } + (*stype)--; + + return pending; +} + +/** + * kbasep_tlstream_read - copy data from streams to buffer provided by user + * @filp: pointer to file structure (unused) + * @buffer: pointer to the buffer provided by user + * @size: maximum amount of data that can be stored in the buffer + * @f_pos: pointer to file offset (unused) + * + * Return: number of bytes stored in the buffer + */ +static ssize_t kbasep_tlstream_read( + struct file *filp, + char __user *buffer, + size_t size, + loff_t *f_pos) +{ + ssize_t copy_len = 0; + + KBASE_DEBUG_ASSERT(filp); + KBASE_DEBUG_ASSERT(f_pos); + + if (!buffer) + return -EINVAL; + + if ((0 > *f_pos) || (PACKET_SIZE > size)) + return -EINVAL; + + mutex_lock(&tl_reader_lock); + + while (copy_len < size) { + enum tl_stream_type stype; + unsigned int rb_idx_raw = 0; + unsigned int rb_idx; + size_t rb_size; + + /* If we don't have any data yet, wait for packet to be + * submitted. If we already read some packets and there is no + * packet pending return back to user. */ + if (0 < copy_len) { + if (!kbasep_tlstream_packet_pending( + &stype, + &rb_idx_raw)) + break; + } else { + if (wait_event_interruptible( + tl_event_queue, + kbasep_tlstream_packet_pending( + &stype, + &rb_idx_raw))) { + copy_len = -ERESTARTSYS; + break; + } + } + + /* Check if this packet fits into the user buffer. + * If so copy its content. */ + rb_idx = rb_idx_raw % PACKET_COUNT; + rb_size = atomic_read(&tl_stream[stype]->buffer[rb_idx].size); + if (rb_size > size - copy_len) + break; + if (copy_to_user( + &buffer[copy_len], + tl_stream[stype]->buffer[rb_idx].data, + rb_size)) { + copy_len = -EFAULT; + break; + } + + /* If the rbi still points to the packet we just processed + * then there was no overflow so we add the copied size to + * copy_len and move rbi on to the next packet + */ + smp_rmb(); + if (atomic_read(&tl_stream[stype]->rbi) == rb_idx_raw) { + copy_len += rb_size; + atomic_inc(&tl_stream[stype]->rbi); + +#if MALI_UNIT_TEST + atomic_add(rb_size, &tlstream_bytes_collected); +#endif /* MALI_UNIT_TEST */ + } + } + + mutex_unlock(&tl_reader_lock); + + return copy_len; +} + +/** + * kbasep_tlstream_poll - poll timeline stream for packets + * @filp: pointer to file structure + * @wait: pointer to poll table + * Return: POLLIN if data can be read without blocking, otherwise zero + */ +static unsigned int kbasep_tlstream_poll(struct file *filp, poll_table *wait) +{ + enum tl_stream_type stream_type; + unsigned int rb_idx; + + KBASE_DEBUG_ASSERT(filp); + KBASE_DEBUG_ASSERT(wait); + + poll_wait(filp, &tl_event_queue, wait); + if (kbasep_tlstream_packet_pending(&stream_type, &rb_idx)) + return POLLIN; + return 0; +} + +/** + * kbasep_tlstream_release - release timeline stream descriptor + * @inode: pointer to inode structure + * @filp: pointer to file structure + * + * Return always return zero + */ +static int kbasep_tlstream_release(struct inode *inode, struct file *filp) +{ + KBASE_DEBUG_ASSERT(inode); + KBASE_DEBUG_ASSERT(filp); + CSTD_UNUSED(inode); + CSTD_UNUSED(filp); + + /* Stop autoflush timer before releasing access to streams. */ + atomic_set(&autoflush_timer_active, 0); + del_timer_sync(&autoflush_timer); + + atomic_set(&kbase_tlstream_enabled, 0); + return 0; +} + +/** + * kbasep_tlstream_timeline_header - prepare timeline header stream packet + * @stream_type: type of the stream that will carry header data + * @tp_desc: pointer to array with tracepoint descriptors + * @tp_count: number of descriptors in the given array + * + * Functions fills in information about tracepoints stored in body stream + * associated with this header stream. + */ +static void kbasep_tlstream_timeline_header( + enum tl_stream_type stream_type, + const struct tp_desc *tp_desc, + u32 tp_count) +{ + const u8 tv = SWTRACE_VERSION; /* protocol version */ + const u8 ps = sizeof(void *); /* pointer size */ + size_t msg_size = sizeof(tv) + sizeof(ps) + sizeof(tp_count); + char *buffer; + size_t pos = 0; + unsigned long flags; + unsigned int i; + + KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); + KBASE_DEBUG_ASSERT(tp_desc); + + /* Calculate the size of the timeline message. */ + for (i = 0; i < tp_count; i++) { + msg_size += sizeof(tp_desc[i].id); + msg_size += + strnlen(tp_desc[i].id_str, STRLEN_MAX) + + sizeof(char) + sizeof(u32); + msg_size += + strnlen(tp_desc[i].name, STRLEN_MAX) + + sizeof(char) + sizeof(u32); + msg_size += + strnlen(tp_desc[i].arg_types, STRLEN_MAX) + + sizeof(char) + sizeof(u32); + msg_size += + strnlen(tp_desc[i].arg_names, STRLEN_MAX) + + sizeof(char) + sizeof(u32); + } + + KBASE_DEBUG_ASSERT(PACKET_SIZE - PACKET_HEADER_SIZE >= msg_size); + + buffer = kbasep_tlstream_msgbuf_acquire(stream_type, msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &tv, sizeof(tv)); + pos = kbasep_tlstream_write_bytes(buffer, pos, &ps, sizeof(ps)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &tp_count, sizeof(tp_count)); + + for (i = 0; i < tp_count; i++) { + pos = kbasep_tlstream_write_bytes( + buffer, pos, + &tp_desc[i].id, sizeof(tp_desc[i].id)); + pos = kbasep_tlstream_write_string( + buffer, pos, + tp_desc[i].id_str, msg_size - pos); + pos = kbasep_tlstream_write_string( + buffer, pos, + tp_desc[i].name, msg_size - pos); + pos = kbasep_tlstream_write_string( + buffer, pos, + tp_desc[i].arg_types, msg_size - pos); + pos = kbasep_tlstream_write_string( + buffer, pos, + tp_desc[i].arg_names, msg_size - pos); + } + + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(stream_type, flags); + + /* We don't expect any more data to be read in this stream. + * As header stream must be read before its associated body stream, + * make this packet visible to the user straightaway. */ + kbasep_tlstream_flush_stream(stream_type); +} + +/*****************************************************************************/ + +int kbase_tlstream_init(void) +{ + enum tl_stream_type i; + + /* Prepare stream structures. */ + for (i = 0; i < TL_STREAM_TYPE_COUNT; i++) { + tl_stream[i] = kmalloc(sizeof(**tl_stream), GFP_KERNEL); + if (!tl_stream[i]) + break; + kbasep_timeline_stream_init(tl_stream[i], i); + } + if (TL_STREAM_TYPE_COUNT > i) { + for (; i > 0; i--) { + kbasep_timeline_stream_term(tl_stream[i - 1]); + kfree(tl_stream[i - 1]); + } + return -ENOMEM; + } + + /* Initialize autoflush timer. */ + atomic_set(&autoflush_timer_active, 0); + setup_timer(&autoflush_timer, + kbasep_tlstream_autoflush_timer_callback, + 0); + + return 0; +} + +void kbase_tlstream_term(void) +{ + enum tl_stream_type i; + + for (i = 0; i < TL_STREAM_TYPE_COUNT; i++) { + kbasep_timeline_stream_term(tl_stream[i]); + kfree(tl_stream[i]); + } +} + +static void kbase_create_timeline_objects(struct kbase_context *kctx) +{ + struct kbase_device *kbdev = kctx->kbdev; + unsigned int lpu_id; + unsigned int as_nr; + struct kbasep_kctx_list_element *element; + + /* Create LPU objects. */ + for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { + u32 *lpu = + &kbdev->gpu_props.props.raw_props.js_features[lpu_id]; + KBASE_TLSTREAM_TL_SUMMARY_NEW_LPU(lpu, lpu_id, *lpu); + } + + /* Create Address Space objects. */ + for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) + KBASE_TLSTREAM_TL_SUMMARY_NEW_AS(&kbdev->as[as_nr], as_nr); + + /* Create GPU object and make it retain all LPUs and address spaces. */ + KBASE_TLSTREAM_TL_SUMMARY_NEW_GPU( + kbdev, + kbdev->gpu_props.props.raw_props.gpu_id, + kbdev->gpu_props.num_cores); + + for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { + void *lpu = + &kbdev->gpu_props.props.raw_props.js_features[lpu_id]; + KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_LPU_GPU(lpu, kbdev); + } + for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) + KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_AS_GPU( + &kbdev->as[as_nr], + kbdev); + + /* Create object for each known context. */ + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry(element, &kbdev->kctx_list, link) { + KBASE_TLSTREAM_TL_SUMMARY_NEW_CTX( + element->kctx, + element->kctx->id, + (u32)(element->kctx->tgid)); + } + /* Before releasing the lock, reset body stream buffers. + * This will prevent context creation message to be directed to both + * summary and body stream. + */ + kbase_tlstream_reset_body_streams(); + mutex_unlock(&kbdev->kctx_list_lock); + /* Static object are placed into summary packet that needs to be + * transmitted first. Flush all streams to make it available to + * user space. + */ + kbase_tlstream_flush_streams(); +} + +int kbase_tlstream_acquire(struct kbase_context *kctx, u32 flags) +{ + int ret; + u32 tlstream_enabled = TLSTREAM_ENABLED | flags; + + if (0 == atomic_cmpxchg(&kbase_tlstream_enabled, 0, tlstream_enabled)) { + int rcode; + + ret = anon_inode_getfd( + "[mali_tlstream]", + &kbasep_tlstream_fops, + kctx, + O_RDONLY | O_CLOEXEC); + if (ret < 0) { + atomic_set(&kbase_tlstream_enabled, 0); + return ret; + } + + /* Reset and initialize header streams. */ + kbasep_timeline_stream_reset( + tl_stream[TL_STREAM_TYPE_OBJ_HEADER]); + kbasep_timeline_stream_reset( + tl_stream[TL_STREAM_TYPE_OBJ_SUMMARY]); + kbasep_timeline_stream_reset( + tl_stream[TL_STREAM_TYPE_AUX_HEADER]); + kbasep_tlstream_timeline_header( + TL_STREAM_TYPE_OBJ_HEADER, + tp_desc_obj, + ARRAY_SIZE(tp_desc_obj)); + kbasep_tlstream_timeline_header( + TL_STREAM_TYPE_AUX_HEADER, + tp_desc_aux, + ARRAY_SIZE(tp_desc_aux)); + + /* Start autoflush timer. */ + atomic_set(&autoflush_timer_active, 1); + rcode = mod_timer( + &autoflush_timer, + jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); + CSTD_UNUSED(rcode); + + /* If job dumping is enabled, readjust the software event's + * timeout as the default value of 3 seconds is often + * insufficient. */ + if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { + dev_info(kctx->kbdev->dev, + "Job dumping is enabled, readjusting the software event's timeout\n"); + atomic_set(&kctx->kbdev->js_data.soft_job_timeout_ms, + 1800000); + } + + /* Summary stream was cleared during acquire. + * Create static timeline objects that will be + * read by client. + */ + kbase_create_timeline_objects(kctx); + + } else { + ret = -EBUSY; + } + + return ret; +} + +void kbase_tlstream_flush_streams(void) +{ + enum tl_stream_type stype; + + for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) + kbasep_tlstream_flush_stream(stype); +} + +void kbase_tlstream_reset_body_streams(void) +{ + kbasep_timeline_stream_reset( + tl_stream[TL_STREAM_TYPE_OBJ]); + kbasep_timeline_stream_reset( + tl_stream[TL_STREAM_TYPE_AUX]); +} + +#if MALI_UNIT_TEST +void kbase_tlstream_stats(u32 *bytes_collected, u32 *bytes_generated) +{ + KBASE_DEBUG_ASSERT(bytes_collected); + KBASE_DEBUG_ASSERT(bytes_generated); + *bytes_collected = atomic_read(&tlstream_bytes_collected); + *bytes_generated = atomic_read(&tlstream_bytes_generated); +} +#endif /* MALI_UNIT_TEST */ + +/*****************************************************************************/ + +void __kbase_tlstream_tl_summary_new_ctx(void *context, u32 nr, u32 tgid) +{ + const u32 msg_id = KBASE_TL_NEW_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(nr) + + sizeof(tgid); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &nr, sizeof(nr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &tgid, sizeof(tgid)); + + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +void __kbase_tlstream_tl_summary_new_gpu(void *gpu, u32 id, u32 core_count) +{ + const u32 msg_id = KBASE_TL_NEW_GPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu) + sizeof(id) + + sizeof(core_count); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &id, sizeof(id)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &core_count, sizeof(core_count)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +void __kbase_tlstream_tl_summary_new_lpu(void *lpu, u32 nr, u32 fn) +{ + const u32 msg_id = KBASE_TL_NEW_LPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(lpu) + sizeof(nr) + + sizeof(fn); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &nr, sizeof(nr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &fn, sizeof(fn)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +void __kbase_tlstream_tl_summary_lifelink_lpu_gpu(void *lpu, void *gpu) +{ + const u32 msg_id = KBASE_TL_LIFELINK_LPU_GPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(lpu) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +void __kbase_tlstream_tl_summary_new_as(void *as, u32 nr) +{ + const u32 msg_id = KBASE_TL_NEW_AS; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(nr); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &nr, sizeof(nr)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +void __kbase_tlstream_tl_summary_lifelink_as_gpu(void *as, void *gpu) +{ + const u32 msg_id = KBASE_TL_LIFELINK_AS_GPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ_SUMMARY, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); +} + +/*****************************************************************************/ + +void __kbase_tlstream_tl_new_ctx(void *context, u32 nr, u32 tgid) +{ + const u32 msg_id = KBASE_TL_NEW_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(nr) + + sizeof(tgid); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &nr, sizeof(nr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &tgid, sizeof(tgid)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_new_atom(void *atom, u32 nr) +{ + const u32 msg_id = KBASE_TL_NEW_ATOM; + const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + + sizeof(nr); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &nr, sizeof(nr)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_del_ctx(void *context) +{ + const u32 msg_id = KBASE_TL_DEL_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(context); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_del_atom(void *atom) +{ + const u32 msg_id = KBASE_TL_DEL_ATOM; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ret_ctx_lpu(void *context, void *lpu) +{ + const u32 msg_id = KBASE_TL_RET_CTX_LPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(lpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ret_atom_ctx(void *atom, void *context) +{ + const u32 msg_id = KBASE_TL_RET_ATOM_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(context); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ret_atom_lpu( + void *atom, void *lpu, const char *attrib_match_list) +{ + const u32 msg_id = KBASE_TL_RET_ATOM_LPU; + const size_t msg_s0 = sizeof(u32) + sizeof(char) + + strnlen(attrib_match_list, STRLEN_MAX); + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + + sizeof(atom) + sizeof(lpu) + msg_s0; + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + pos = kbasep_tlstream_write_string( + buffer, pos, attrib_match_list, msg_s0); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_nret_ctx_lpu(void *context, void *lpu) +{ + const u32 msg_id = KBASE_TL_NRET_CTX_LPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(lpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_nret_atom_ctx(void *atom, void *context) +{ + const u32 msg_id = KBASE_TL_NRET_ATOM_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(context); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &context, sizeof(context)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_dep_atom_atom(void *atom1, void *atom2) +{ + const u32 msg_id = KBASE_TL_DEP_ATOM_ATOM; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom1, sizeof(atom1)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom2, sizeof(atom2)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ndep_atom_atom(void *atom1, void *atom2) +{ + const u32 msg_id = KBASE_TL_NDEP_ATOM_ATOM; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom1, sizeof(atom1)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom2, sizeof(atom2)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_rdep_atom_atom(void *atom1, void *atom2) +{ + const u32 msg_id = KBASE_TL_RDEP_ATOM_ATOM; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom1, sizeof(atom1)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom2, sizeof(atom2)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_nret_atom_lpu(void *atom, void *lpu) +{ + const u32 msg_id = KBASE_TL_NRET_ATOM_LPU; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(lpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ret_as_ctx(void *as, void *ctx) +{ + const u32 msg_id = KBASE_TL_RET_AS_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(ctx); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &ctx, sizeof(ctx)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_nret_as_ctx(void *as, void *ctx) +{ + const u32 msg_id = KBASE_TL_NRET_AS_CTX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(ctx); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &ctx, sizeof(ctx)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_ret_atom_as(void *atom, void *as) +{ + const u32 msg_id = KBASE_TL_RET_ATOM_AS; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(as); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_nret_atom_as(void *atom, void *as) +{ + const u32 msg_id = KBASE_TL_NRET_ATOM_AS; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(as); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_atom_config( + void *atom, u64 jd, u64 affinity, u32 config) +{ + const u32 msg_id = KBASE_TL_ATTRIB_ATOM_CONFIG; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + + sizeof(jd) + sizeof(affinity) + sizeof(config); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &jd, sizeof(jd)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &affinity, sizeof(affinity)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &config, sizeof(config)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_atom_priority(void *atom, u32 prio) +{ + const u32 msg_id = KBASE_TL_ATTRIB_ATOM_PRIORITY; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(prio); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &prio, sizeof(prio)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_atom_state(void *atom, u32 state) +{ + const u32 msg_id = KBASE_TL_ATTRIB_ATOM_STATE; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(state); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &state, sizeof(state)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_atom_priority_change(void *atom) +{ + const u32 msg_id = KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_atom_jit( + void *atom, u64 edit_addr, u64 new_addr) +{ + const u32 msg_id = KBASE_TL_ATTRIB_ATOM_JIT; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom) + + sizeof(edit_addr) + sizeof(new_addr); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &edit_addr, sizeof(edit_addr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &new_addr, sizeof(new_addr)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_attrib_as_config( + void *as, u64 transtab, u64 memattr, u64 transcfg) +{ + const u32 msg_id = KBASE_TL_ATTRIB_AS_CONFIG; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(as) + + sizeof(transtab) + sizeof(memattr) + sizeof(transcfg); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &as, sizeof(as)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &transtab, sizeof(transtab)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &memattr, sizeof(memattr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &transcfg, sizeof(transcfg)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_event_lpu_softstop(void *lpu) +{ + const u32 msg_id = KBASE_TL_EVENT_LPU_SOFTSTOP; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(lpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &lpu, sizeof(lpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_event_atom_softstop_ex(void *atom) +{ + const u32 msg_id = KBASE_TL_EVENT_ATOM_SOFTSTOP_EX; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_tl_event_atom_softstop_issue(void *atom) +{ + const u32 msg_id = KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(atom); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &atom, sizeof(atom)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +void __kbase_tlstream_jd_gpu_soft_reset(void *gpu) +{ + const u32 msg_id = KBASE_JD_GPU_SOFT_RESET; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_OBJ, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); +} + +/*****************************************************************************/ + +void __kbase_tlstream_aux_pm_state(u32 core_type, u64 state) +{ + const u32 msg_id = KBASE_AUX_PM_STATE; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(core_type) + + sizeof(state); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &core_type, sizeof(core_type)); + pos = kbasep_tlstream_write_bytes(buffer, pos, &state, sizeof(state)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} + +void __kbase_tlstream_aux_pagefault(u32 ctx_nr, u64 page_count_change) +{ + const u32 msg_id = KBASE_AUX_PAGEFAULT; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(ctx_nr) + + sizeof(page_count_change); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes(buffer, pos, &ctx_nr, sizeof(ctx_nr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, + &page_count_change, sizeof(page_count_change)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} + +void __kbase_tlstream_aux_pagesalloc(u32 ctx_nr, u64 page_count) +{ + const u32 msg_id = KBASE_AUX_PAGESALLOC; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(ctx_nr) + + sizeof(page_count); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes(buffer, pos, &ctx_nr, sizeof(ctx_nr)); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &page_count, sizeof(page_count)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} + +void __kbase_tlstream_aux_devfreq_target(u64 target_freq) +{ + const u32 msg_id = KBASE_AUX_DEVFREQ_TARGET; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(target_freq); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &target_freq, sizeof(target_freq)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} + +void __kbase_tlstream_aux_protected_enter_start(void *gpu) +{ + const u32 msg_id = KBASE_AUX_PROTECTED_ENTER_START; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} +void __kbase_tlstream_aux_protected_enter_end(void *gpu) +{ + const u32 msg_id = KBASE_AUX_PROTECTED_ENTER_END; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} + +void __kbase_tlstream_aux_protected_leave_start(void *gpu) +{ + const u32 msg_id = KBASE_AUX_PROTECTED_LEAVE_START; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} +void __kbase_tlstream_aux_protected_leave_end(void *gpu) +{ + const u32 msg_id = KBASE_AUX_PROTECTED_LEAVE_END; + const size_t msg_size = + sizeof(msg_id) + sizeof(u64) + sizeof(gpu); + unsigned long flags; + char *buffer; + size_t pos = 0; + + buffer = kbasep_tlstream_msgbuf_acquire( + TL_STREAM_TYPE_AUX, + msg_size, &flags); + KBASE_DEBUG_ASSERT(buffer); + + pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_tlstream_write_timestamp(buffer, pos); + pos = kbasep_tlstream_write_bytes( + buffer, pos, &gpu, sizeof(gpu)); + KBASE_DEBUG_ASSERT(msg_size == pos); + + kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_tlstream.h b/drivers/gpu/arm/bifrost/mali_kbase_tlstream.h new file mode 100644 index 000000000000..c0a1117d5f25 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_tlstream.h @@ -0,0 +1,623 @@ +/* + * + * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#if !defined(_KBASE_TLSTREAM_H) +#define _KBASE_TLSTREAM_H + +#include + +/*****************************************************************************/ + +/** + * kbase_tlstream_init - initialize timeline infrastructure in kernel + * Return: zero on success, negative number on error + */ +int kbase_tlstream_init(void); + +/** + * kbase_tlstream_term - terminate timeline infrastructure in kernel + * + * Timeline need have to been previously enabled with kbase_tlstream_init(). + */ +void kbase_tlstream_term(void); + +/** + * kbase_tlstream_acquire - acquire timeline stream file descriptor + * @kctx: kernel common context + * @flags: timeline stream flags + * + * This descriptor is meant to be used by userspace timeline to gain access to + * kernel timeline stream. This stream is later broadcasted by user space to the + * timeline client. + * Only one entity can own the descriptor at any given time. Descriptor shall be + * closed if unused. If descriptor cannot be obtained (i.e. when it is already + * being used) return will be a negative value. + * + * Return: file descriptor on success, negative number on error + */ +int kbase_tlstream_acquire(struct kbase_context *kctx, u32 flags); + +/** + * kbase_tlstream_flush_streams - flush timeline streams. + * + * Function will flush pending data in all timeline streams. + */ +void kbase_tlstream_flush_streams(void); + +/** + * kbase_tlstream_reset_body_streams - reset timeline body streams. + * + * Function will discard pending data in all timeline body streams. + */ +void kbase_tlstream_reset_body_streams(void); + +#if MALI_UNIT_TEST +/** + * kbase_tlstream_test - start timeline stream data generator + * @tpw_count: number of trace point writers in each context + * @msg_delay: time delay in milliseconds between trace points written by one + * writer + * @msg_count: number of trace points written by one writer + * @aux_msg: if non-zero aux messages will be included + * + * This test starts a requested number of asynchronous writers in both IRQ and + * thread context. Each writer will generate required number of test + * tracepoints (tracepoints with embedded information about writer that + * should be verified by user space reader). Tracepoints will be emitted in + * all timeline body streams. If aux_msg is non-zero writer will also + * generate not testable tracepoints (tracepoints without information about + * writer). These tracepoints are used to check correctness of remaining + * timeline message generating functions. Writer will wait requested time + * between generating another set of messages. This call blocks until all + * writers finish. + */ +void kbase_tlstream_test( + unsigned int tpw_count, + unsigned int msg_delay, + unsigned int msg_count, + int aux_msg); + +/** + * kbase_tlstream_stats - read timeline stream statistics + * @bytes_collected: will hold number of bytes read by the user + * @bytes_generated: will hold number of bytes generated by trace points + */ +void kbase_tlstream_stats(u32 *bytes_collected, u32 *bytes_generated); +#endif /* MALI_UNIT_TEST */ + +/*****************************************************************************/ + +#define TL_ATOM_STATE_IDLE 0 +#define TL_ATOM_STATE_READY 1 +#define TL_ATOM_STATE_DONE 2 +#define TL_ATOM_STATE_POSTED 3 + +void __kbase_tlstream_tl_summary_new_ctx(void *context, u32 nr, u32 tgid); +void __kbase_tlstream_tl_summary_new_gpu(void *gpu, u32 id, u32 core_count); +void __kbase_tlstream_tl_summary_new_lpu(void *lpu, u32 nr, u32 fn); +void __kbase_tlstream_tl_summary_lifelink_lpu_gpu(void *lpu, void *gpu); +void __kbase_tlstream_tl_summary_new_as(void *as, u32 nr); +void __kbase_tlstream_tl_summary_lifelink_as_gpu(void *as, void *gpu); +void __kbase_tlstream_tl_new_ctx(void *context, u32 nr, u32 tgid); +void __kbase_tlstream_tl_new_atom(void *atom, u32 nr); +void __kbase_tlstream_tl_del_ctx(void *context); +void __kbase_tlstream_tl_del_atom(void *atom); +void __kbase_tlstream_tl_ret_ctx_lpu(void *context, void *lpu); +void __kbase_tlstream_tl_ret_atom_ctx(void *atom, void *context); +void __kbase_tlstream_tl_ret_atom_lpu( + void *atom, void *lpu, const char *attrib_match_list); +void __kbase_tlstream_tl_nret_ctx_lpu(void *context, void *lpu); +void __kbase_tlstream_tl_nret_atom_ctx(void *atom, void *context); +void __kbase_tlstream_tl_nret_atom_lpu(void *atom, void *lpu); +void __kbase_tlstream_tl_ret_as_ctx(void *as, void *ctx); +void __kbase_tlstream_tl_nret_as_ctx(void *as, void *ctx); +void __kbase_tlstream_tl_ret_atom_as(void *atom, void *as); +void __kbase_tlstream_tl_nret_atom_as(void *atom, void *as); +void __kbase_tlstream_tl_dep_atom_atom(void *atom1, void *atom2); +void __kbase_tlstream_tl_ndep_atom_atom(void *atom1, void *atom2); +void __kbase_tlstream_tl_rdep_atom_atom(void *atom1, void *atom2); +void __kbase_tlstream_tl_attrib_atom_config( + void *atom, u64 jd, u64 affinity, u32 config); +void __kbase_tlstream_tl_attrib_atom_priority(void *atom, u32 prio); +void __kbase_tlstream_tl_attrib_atom_state(void *atom, u32 state); +void __kbase_tlstream_tl_attrib_atom_priority_change(void *atom); +void __kbase_tlstream_tl_attrib_atom_jit( + void *atom, u64 edit_addr, u64 new_addr); +void __kbase_tlstream_tl_attrib_as_config( + void *as, u64 transtab, u64 memattr, u64 transcfg); +void __kbase_tlstream_tl_event_atom_softstop_ex(void *atom); +void __kbase_tlstream_tl_event_lpu_softstop(void *lpu); +void __kbase_tlstream_tl_event_atom_softstop_issue(void *atom); +void __kbase_tlstream_jd_gpu_soft_reset(void *gpu); +void __kbase_tlstream_aux_pm_state(u32 core_type, u64 state); +void __kbase_tlstream_aux_pagefault(u32 ctx_nr, u64 page_count_change); +void __kbase_tlstream_aux_pagesalloc(u32 ctx_nr, u64 page_count); +void __kbase_tlstream_aux_devfreq_target(u64 target_freq); +void __kbase_tlstream_aux_protected_enter_start(void *gpu); +void __kbase_tlstream_aux_protected_enter_end(void *gpu); +void __kbase_tlstream_aux_protected_leave_start(void *gpu); +void __kbase_tlstream_aux_protected_leave_end(void *gpu); + +#define TLSTREAM_ENABLED (1 << 31) + +extern atomic_t kbase_tlstream_enabled; + +#define __TRACE_IF_ENABLED(trace_name, ...) \ + do { \ + int enabled = atomic_read(&kbase_tlstream_enabled); \ + if (enabled & TLSTREAM_ENABLED) \ + __kbase_tlstream_##trace_name(__VA_ARGS__); \ + } while (0) + +#define __TRACE_IF_ENABLED_LATENCY(trace_name, ...) \ + do { \ + int enabled = atomic_read(&kbase_tlstream_enabled); \ + if (enabled & BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS) \ + __kbase_tlstream_##trace_name(__VA_ARGS__); \ + } while (0) + +#define __TRACE_IF_ENABLED_JD(trace_name, ...) \ + do { \ + int enabled = atomic_read(&kbase_tlstream_enabled); \ + if (enabled & BASE_TLSTREAM_JOB_DUMPING_ENABLED) \ + __kbase_tlstream_##trace_name(__VA_ARGS__); \ + } while (0) + +/*****************************************************************************/ + +/** + * KBASE_TLSTREAM_TL_SUMMARY_NEW_CTX - create context object in timeline + * summary + * @context: name of the context object + * @nr: context number + * @tgid: thread Group Id + * + * Function emits a timeline message informing about context creation. Context + * is created with context number (its attribute), that can be used to link + * kbase context with userspace context. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_NEW_CTX(context, nr, tgid) \ + __TRACE_IF_ENABLED(tl_summary_new_ctx, context, nr, tgid) + +/** + * KBASE_TLSTREAM_TL_SUMMARY_NEW_GPU - create GPU object in timeline summary + * @gpu: name of the GPU object + * @id: id value of this GPU + * @core_count: number of cores this GPU hosts + * + * Function emits a timeline message informing about GPU creation. GPU is + * created with two attributes: id and core count. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_NEW_GPU(gpu, id, core_count) \ + __TRACE_IF_ENABLED(tl_summary_new_gpu, gpu, id, core_count) + +/** + * KBASE_TLSTREAM_TL_SUMMARY_NEW_LPU - create LPU object in timeline summary + * @lpu: name of the Logical Processing Unit object + * @nr: sequential number assigned to this LPU + * @fn: property describing this LPU's functional abilities + * + * Function emits a timeline message informing about LPU creation. LPU is + * created with two attributes: number linking this LPU with GPU's job slot + * and function bearing information about this LPU abilities. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_NEW_LPU(lpu, nr, fn) \ + __TRACE_IF_ENABLED(tl_summary_new_lpu, lpu, nr, fn) + +/** + * KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_LPU_GPU - lifelink LPU object to GPU + * @lpu: name of the Logical Processing Unit object + * @gpu: name of the GPU object + * + * Function emits a timeline message informing that LPU object shall be deleted + * along with GPU object. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_LPU_GPU(lpu, gpu) \ + __TRACE_IF_ENABLED(tl_summary_lifelink_lpu_gpu, lpu, gpu) + +/** + * KBASE_TLSTREAM_TL_SUMMARY_NEW_AS - create address space object in timeline summary + * @as: name of the address space object + * @nr: sequential number assigned to this address space + * + * Function emits a timeline message informing about address space creation. + * Address space is created with one attribute: number identifying this + * address space. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_NEW_AS(as, nr) \ + __TRACE_IF_ENABLED(tl_summary_new_as, as, nr) + +/** + * KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_AS_GPU - lifelink address space object to GPU + * @as: name of the address space object + * @gpu: name of the GPU object + * + * Function emits a timeline message informing that address space object + * shall be deleted along with GPU object. + * This message is directed to timeline summary stream. + */ +#define KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_AS_GPU(as, gpu) \ + __TRACE_IF_ENABLED(tl_summary_lifelink_as_gpu, as, gpu) + +/** + * KBASE_TLSTREAM_TL_NEW_CTX - create context object in timeline + * @context: name of the context object + * @nr: context number + * @tgid: thread Group Id + * + * Function emits a timeline message informing about context creation. Context + * is created with context number (its attribute), that can be used to link + * kbase context with userspace context. + */ +#define KBASE_TLSTREAM_TL_NEW_CTX(context, nr, tgid) \ + __TRACE_IF_ENABLED(tl_new_ctx, context, nr, tgid) + +/** + * KBASE_TLSTREAM_TL_NEW_ATOM - create atom object in timeline + * @atom: name of the atom object + * @nr: sequential number assigned to this atom + * + * Function emits a timeline message informing about atom creation. Atom is + * created with atom number (its attribute) that links it with actual work + * bucket id understood by hardware. + */ +#define KBASE_TLSTREAM_TL_NEW_ATOM(atom, nr) \ + __TRACE_IF_ENABLED(tl_new_atom, atom, nr) + +/** + * KBASE_TLSTREAM_TL_DEL_CTX - destroy context object in timeline + * @context: name of the context object + * + * Function emits a timeline message informing that context object ceased to + * exist. + */ +#define KBASE_TLSTREAM_TL_DEL_CTX(context) \ + __TRACE_IF_ENABLED(tl_del_ctx, context) + +/** + * KBASE_TLSTREAM_TL_DEL_ATOM - destroy atom object in timeline + * @atom: name of the atom object + * + * Function emits a timeline message informing that atom object ceased to + * exist. + */ +#define KBASE_TLSTREAM_TL_DEL_ATOM(atom) \ + __TRACE_IF_ENABLED(tl_del_atom, atom) + +/** + * KBASE_TLSTREAM_TL_RET_CTX_LPU - retain context by LPU + * @context: name of the context object + * @lpu: name of the Logical Processing Unit object + * + * Function emits a timeline message informing that context is being held + * by LPU and must not be deleted unless it is released. + */ +#define KBASE_TLSTREAM_TL_RET_CTX_LPU(context, lpu) \ + __TRACE_IF_ENABLED(tl_ret_ctx_lpu, context, lpu) + +/** + * KBASE_TLSTREAM_TL_RET_ATOM_CTX - retain atom by context + * @atom: name of the atom object + * @context: name of the context object + * + * Function emits a timeline message informing that atom object is being held + * by context and must not be deleted unless it is released. + */ +#define KBASE_TLSTREAM_TL_RET_ATOM_CTX(atom, context) \ + __TRACE_IF_ENABLED(tl_ret_atom_ctx, atom, context) + +/** + * KBASE_TLSTREAM_TL_RET_ATOM_LPU - retain atom by LPU + * @atom: name of the atom object + * @lpu: name of the Logical Processing Unit object + * @attrib_match_list: list containing match operator attributes + * + * Function emits a timeline message informing that atom object is being held + * by LPU and must not be deleted unless it is released. + */ +#define KBASE_TLSTREAM_TL_RET_ATOM_LPU(atom, lpu, attrib_match_list) \ + __TRACE_IF_ENABLED(tl_ret_atom_lpu, atom, lpu, attrib_match_list) + +/** + * KBASE_TLSTREAM_TL_NRET_CTX_LPU - release context by LPU + * @context: name of the context object + * @lpu: name of the Logical Processing Unit object + * + * Function emits a timeline message informing that context is being released + * by LPU object. + */ +#define KBASE_TLSTREAM_TL_NRET_CTX_LPU(context, lpu) \ + __TRACE_IF_ENABLED(tl_nret_ctx_lpu, context, lpu) + +/** + * KBASE_TLSTREAM_TL_NRET_ATOM_CTX - release atom by context + * @atom: name of the atom object + * @context: name of the context object + * + * Function emits a timeline message informing that atom object is being + * released by context. + */ +#define KBASE_TLSTREAM_TL_NRET_ATOM_CTX(atom, context) \ + __TRACE_IF_ENABLED(tl_nret_atom_ctx, atom, context) + +/** + * KBASE_TLSTREAM_TL_NRET_ATOM_LPU - release atom by LPU + * @atom: name of the atom object + * @lpu: name of the Logical Processing Unit object + * + * Function emits a timeline message informing that atom object is being + * released by LPU. + */ +#define KBASE_TLSTREAM_TL_NRET_ATOM_LPU(atom, lpu) \ + __TRACE_IF_ENABLED(tl_nret_atom_lpu, atom, lpu) + +/** + * KBASE_TLSTREAM_TL_RET_AS_CTX - lifelink address space object to context + * @as: name of the address space object + * @ctx: name of the context object + * + * Function emits a timeline message informing that address space object + * is being held by the context object. + */ +#define KBASE_TLSTREAM_TL_RET_AS_CTX(as, ctx) \ + __TRACE_IF_ENABLED(tl_ret_as_ctx, as, ctx) + +/** + * KBASE_TLSTREAM_TL_NRET_AS_CTX - release address space by context + * @as: name of the address space object + * @ctx: name of the context object + * + * Function emits a timeline message informing that address space object + * is being released by atom. + */ +#define KBASE_TLSTREAM_TL_NRET_AS_CTX(as, ctx) \ + __TRACE_IF_ENABLED(tl_nret_as_ctx, as, ctx) + +/** + * KBASE_TLSTREAM_TL_RET_ATOM_AS - retain atom by address space + * @atom: name of the atom object + * @as: name of the address space object + * + * Function emits a timeline message informing that atom object is being held + * by address space and must not be deleted unless it is released. + */ +#define KBASE_TLSTREAM_TL_RET_ATOM_AS(atom, as) \ + __TRACE_IF_ENABLED(tl_ret_atom_as, atom, as) + +/** + * KBASE_TLSTREAM_TL_NRET_ATOM_AS - release atom by address space + * @atom: name of the atom object + * @as: name of the address space object + * + * Function emits a timeline message informing that atom object is being + * released by address space. + */ +#define KBASE_TLSTREAM_TL_NRET_ATOM_AS(atom, as) \ + __TRACE_IF_ENABLED(tl_nret_atom_as, atom, as) + +/** + * KBASE_TLSTREAM_TL_DEP_ATOM_ATOM - parent atom depends on child atom + * @atom1: name of the child atom object + * @atom2: name of the parent atom object that depends on child atom + * + * Function emits a timeline message informing that parent atom waits for + * child atom object to be completed before start its execution. + */ +#define KBASE_TLSTREAM_TL_DEP_ATOM_ATOM(atom1, atom2) \ + __TRACE_IF_ENABLED(tl_dep_atom_atom, atom1, atom2) + +/** + * KBASE_TLSTREAM_TL_NDEP_ATOM_ATOM - dependency between atoms resolved + * @atom1: name of the child atom object + * @atom2: name of the parent atom object that depended on child atom + * + * Function emits a timeline message informing that parent atom execution + * dependency on child atom has been resolved. + */ +#define KBASE_TLSTREAM_TL_NDEP_ATOM_ATOM(atom1, atom2) \ + __TRACE_IF_ENABLED(tl_ndep_atom_atom, atom1, atom2) + +/** + * KBASE_TLSTREAM_TL_RDEP_ATOM_ATOM - information about already resolved dependency between atoms + * @atom1: name of the child atom object + * @atom2: name of the parent atom object that depended on child atom + * + * Function emits a timeline message informing that parent atom execution + * dependency on child atom has been resolved. + */ +#define KBASE_TLSTREAM_TL_RDEP_ATOM_ATOM(atom1, atom2) \ + __TRACE_IF_ENABLED(tl_rdep_atom_atom, atom1, atom2) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_ATOM_CONFIG - atom job slot attributes + * @atom: name of the atom object + * @jd: job descriptor address + * @affinity: job affinity + * @config: job config + * + * Function emits a timeline message containing atom attributes. + */ +#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_CONFIG(atom, jd, affinity, config) \ + __TRACE_IF_ENABLED(tl_attrib_atom_config, atom, jd, affinity, config) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY - atom priority + * @atom: name of the atom object + * @prio: atom priority + * + * Function emits a timeline message containing atom priority. + */ +#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY(atom, prio) \ + __TRACE_IF_ENABLED_LATENCY(tl_attrib_atom_priority, atom, prio) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE - atom state + * @atom: name of the atom object + * @state: atom state + * + * Function emits a timeline message containing atom state. + */ +#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(atom, state) \ + __TRACE_IF_ENABLED_LATENCY(tl_attrib_atom_state, atom, state) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY_CHANGE - atom caused priority change + * @atom: name of the atom object + * + * Function emits a timeline message signalling priority change + */ +#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY_CHANGE(atom) \ + __TRACE_IF_ENABLED_LATENCY(tl_attrib_atom_priority_change, atom) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT - jit happened on atom + * @atom: atom identifier + * @edit_addr: address edited by jit + * @new_addr: address placed into the edited location + */ +#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT(atom, edit_addr, new_addr) \ + __TRACE_IF_ENABLED_JD(tl_attrib_atom_jit, atom, edit_addr, new_addr) + +/** + * KBASE_TLSTREAM_TL_ATTRIB_AS_CONFIG - address space attributes + * @as: assigned address space + * @transtab: configuration of the TRANSTAB register + * @memattr: configuration of the MEMATTR register + * @transcfg: configuration of the TRANSCFG register (or zero if not present) + * + * Function emits a timeline message containing address space attributes. + */ +#define KBASE_TLSTREAM_TL_ATTRIB_AS_CONFIG(as, transtab, memattr, transcfg) \ + __TRACE_IF_ENABLED(tl_attrib_as_config, as, transtab, memattr, transcfg) + +/** + * KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_ex + * @atom: atom identifier + */ +#define KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(atom) \ + __TRACE_IF_ENABLED(tl_event_atom_softstop_ex, atom) + +/** + * KBASE_TLSTREAM_TL_EVENT_LPU_softstop + * @lpu: name of the LPU object + */ +#define KBASE_TLSTREAM_TL_EVENT_LPU_SOFTSTOP(lpu) \ + __TRACE_IF_ENABLED(tl_event_lpu_softstop, lpu) + +/** + * KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_issue + * @atom: atom identifier + */ +#define KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_ISSUE(atom) \ + __TRACE_IF_ENABLED(tl_event_atom_softstop_issue, atom) + +/** + * KBASE_TLSTREAM_JD_GPU_SOFT_RESET - The GPU is being soft reset + * @gpu: name of the GPU object + * + * This imperative tracepoint is specific to job dumping. + * Function emits a timeline message indicating GPU soft reset. + */ +#define KBASE_TLSTREAM_JD_GPU_SOFT_RESET(gpu) \ + __TRACE_IF_ENABLED(jd_gpu_soft_reset, gpu) + + +/** + * KBASE_TLSTREAM_AUX_PM_STATE - timeline message: power management state + * @core_type: core type (shader, tiler, l2 cache, l3 cache) + * @state: 64bits bitmask reporting power state of the cores (1-ON, 0-OFF) + */ +#define KBASE_TLSTREAM_AUX_PM_STATE(core_type, state) \ + __TRACE_IF_ENABLED(aux_pm_state, core_type, state) + +/** + * KBASE_TLSTREAM_AUX_PAGEFAULT - timeline message: MMU page fault event + * resulting in new pages being mapped + * @ctx_nr: kernel context number + * @page_count_change: number of pages to be added + */ +#define KBASE_TLSTREAM_AUX_PAGEFAULT(ctx_nr, page_count_change) \ + __TRACE_IF_ENABLED(aux_pagefault, ctx_nr, page_count_change) + +/** + * KBASE_TLSTREAM_AUX_PAGESALLOC - timeline message: total number of allocated + * pages is changed + * @ctx_nr: kernel context number + * @page_count: number of pages used by the context + */ +#define KBASE_TLSTREAM_AUX_PAGESALLOC(ctx_nr, page_count) \ + __TRACE_IF_ENABLED(aux_pagesalloc, ctx_nr, page_count) + +/** + * KBASE_TLSTREAM_AUX_DEVFREQ_TARGET - timeline message: new target DVFS + * frequency + * @target_freq: new target frequency + */ +#define KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(target_freq) \ + __TRACE_IF_ENABLED(aux_devfreq_target, target_freq) + +/** + * KBASE_TLSTREAM_AUX_PROTECTED_ENTER_START - The GPU has started transitioning + * to protected mode + * @gpu: name of the GPU object + * + * Function emits a timeline message indicating the GPU is starting to + * transition to protected mode. + */ +#define KBASE_TLSTREAM_AUX_PROTECTED_ENTER_START(gpu) \ + __TRACE_IF_ENABLED_LATENCY(aux_protected_enter_start, gpu) + +/** + * KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END - The GPU has finished transitioning + * to protected mode + * @gpu: name of the GPU object + * + * Function emits a timeline message indicating the GPU has finished + * transitioning to protected mode. + */ +#define KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END(gpu) \ + __TRACE_IF_ENABLED_LATENCY(aux_protected_enter_end, gpu) + +/** + * KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_START - The GPU has started transitioning + * to non-protected mode + * @gpu: name of the GPU object + * + * Function emits a timeline message indicating the GPU is starting to + * transition to non-protected mode. + */ +#define KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_START(gpu) \ + __TRACE_IF_ENABLED_LATENCY(aux_protected_leave_start, gpu) + +/** + * KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END - The GPU has finished transitioning + * to non-protected mode + * @gpu: name of the GPU object + * + * Function emits a timeline message indicating the GPU has finished + * transitioning to non-protected mode. + */ +#define KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END(gpu) \ + __TRACE_IF_ENABLED_LATENCY(aux_protected_leave_end, gpu) + +#endif /* _KBASE_TLSTREAM_H */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_trace_defs.h new file mode 100644 index 000000000000..e2e0544208ce --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_defs.h @@ -0,0 +1,264 @@ +/* + * + * (C) COPYRIGHT 2011-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * The purpose of this header file is just to contain a list of trace code idenitifers + * + * Each identifier is wrapped in a macro, so that its string form and enum form can be created + * + * Each macro is separated with a comma, to allow insertion into an array initializer or enum definition block. + * + * This allows automatic creation of an enum and a corresponding array of strings + * + * Before #including, the includer MUST #define KBASE_TRACE_CODE_MAKE_CODE. + * After #including, the includer MUST #under KBASE_TRACE_CODE_MAKE_CODE. + * + * e.g.: + * #define KBASE_TRACE_CODE( X ) KBASE_TRACE_CODE_ ## X + * typedef enum + * { + * #define KBASE_TRACE_CODE_MAKE_CODE( X ) KBASE_TRACE_CODE( X ) + * #include "mali_kbase_trace_defs.h" + * #undef KBASE_TRACE_CODE_MAKE_CODE + * } kbase_trace_code; + * + * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THE ABOVE + * + * + * The use of the macro here is: + * - KBASE_TRACE_CODE_MAKE_CODE( X ) + * + * Which produces: + * - For an enum, KBASE_TRACE_CODE_X + * - For a string, "X" + * + * + * For example: + * - KBASE_TRACE_CODE_MAKE_CODE( JM_JOB_COMPLETE ) expands to: + * - KBASE_TRACE_CODE_JM_JOB_COMPLETE for the enum + * - "JM_JOB_COMPLETE" for the string + * - To use it to trace an event, do: + * - KBASE_TRACE_ADD( kbdev, JM_JOB_COMPLETE, subcode, kctx, uatom, val ); + */ + +#if 0 /* Dummy section to avoid breaking formatting */ +int dummy_array[] = { +#endif + +/* + * Core events + */ + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_DESTROY), + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_HWINSTR_TERM), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ), + /* info_val == bits cleared */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_CLEAR), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_DONE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_SOFT_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_HARD_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_CLEAR), + /* GPU addr==dump address */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_SAMPLE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_CLEAN_INV_CACHES), +/* + * Job Slot management events + */ + /* info_val==irq rawstat at start */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ), + /* info_val==jobs processed */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ_END), +/* In the following: + * + * - ctx is set if a corresponding job found (NULL otherwise, e.g. some soft-stop cases) + * - uatom==kernel-side mapped uatom address (for correlation with user-side) + */ + /* info_val==exit code; gpu_addr==chain gpuaddr */ + KBASE_TRACE_CODE_MAKE_CODE(JM_JOB_DONE), + /* gpu_addr==JS_HEAD_NEXT written, info_val==lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT), + /* gpu_addr is as follows: + * - If JS_STATUS active after soft-stop, val==gpu addr written to + * JS_HEAD on submit + * - otherwise gpu_addr==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_0), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_1), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_0), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_1), + /* gpu_addr==JS_TAIL read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_UPDATE_HEAD), +/* gpu_addr is as follows: + * - If JS_STATUS active before soft-stop, val==JS_HEAD + * - otherwise gpu_addr==0 + */ + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_CHECK_HEAD), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS_DONE), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_NON_SCHEDULED), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_SCHEDULED), + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_DONE), + /* info_val == nr jobs submitted */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_SOFT_OR_HARD_STOP), + /* gpu_addr==JS_HEAD_NEXT last written */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_EVICT), + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT_AFTER_RESET), + KBASE_TRACE_CODE_MAKE_CODE(JM_BEGIN_RESET_WORKER), + KBASE_TRACE_CODE_MAKE_CODE(JM_END_RESET_WORKER), +/* + * Job dispatch events + */ + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER_END), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==0, info_val==0, uatom==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JD_ZAP_CONTEXT), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL_WORKER), +/* + * Scheduler Core events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX_NOLOCK), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_ADD_JOB), + /* gpu_addr==last value written/would be written to JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_REMOVE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_RELEASE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_TRY_SCHEDULE_HEAD_CTX), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_RETRY_NEEDED), + /* kctx is the one being evicted, info_val == kctx to put in */ + KBASE_TRACE_CODE_MAKE_CODE(JS_FAST_START_EVICTS_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_SUBMIT_TO_BLOCKED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_CURRENT), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_CORES_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_INUSE_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_AFFINITY_WOULD_VIOLATE), + /* info_val == the ctx attribute now on ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_CTX), + /* info_val == the ctx attribute now on runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_RUNPOOL), + /* info_val == the ctx attribute now off ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_CTX), + /* info_val == the ctx attribute now off runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_RUNPOOL), +/* + * Scheduler Policy events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_INIT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TERM_CTX), + /* info_val == whether it was evicted */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TRY_EVICT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_FOREACH_CTX_JOBS), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_HEAD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_ADD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_REMOVE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB_IRQ), + /* gpu_addr==JS_HEAD to write if the job were run */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_START), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_END), +/* + * Power Management Events + */ + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERING_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERED_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE_TILER), + /* PM_DESIRED_REACHED: gpu_addr == pm.gpu_in_desired_state */ + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED), + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_WAKE_WAITERS), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_ACTIVE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_IDLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_ON), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_OFF), + /* info_val == policy number, or -1 for "Already changing" */ + KBASE_TRACE_CODE_MAKE_CODE(PM_SET_POLICY), + KBASE_TRACE_CODE_MAKE_CODE(PM_CA_SET_POLICY), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_INIT), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_TERM), +/* Unused code just to make it easier to not have a comma at the end. + * All other codes MUST come before this */ + KBASE_TRACE_CODE_MAKE_CODE(DUMMY) + +#if 0 /* Dummy section to avoid breaking formatting */ +}; +#endif + +/* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c new file mode 100644 index 000000000000..5830e87f0818 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c @@ -0,0 +1,236 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +#define CREATE_TRACE_POINTS + +#ifdef CONFIG_MALI_TRACE_TIMELINE +#include "mali_timeline.h" + +#include +#include + +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_atoms_in_flight); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_atom); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_gpu_slot_active); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_gpu_slot_action); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_gpu_power_active); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_l2_power_active); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_pm_event); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_slot_atom); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_pm_checktrans); +EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_context_active); + +struct kbase_trace_timeline_desc { + char *enum_str; + char *desc; + char *format; + char *format_desc; +}; + +static struct kbase_trace_timeline_desc kbase_trace_timeline_desc_table[] = { + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) { #enum_val, desc, format, format_desc } + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +}; + +#define KBASE_NR_TRACE_CODES ARRAY_SIZE(kbase_trace_timeline_desc_table) + +static void *kbasep_trace_timeline_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +static void kbasep_trace_timeline_seq_stop(struct seq_file *s, void *data) +{ +} + +static void *kbasep_trace_timeline_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + (*pos)++; + + if (*pos == KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +static int kbasep_trace_timeline_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace_timeline_desc *trace_desc = data; + + seq_printf(s, "%s#%s#%s#%s\n", trace_desc->enum_str, trace_desc->desc, trace_desc->format, trace_desc->format_desc); + return 0; +} + + +static const struct seq_operations kbasep_trace_timeline_seq_ops = { + .start = kbasep_trace_timeline_seq_start, + .next = kbasep_trace_timeline_seq_next, + .stop = kbasep_trace_timeline_seq_stop, + .show = kbasep_trace_timeline_seq_show, +}; + +static int kbasep_trace_timeline_debugfs_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &kbasep_trace_timeline_seq_ops); +} + +static const struct file_operations kbasep_trace_timeline_debugfs_fops = { + .open = kbasep_trace_timeline_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +#ifdef CONFIG_DEBUG_FS + +void kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev) +{ + debugfs_create_file("mali_timeline_defs", + S_IRUGO, kbdev->mali_debugfs_directory, NULL, + &kbasep_trace_timeline_debugfs_fops); +} + +#endif /* CONFIG_DEBUG_FS */ + +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->timeline.slot_atoms_submitted[js] > 0) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 1); + } else { + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 1); + KBASE_TIMELINE_JOB_START(kctx, js, atom_number); + } + ++kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 0); + } else { + /* Job finished in JS_HEAD */ + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 0); + KBASE_TIMELINE_JOB_STOP(kctx, js, atom_number); + + /* see if we need to trace the job in JS_NEXT moving to JS_HEAD */ + if (kbase_backend_nr_atoms_submitted(kbdev, js)) { + struct kbase_jd_atom *next_katom; + struct kbase_context *next_kctx; + + /* Peek the next atom - note that the atom in JS_HEAD will already + * have been dequeued */ + next_katom = kbase_backend_inspect_head(kbdev, js); + WARN_ON(!next_katom); + next_kctx = next_katom->kctx; + KBASE_TIMELINE_JOB_START_NEXT(next_kctx, js, 0); + KBASE_TIMELINE_JOB_START_HEAD(next_kctx, js, 1); + KBASE_TIMELINE_JOB_START(next_kctx, js, kbase_jd_atom_id(next_kctx, next_katom)); + } + } + + --kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ + int uid = 0; + int old_uid; + + /* If a producer already exists for the event, try to use their UID (multiple-producers) */ + uid = atomic_read(&kbdev->timeline.pm_event_uid[event_sent]); + old_uid = uid; + + /* Get a new non-zero UID if we don't have one yet */ + while (!uid) + uid = atomic_inc_return(&kbdev->timeline.pm_event_uid_counter); + + /* Try to use this UID */ + if (old_uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event_sent], old_uid, uid)) + /* If it changed, raced with another producer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_sent, uid); +} + +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != 0) { + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); + } +} + +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); +} + +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + /* Simply log the start of the transition */ + kbdev->timeline.l2_transitioning = true; + KBASE_TIMELINE_POWERING_L2(kbdev); +} + +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + /* Simply log the end of the transition */ + if (kbdev->timeline.l2_transitioning) { + kbdev->timeline.l2_transitioning = false; + KBASE_TIMELINE_POWERED_L2(kbdev); + } +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h new file mode 100644 index 000000000000..619072f3215c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h @@ -0,0 +1,363 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if !defined(_KBASE_TRACE_TIMELINE_H) +#define _KBASE_TRACE_TIMELINE_H + +#ifdef CONFIG_MALI_TRACE_TIMELINE + +enum kbase_trace_timeline_code { + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) enum_val + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +}; + +#ifdef CONFIG_DEBUG_FS + +/** Initialize Timeline DebugFS entries */ +void kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev); + +#else /* CONFIG_DEBUG_FS */ + +#define kbasep_trace_timeline_debugfs_init CSTD_NOP + +#endif /* CONFIG_DEBUG_FS */ + +/* mali_timeline.h defines kernel tracepoints used by the KBASE_TIMELINE + * functions. + * Output is timestamped by either sched_clock() (default), local_clock(), or + * cpu_clock(), depending on /sys/kernel/debug/tracing/trace_clock */ +#include "mali_timeline.h" + +/* Trace number of atoms in flight for kctx (atoms either not completed, or in + process of being returned to user */ +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_atoms_in_flight(ts.tv_sec, ts.tv_nsec, \ + (int)kctx->timeline.owner_tgid, \ + count); \ + } while (0) + +/* Trace atom_id being Ready to Run */ +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_atom(ts.tv_sec, ts.tv_nsec, \ + CTX_FLOW_ATOM_READY, \ + (int)kctx->timeline.owner_tgid, \ + atom_id); \ + } while (0) + +/* Trace number of atoms submitted to job slot js + * + * NOTE: This uses a different tracepoint to the head/next/soft-stop actions, + * so that those actions can be filtered out separately from this + * + * This is because this is more useful, as we can use it to calculate general + * utilization easily and accurately */ +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_slot_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_ACTIVE, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + + +/* Trace atoms present in JS_NEXT */ +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_NEXT, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace atoms present in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_HEAD, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace that a soft stop/evict from next is being attempted on a slot */ +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_STOPPING, \ + (kctx) ? (int)kctx->timeline.owner_tgid : 0, \ + js, count); \ + } while (0) + + + +/* Trace state of overall GPU power */ +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_ACTIVE, active); \ + } while (0) + +/* Trace state of tiler power */ +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_TILER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace number of shaders currently powered */ +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_SHADER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 power */ +#define KBASE_TIMELINE_POWER_L2(kbdev, bitmap) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_L2_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 cache*/ +#define KBASE_TIMELINE_POWERING_L2(kbdev) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_POWERING, \ + 1); \ + } while (0) + +#define KBASE_TIMELINE_POWERED_L2(kbdev) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_ACTIVE, \ + 1); \ + } while (0) + +/* Trace kbase_pm_send_event message send */ +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_SEND_EVENT, \ + event_type, pm_event_id); \ + } while (0) + +/* Trace kbase_pm_worker message receive */ +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_HANDLE_EVENT, \ + event_type, pm_event_id); \ + } while (0) + + +/* Trace atom_id starting in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_START_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _consumerof_atom_number); \ + } while (0) + +/* Trace atom_id stopping on JS_HEAD */ +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_STOP_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _producerof_atom_number_completed); \ + } while (0) + +/** Trace beginning/end of a call to kbase_pm_check_transitions_nolock from a + * certin caller */ +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_pm_checktrans(ts.tv_sec, ts.tv_nsec, \ + trace_code, 1); \ + } while (0) + +/* Trace number of contexts active */ +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) \ + do { \ + struct timespec ts; \ + getrawmonotonic(&ts); \ + trace_mali_timeline_context_active(ts.tv_sec, ts.tv_nsec, \ + count); \ + } while (0) + +/* NOTE: kbase_timeline_pm_cores_func() is in mali_kbase_pm_policy.c */ + +/** + * Trace that an atom is starting on a job slot + * + * The caller must be holding hwaccess_lock + */ +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js); + +/** + * Trace that an atom has done on a job slot + * + * 'Done' in this sense can occur either because: + * - the atom in JS_HEAD finished + * - the atom in JS_NEXT was evicted + * + * Whether the atom finished or was evicted is passed in @a done_code + * + * It is assumed that the atom has already been removed from the submit slot, + * with either: + * - kbasep_jm_dequeue_submit_slot() + * - kbasep_jm_dequeue_tail_submit_slot() + * + * The caller must be holding hwaccess_lock + */ +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code); + + +/** Trace a pm event starting */ +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, + enum kbase_timeline_pm_event event_sent); + +/** Trace a pm event finishing */ +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Check whether a pm event was present, and if so trace finishing it */ +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Trace L2 power-up start */ +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev); + +/** Trace L2 power-up done */ +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev); + +#else + +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) CSTD_NOP() + +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) CSTD_NOP() + +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_L2(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWERING_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_POWERED_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) CSTD_NOP() + +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) CSTD_NOP() + +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) CSTD_NOP() + +static inline void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); +} + +static inline void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); +} + +static inline void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ +} + +static inline void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static inline void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static inline void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ +} + +static inline void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ +} +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#endif /* _KBASE_TRACE_TIMELINE_H */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline_defs.h new file mode 100644 index 000000000000..156a95a67f4a --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline_defs.h @@ -0,0 +1,140 @@ +/* + * + * (C) COPYRIGHT 2012-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * Conventions on Event Names: + * + * - The prefix determines something about how the timeline should be + * displayed, and is split up into various parts, separated by underscores: + * - 'SW' and 'HW' as the first part will be used to determine whether a + * timeline is to do with Software or Hardware - effectively, separate + * 'channels' for Software and Hardware + * - 'START', 'STOP', 'ENTER', 'LEAVE' can be used in the second part, and + * signify related pairs of events - these are optional. + * - 'FLOW' indicates a generic event, which can use dependencies + * - This gives events such as: + * - 'SW_ENTER_FOO' + * - 'SW_LEAVE_FOO' + * - 'SW_FLOW_BAR_1' + * - 'SW_FLOW_BAR_2' + * - 'HW_START_BAZ' + * - 'HW_STOP_BAZ' + * - And an unadorned HW event: + * - 'HW_BAZ_FROZBOZ' + */ + +/* + * Conventions on parameter names: + * - anything with 'instance' in the name will have a separate timeline based + * on that instances. + * - underscored-prefixed parameters will by hidden by default on timelines + * + * Hence: + * - Different job slots have their own 'instance', based on the instance value + * - Per-context info (e.g. atoms on a context) have their own 'instance' + * (i.e. each context should be on a different timeline) + * + * Note that globally-shared resources can be tagged with a tgid, but we don't + * want an instance per context: + * - There's no point having separate Job Slot timelines for each context, that + * would be confusing - there's only really 3 job slots! + * - There's no point having separate Shader-powered timelines for each + * context, that would be confusing - all shader cores (whether it be 4, 8, + * etc) are shared in the system. + */ + + /* + * CTX events + */ + /* Separate timelines for each context 'instance'*/ + KBASE_TIMELINE_TRACE_CODE(CTX_SET_NR_ATOMS_IN_FLIGHT, "CTX: Atoms in flight", "%d,%d", "_instance_tgid,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(CTX_FLOW_ATOM_READY, "CTX: Atoms Ready to Run", "%d,%d,%d", "_instance_tgid,_consumerof_atom_number,_producerof_atom_number_ready"), + + /* + * SW Events + */ + /* Separate timelines for each slot 'instance' */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_ACTIVE, "SW: GPU slot active", "%d,%d,%d", "_tgid,_instance_slot,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_NEXT, "SW: GPU atom in NEXT", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_next"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_HEAD, "SW: GPU atom in HEAD", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_head"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_STOPPING, "SW: Try Soft-Stop on GPU slot", "%d,%d,%d", "_tgid,_instance_slot,_value_is_slot_stopping"), + /* Shader and overall power is shared - can't have separate instances of + * it, just tagging with the context */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_ACTIVE, "SW: GPU power active", "%d,%d", "_tgid,_value_is_power_active"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_TILER_ACTIVE, "SW: GPU tiler powered", "%d,%d", "_tgid,_value_number_of_tilers"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_SHADER_ACTIVE, "SW: GPU shaders powered", "%d,%d", "_tgid,_value_number_of_shaders"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powered", "%d,%d", "_tgid,_value_number_of_l2"), + + /* SW Power event messaging. _event_type is one from the kbase_pm_event enum */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_SEND_EVENT, "SW: PM Send Event", "%d,%d,%d", "_tgid,_event_type,_writerof_pm_event_id"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_HANDLE_EVENT, "SW: PM Handle Event", "%d,%d,%d", "_tgid,_event_type,_finalconsumerof_pm_event_id"), + /* SW L2 power events */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_POWERING, "SW: GPU L2 powering", "%d,%d", "_tgid,_writerof_l2_transitioning"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powering done", "%d,%d", "_tgid,_finalconsumerof_l2_transitioning"), + + KBASE_TIMELINE_TRACE_CODE(SW_SET_CONTEXT_ACTIVE, "SW: Context Active", "%d,%d", "_tgid,_value_active"), + + /* + * BEGIN: Significant SW Functions that call kbase_pm_check_transitions_nolock() + */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_writerof_pm_checktrans_gpu_interrupt"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_gpu_interrupt"), + + /* + * Significant Indirect callers of kbase_pm_check_transitions_nolock() + */ + /* kbase_pm_request_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader_tiler"), + /* kbase_pm_release_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_shader_poweroff_callback"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_shader_poweroff_callback"), + /* + * END: SW Functions that call kbase_pm_check_transitions_nolock() + */ + + /* + * HW Events + */ + KBASE_TIMELINE_TRACE_CODE(HW_MMU_FAULT, +"HW: MMU Fault", "%d,%d,%d", "_tgid,fault_type,fault_stage,asid"), + KBASE_TIMELINE_TRACE_CODE(HW_START_GPU_JOB_CHAIN_SW_APPROX, +"HW: Job Chain start (SW approximated)", "%d,%d,%d", +"_tgid,job_slot,_consumerof_atom_number_ready"), + KBASE_TIMELINE_TRACE_CODE(HW_STOP_GPU_JOB_CHAIN_SW_APPROX, +"HW: Job Chain stop (SW approximated)", "%d,%d,%d", +"_tgid,job_slot,_producerof_atom_number_completed") diff --git a/drivers/gpu/arm/bifrost/mali_kbase_uku.h b/drivers/gpu/arm/bifrost/mali_kbase_uku.h new file mode 100644 index 000000000000..2a69da7394ba --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_uku.h @@ -0,0 +1,532 @@ +/* + * + * (C) COPYRIGHT 2008-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UKU_H_ +#define _KBASE_UKU_H_ + +#include "mali_uk.h" +#include "mali_base_kernel.h" + +/* This file needs to support being included from kernel and userside (which use different defines) */ +#if defined(CONFIG_MALI_ERROR_INJECT) || MALI_ERROR_INJECT_ON +#define SUPPORT_MALI_ERROR_INJECT +#endif /* defined(CONFIG_MALI_ERROR_INJECT) || MALI_ERROR_INJECT_ON */ +#if defined(CONFIG_MALI_NO_MALI) +#define SUPPORT_MALI_NO_MALI +#elif defined(MALI_NO_MALI) +#if MALI_NO_MALI +#define SUPPORT_MALI_NO_MALI +#endif +#endif + +#if defined(SUPPORT_MALI_NO_MALI) || defined(SUPPORT_MALI_ERROR_INJECT) +#include "backend/gpu/mali_kbase_model_dummy.h" +#endif + +#include "mali_kbase_gpuprops_types.h" + +/* + * 10.1: + * - Do mmap in kernel for SAME_VA memory allocations rather then + * calling back into the kernel as a 2nd stage of the allocation request. + * + * 10.2: + * - Add KBASE_FUNC_MEM_JIT_INIT which allows clients to request a custom VA + * region for use with JIT (ignored on 32-bit platforms) + * + * 10.3: + * - base_jd_core_req typedef-ed to u32 (instead of to u16) + * - two flags added: BASE_JD_REQ_SKIP_CACHE_STAT / _END + * + * 10.4: + * - Removed KBASE_FUNC_EXT_BUFFER_LOCK used only in internal tests + * + * 10.5: + * - Reverted to performing mmap in user space so that tools like valgrind work. + * + * 10.6: + * - Add flags input variable to KBASE_FUNC_TLSTREAM_ACQUIRE + */ +#define BASE_UK_VERSION_MAJOR 10 +#define BASE_UK_VERSION_MINOR 6 + +#define LINUX_UK_BASE_MAGIC 0x80 + +struct kbase_uk_mem_alloc { + union uk_header header; + /* IN */ + u64 va_pages; + u64 commit_pages; + u64 extent; + /* IN/OUT */ + u64 flags; + /* OUT */ + u64 gpu_va; + u16 va_alignment; + u8 padding[6]; +}; + +struct kbase_uk_mem_free { + union uk_header header; + /* IN */ + u64 gpu_addr; + /* OUT */ +}; + +struct kbase_uk_mem_alias { + union uk_header header; + /* IN/OUT */ + u64 flags; + /* IN */ + u64 stride; + u64 nents; + u64 ai; + /* OUT */ + u64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_import { + union uk_header header; + /* IN */ + u64 phandle; + u32 type; + u32 padding; + /* IN/OUT */ + u64 flags; + /* OUT */ + u64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_flags_change { + union uk_header header; + /* IN */ + u64 gpu_va; + u64 flags; + u64 mask; +}; + +struct kbase_uk_job_submit { + union uk_header header; + /* IN */ + u64 addr; + u32 nr_atoms; + u32 stride; /* bytes between atoms, i.e. sizeof(base_jd_atom_v2) */ + /* OUT */ +}; + +struct kbase_uk_post_term { + union uk_header header; +}; + +struct kbase_uk_sync_now { + union uk_header header; + + /* IN */ + struct base_syncset sset; + + /* OUT */ +}; + +struct kbase_uk_hwcnt_setup { + union uk_header header; + + /* IN */ + u64 dump_buffer; + u32 jm_bm; + u32 shader_bm; + u32 tiler_bm; + u32 unused_1; /* keep for backwards compatibility */ + u32 mmu_l2_bm; + u32 padding; + /* OUT */ +}; + +/** + * struct kbase_uk_hwcnt_reader_setup - User/Kernel space data exchange structure + * @header: UK structure header + * @buffer_count: requested number of dumping buffers + * @jm_bm: counters selection bitmask (JM) + * @shader_bm: counters selection bitmask (Shader) + * @tiler_bm: counters selection bitmask (Tiler) + * @mmu_l2_bm: counters selection bitmask (MMU_L2) + * @fd: dumping notification file descriptor + * + * This structure sets up HWC dumper/reader for this context. + * Multiple instances can be created for single context. + */ +struct kbase_uk_hwcnt_reader_setup { + union uk_header header; + + /* IN */ + u32 buffer_count; + u32 jm_bm; + u32 shader_bm; + u32 tiler_bm; + u32 mmu_l2_bm; + + /* OUT */ + s32 fd; +}; + +struct kbase_uk_hwcnt_dump { + union uk_header header; +}; + +struct kbase_uk_hwcnt_clear { + union uk_header header; +}; + +struct kbase_uk_fence_validate { + union uk_header header; + /* IN */ + s32 fd; + u32 padding; + /* OUT */ +}; + +struct kbase_uk_stream_create { + union uk_header header; + /* IN */ + char name[32]; + /* OUT */ + s32 fd; + u32 padding; +}; + +struct kbase_uk_gpuprops { + union uk_header header; + + /* IN */ + struct mali_base_gpu_props props; + /* OUT */ +}; + +struct kbase_uk_mem_query { + union uk_header header; + /* IN */ + u64 gpu_addr; +#define KBASE_MEM_QUERY_COMMIT_SIZE 1 +#define KBASE_MEM_QUERY_VA_SIZE 2 +#define KBASE_MEM_QUERY_FLAGS 3 + u64 query; + /* OUT */ + u64 value; +}; + +struct kbase_uk_mem_commit { + union uk_header header; + /* IN */ + u64 gpu_addr; + u64 pages; + /* OUT */ + u32 result_subcode; + u32 padding; +}; + +struct kbase_uk_find_cpu_offset { + union uk_header header; + /* IN */ + u64 gpu_addr; + u64 cpu_addr; + u64 size; + /* OUT */ + u64 offset; +}; + +#define KBASE_GET_VERSION_BUFFER_SIZE 64 +struct kbase_uk_get_ddk_version { + union uk_header header; + /* OUT */ + char version_buffer[KBASE_GET_VERSION_BUFFER_SIZE]; + u32 version_string_size; + u32 padding; +}; + +struct kbase_uk_disjoint_query { + union uk_header header; + /* OUT */ + u32 counter; + u32 padding; +}; + +struct kbase_uk_set_flags { + union uk_header header; + /* IN */ + u32 create_flags; + u32 padding; +}; + +#if MALI_UNIT_TEST +#define TEST_ADDR_COUNT 4 +#define KBASE_TEST_BUFFER_SIZE 128 +struct kbase_exported_test_data { + u64 test_addr[TEST_ADDR_COUNT]; /**< memory address */ + u32 test_addr_pages[TEST_ADDR_COUNT]; /**< memory size in pages */ + u64 kctx; /**< base context created by process */ + u64 mm; /**< pointer to process address space */ + u8 buffer1[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ + u8 buffer2[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ +}; + +struct kbase_uk_set_test_data { + union uk_header header; + /* IN */ + struct kbase_exported_test_data test_data; +}; + +#endif /* MALI_UNIT_TEST */ + +#ifdef SUPPORT_MALI_ERROR_INJECT +struct kbase_uk_error_params { + union uk_header header; + /* IN */ + struct kbase_error_params params; +}; +#endif /* SUPPORT_MALI_ERROR_INJECT */ + +#ifdef SUPPORT_MALI_NO_MALI +struct kbase_uk_model_control_params { + union uk_header header; + /* IN */ + struct kbase_model_control_params params; +}; +#endif /* SUPPORT_MALI_NO_MALI */ + +struct kbase_uk_profiling_controls { + union uk_header header; + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +}; + +struct kbase_uk_debugfs_mem_profile_add { + union uk_header header; + u32 len; + u32 padding; + u64 buf; +}; + +struct kbase_uk_context_id { + union uk_header header; + /* OUT */ + int id; +}; + +/** + * struct kbase_uk_tlstream_acquire - User/Kernel space data exchange structure + * @header: UK structure header + * @flags: timeline stream flags + * @fd: timeline stream file descriptor + * + * This structure is used when performing a call to acquire kernel side timeline + * stream file descriptor. + */ +struct kbase_uk_tlstream_acquire { + union uk_header header; + /* IN */ + u32 flags; + /* OUT */ + s32 fd; +}; + +/** + * struct kbase_uk_tlstream_acquire_v10_4 - User/Kernel space data exchange + * structure + * @header: UK structure header + * @fd: timeline stream file descriptor + * + * This structure is used when performing a call to acquire kernel side timeline + * stream file descriptor. + */ +struct kbase_uk_tlstream_acquire_v10_4 { + union uk_header header; + /* IN */ + /* OUT */ + s32 fd; +}; + +/** + * struct kbase_uk_tlstream_flush - User/Kernel space data exchange structure + * @header: UK structure header + * + * This structure is used when performing a call to flush kernel side + * timeline streams. + */ +struct kbase_uk_tlstream_flush { + union uk_header header; + /* IN */ + /* OUT */ +}; + +#if MALI_UNIT_TEST +/** + * struct kbase_uk_tlstream_test - User/Kernel space data exchange structure + * @header: UK structure header + * @tpw_count: number of trace point writers in each context + * @msg_delay: time delay between tracepoints from one writer in milliseconds + * @msg_count: number of trace points written by one writer + * @aux_msg: if non-zero aux messages will be included + * + * This structure is used when performing a call to start timeline stream test + * embedded in kernel. + */ +struct kbase_uk_tlstream_test { + union uk_header header; + /* IN */ + u32 tpw_count; + u32 msg_delay; + u32 msg_count; + u32 aux_msg; + /* OUT */ +}; + +/** + * struct kbase_uk_tlstream_stats - User/Kernel space data exchange structure + * @header: UK structure header + * @bytes_collected: number of bytes read by user + * @bytes_generated: number of bytes generated by tracepoints + * + * This structure is used when performing a call to obtain timeline stream + * statistics. + */ +struct kbase_uk_tlstream_stats { + union uk_header header; /**< UK structure header. */ + /* IN */ + /* OUT */ + u32 bytes_collected; + u32 bytes_generated; +}; +#endif /* MALI_UNIT_TEST */ + +/** + * struct struct kbase_uk_prfcnt_value for the KBASE_FUNC_SET_PRFCNT_VALUES ioctl + * @header: UK structure header + * @data: Counter samples for the dummy model + * @size:............Size of the counter sample data + */ +struct kbase_uk_prfcnt_values { + union uk_header header; + /* IN */ + u32 *data; + u32 size; +}; + +/** + * struct kbase_uk_soft_event_update - User/Kernel space data exchange structure + * @header: UK structure header + * @evt: the GPU address containing the event + * @new_status: the new event status, must be either BASE_JD_SOFT_EVENT_SET or + * BASE_JD_SOFT_EVENT_RESET + * @flags: reserved for future uses, must be set to 0 + * + * This structure is used to update the status of a software event. If the + * event's status is set to BASE_JD_SOFT_EVENT_SET, any job currently waiting + * on this event will complete. + */ +struct kbase_uk_soft_event_update { + union uk_header header; + /* IN */ + u64 evt; + u32 new_status; + u32 flags; +}; + +/** + * struct kbase_uk_mem_jit_init - User/Kernel space data exchange structure + * @header: UK structure header + * @va_pages: Number of virtual pages required for JIT + * + * This structure is used when requesting initialization of JIT. + */ +struct kbase_uk_mem_jit_init { + union uk_header header; + /* IN */ + u64 va_pages; +}; + +enum kbase_uk_function_id { + KBASE_FUNC_MEM_ALLOC = (UK_FUNC_ID + 0), + KBASE_FUNC_MEM_IMPORT = (UK_FUNC_ID + 1), + KBASE_FUNC_MEM_COMMIT = (UK_FUNC_ID + 2), + KBASE_FUNC_MEM_QUERY = (UK_FUNC_ID + 3), + KBASE_FUNC_MEM_FREE = (UK_FUNC_ID + 4), + KBASE_FUNC_MEM_FLAGS_CHANGE = (UK_FUNC_ID + 5), + KBASE_FUNC_MEM_ALIAS = (UK_FUNC_ID + 6), + + /* UK_FUNC_ID + 7 not in use since BASE_LEGACY_UK6_SUPPORT dropped */ + + KBASE_FUNC_SYNC = (UK_FUNC_ID + 8), + + KBASE_FUNC_POST_TERM = (UK_FUNC_ID + 9), + + KBASE_FUNC_HWCNT_SETUP = (UK_FUNC_ID + 10), + KBASE_FUNC_HWCNT_DUMP = (UK_FUNC_ID + 11), + KBASE_FUNC_HWCNT_CLEAR = (UK_FUNC_ID + 12), + + KBASE_FUNC_GPU_PROPS_REG_DUMP = (UK_FUNC_ID + 14), + + KBASE_FUNC_FIND_CPU_OFFSET = (UK_FUNC_ID + 15), + + KBASE_FUNC_GET_VERSION = (UK_FUNC_ID + 16), + KBASE_FUNC_SET_FLAGS = (UK_FUNC_ID + 18), + + KBASE_FUNC_SET_TEST_DATA = (UK_FUNC_ID + 19), + KBASE_FUNC_INJECT_ERROR = (UK_FUNC_ID + 20), + KBASE_FUNC_MODEL_CONTROL = (UK_FUNC_ID + 21), + + /* UK_FUNC_ID + 22 not in use since BASE_LEGACY_UK8_SUPPORT dropped */ + + KBASE_FUNC_FENCE_VALIDATE = (UK_FUNC_ID + 23), + KBASE_FUNC_STREAM_CREATE = (UK_FUNC_ID + 24), + KBASE_FUNC_GET_PROFILING_CONTROLS = (UK_FUNC_ID + 25), + KBASE_FUNC_SET_PROFILING_CONTROLS = (UK_FUNC_ID + 26), + /* to be used only for testing + * purposes, otherwise these controls + * are set through gator API */ + + KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD = (UK_FUNC_ID + 27), + KBASE_FUNC_JOB_SUBMIT = (UK_FUNC_ID + 28), + KBASE_FUNC_DISJOINT_QUERY = (UK_FUNC_ID + 29), + + KBASE_FUNC_GET_CONTEXT_ID = (UK_FUNC_ID + 31), + + KBASE_FUNC_TLSTREAM_ACQUIRE_V10_4 = (UK_FUNC_ID + 32), +#if MALI_UNIT_TEST + KBASE_FUNC_TLSTREAM_TEST = (UK_FUNC_ID + 33), + KBASE_FUNC_TLSTREAM_STATS = (UK_FUNC_ID + 34), +#endif /* MALI_UNIT_TEST */ + KBASE_FUNC_TLSTREAM_FLUSH = (UK_FUNC_ID + 35), + + KBASE_FUNC_HWCNT_READER_SETUP = (UK_FUNC_ID + 36), + +#ifdef SUPPORT_MALI_NO_MALI + KBASE_FUNC_SET_PRFCNT_VALUES = (UK_FUNC_ID + 37), +#endif + + KBASE_FUNC_SOFT_EVENT_UPDATE = (UK_FUNC_ID + 38), + + KBASE_FUNC_MEM_JIT_INIT = (UK_FUNC_ID + 39), + + KBASE_FUNC_TLSTREAM_ACQUIRE = (UK_FUNC_ID + 40), + + KBASE_FUNC_MAX +}; + +#endif /* _KBASE_UKU_H_ */ + diff --git a/drivers/gpu/arm/bifrost/mali_kbase_utility.c b/drivers/gpu/arm/bifrost/mali_kbase_utility.c new file mode 100644 index 000000000000..be474ff87401 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_utility.c @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT 2012-2013, 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry) +{ + struct list_head *pos = base->next; + + while (pos != base) { + if (pos == entry) + return true; + + pos = pos->next; + } + return false; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_utility.h b/drivers/gpu/arm/bifrost/mali_kbase_utility.h new file mode 100644 index 000000000000..fd7252dab0de --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_utility.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT 2012-2013, 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UTILITY_H +#define _KBASE_UTILITY_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +/** Test whether the given list entry is a member of the given list. + * + * @param base The head of the list to be tested + * @param entry The list entry to be tested + * + * @return true if entry is a member of base + * false otherwise + */ +bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry); + +#endif /* _KBASE_UTILITY_H */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c new file mode 100644 index 000000000000..ed12945d81f1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c @@ -0,0 +1,2072 @@ +/* + * + * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ + +/* Hwcnt reader API version */ +#define HWCNT_READER_API 1 + +/* The number of nanoseconds in a second. */ +#define NSECS_IN_SEC 1000000000ull /* ns */ + +/* The time resolution of dumping service. */ +#define DUMPING_RESOLUTION 500000ull /* ns */ + +/* The maximal supported number of dumping buffers. */ +#define MAX_BUFFER_COUNT 32 + +/* Size and number of hw counters blocks. */ +#define NR_CNT_BLOCKS_PER_GROUP 8 +#define NR_CNT_PER_BLOCK 64 +#define NR_BYTES_PER_CNT 4 +#define NR_BYTES_PER_HDR 16 +#define PRFCNT_EN_MASK_OFFSET 0x8 + +/*****************************************************************************/ + +enum { + SHADER_HWCNT_BM, + TILER_HWCNT_BM, + MMU_L2_HWCNT_BM, + JM_HWCNT_BM +}; + +enum vinstr_state { + VINSTR_IDLE, + VINSTR_DUMPING, + VINSTR_SUSPENDING, + VINSTR_SUSPENDED, + VINSTR_RESUMING +}; + +/** + * struct kbase_vinstr_context - vinstr context per device + * @lock: protects the entire vinstr context + * @kbdev: pointer to kbase device + * @kctx: pointer to kbase context + * @vmap: vinstr vmap for mapping hwcnt dump buffer + * @gpu_va: GPU hwcnt dump buffer address + * @cpu_va: the CPU side mapping of the hwcnt dump buffer + * @dump_size: size of the dump buffer in bytes + * @bitmap: current set of counters monitored, not always in sync + * with hardware + * @reprogram: when true, reprogram hwcnt block with the new set of + * counters + * @state: vinstr state + * @state_lock: protects information about vinstr state + * @suspend_waitq: notification queue to trigger state re-validation + * @suspend_cnt: reference counter of vinstr's suspend state + * @suspend_work: worker to execute on entering suspended state + * @resume_work: worker to execute on leaving suspended state + * @nclients: number of attached clients, pending or otherwise + * @waiting_clients: head of list of clients being periodically sampled + * @idle_clients: head of list of clients being idle + * @suspended_clients: head of list of clients being suspended + * @thread: periodic sampling thread + * @waitq: notification queue of sampling thread + * @request_pending: request for action for sampling thread + * @clients_present: when true, we have at least one client + * Note: this variable is in sync. with nclients and is + * present to preserve simplicity. Protected by state_lock. + */ +struct kbase_vinstr_context { + struct mutex lock; + struct kbase_device *kbdev; + struct kbase_context *kctx; + + struct kbase_vmap_struct vmap; + u64 gpu_va; + void *cpu_va; + size_t dump_size; + u32 bitmap[4]; + bool reprogram; + + enum vinstr_state state; + struct spinlock state_lock; + wait_queue_head_t suspend_waitq; + unsigned int suspend_cnt; + struct work_struct suspend_work; + struct work_struct resume_work; + + u32 nclients; + struct list_head waiting_clients; + struct list_head idle_clients; + struct list_head suspended_clients; + + struct task_struct *thread; + wait_queue_head_t waitq; + atomic_t request_pending; + + bool clients_present; +}; + +/** + * struct kbase_vinstr_client - a vinstr client attached to a vinstr context + * @vinstr_ctx: vinstr context client is attached to + * @list: node used to attach this client to list in vinstr context + * @buffer_count: number of buffers this client is using + * @event_mask: events this client reacts to + * @dump_size: size of one dump buffer in bytes + * @bitmap: bitmap request for JM, TILER, SHADER and MMU counters + * @legacy_buffer: userspace hwcnt dump buffer (legacy interface) + * @kernel_buffer: kernel hwcnt dump buffer (kernel client interface) + * @accum_buffer: temporary accumulation buffer for preserving counters + * @dump_time: next time this clients shall request hwcnt dump + * @dump_interval: interval between periodic hwcnt dumps + * @dump_buffers: kernel hwcnt dump buffers allocated by this client + * @dump_buffers_meta: metadata of dump buffers + * @meta_idx: index of metadata being accessed by userspace + * @read_idx: index of buffer read by userspace + * @write_idx: index of buffer being written by dumping service + * @waitq: client's notification queue + * @pending: when true, client has attached but hwcnt not yet updated + */ +struct kbase_vinstr_client { + struct kbase_vinstr_context *vinstr_ctx; + struct list_head list; + unsigned int buffer_count; + u32 event_mask; + size_t dump_size; + u32 bitmap[4]; + void __user *legacy_buffer; + void *kernel_buffer; + void *accum_buffer; + u64 dump_time; + u32 dump_interval; + char *dump_buffers; + struct kbase_hwcnt_reader_metadata *dump_buffers_meta; + atomic_t meta_idx; + atomic_t read_idx; + atomic_t write_idx; + wait_queue_head_t waitq; + bool pending; +}; + +/** + * struct kbasep_vinstr_wake_up_timer - vinstr service thread wake up timer + * @hrtimer: high resolution timer + * @vinstr_ctx: vinstr context + */ +struct kbasep_vinstr_wake_up_timer { + struct hrtimer hrtimer; + struct kbase_vinstr_context *vinstr_ctx; +}; + +/*****************************************************************************/ + +static int kbasep_vinstr_service_task(void *data); + +static unsigned int kbasep_vinstr_hwcnt_reader_poll( + struct file *filp, + poll_table *wait); +static long kbasep_vinstr_hwcnt_reader_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg); +static int kbasep_vinstr_hwcnt_reader_mmap( + struct file *filp, + struct vm_area_struct *vma); +static int kbasep_vinstr_hwcnt_reader_release( + struct inode *inode, + struct file *filp); + +/* The timeline stream file operations structure. */ +static const struct file_operations vinstr_client_fops = { + .poll = kbasep_vinstr_hwcnt_reader_poll, + .unlocked_ioctl = kbasep_vinstr_hwcnt_reader_ioctl, + .compat_ioctl = kbasep_vinstr_hwcnt_reader_ioctl, + .mmap = kbasep_vinstr_hwcnt_reader_mmap, + .release = kbasep_vinstr_hwcnt_reader_release, +}; + +/*****************************************************************************/ + +static int enable_hwcnt(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_context *kctx = vinstr_ctx->kctx; + struct kbase_device *kbdev = kctx->kbdev; + struct kbase_uk_hwcnt_setup setup; + int err; + + setup.dump_buffer = vinstr_ctx->gpu_va; + setup.jm_bm = vinstr_ctx->bitmap[JM_HWCNT_BM]; + setup.tiler_bm = vinstr_ctx->bitmap[TILER_HWCNT_BM]; + setup.shader_bm = vinstr_ctx->bitmap[SHADER_HWCNT_BM]; + setup.mmu_l2_bm = vinstr_ctx->bitmap[MMU_L2_HWCNT_BM]; + + /* Mark the context as active so the GPU is kept turned on */ + /* A suspend won't happen here, because we're in a syscall from a + * userspace thread. */ + kbase_pm_context_active(kbdev); + + /* Schedule the context in */ + kbasep_js_schedule_privileged_ctx(kbdev, kctx); + err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &setup); + if (err) { + /* Release the context. This had its own Power Manager Active + * reference */ + kbasep_js_release_privileged_ctx(kbdev, kctx); + + /* Also release our Power Manager Active reference */ + kbase_pm_context_idle(kbdev); + } + + return err; +} + +static void disable_hwcnt(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_context *kctx = vinstr_ctx->kctx; + struct kbase_device *kbdev = kctx->kbdev; + int err; + + err = kbase_instr_hwcnt_disable_internal(kctx); + if (err) { + dev_warn(kbdev->dev, "Failed to disable HW counters (ctx:%p)", + kctx); + return; + } + + /* Release the context. This had its own Power Manager Active reference. */ + kbasep_js_release_privileged_ctx(kbdev, kctx); + + /* Also release our Power Manager Active reference. */ + kbase_pm_context_idle(kbdev); + + dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p", kctx); +} + +static int reprogram_hwcnt(struct kbase_vinstr_context *vinstr_ctx) +{ + disable_hwcnt(vinstr_ctx); + return enable_hwcnt(vinstr_ctx); +} + +static void hwcnt_bitmap_set(u32 dst[4], u32 src[4]) +{ + dst[JM_HWCNT_BM] = src[JM_HWCNT_BM]; + dst[TILER_HWCNT_BM] = src[TILER_HWCNT_BM]; + dst[SHADER_HWCNT_BM] = src[SHADER_HWCNT_BM]; + dst[MMU_L2_HWCNT_BM] = src[MMU_L2_HWCNT_BM]; +} + +static void hwcnt_bitmap_union(u32 dst[4], u32 src[4]) +{ + dst[JM_HWCNT_BM] |= src[JM_HWCNT_BM]; + dst[TILER_HWCNT_BM] |= src[TILER_HWCNT_BM]; + dst[SHADER_HWCNT_BM] |= src[SHADER_HWCNT_BM]; + dst[MMU_L2_HWCNT_BM] |= src[MMU_L2_HWCNT_BM]; +} + +size_t kbase_vinstr_dump_size(struct kbase_device *kbdev) +{ + size_t dump_size; + +#ifndef CONFIG_MALI_NO_MALI + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_V4)) { + u32 nr_cg; + + nr_cg = kbdev->gpu_props.num_core_groups; + dump_size = nr_cg * NR_CNT_BLOCKS_PER_GROUP * + NR_CNT_PER_BLOCK * + NR_BYTES_PER_CNT; + } else +#endif /* CONFIG_MALI_NO_MALI */ + { + /* assume v5 for now */ + base_gpu_props *props = &kbdev->gpu_props.props; + u32 nr_l2 = props->l2_props.num_l2_slices; + u64 core_mask = props->coherency_info.group[0].core_mask; + u32 nr_blocks = fls64(core_mask); + + /* JM and tiler counter blocks are always present */ + dump_size = (2 + nr_l2 + nr_blocks) * + NR_CNT_PER_BLOCK * + NR_BYTES_PER_CNT; + } + return dump_size; +} +KBASE_EXPORT_TEST_API(kbase_vinstr_dump_size); + +static size_t kbasep_vinstr_dump_size_ctx( + struct kbase_vinstr_context *vinstr_ctx) +{ + return kbase_vinstr_dump_size(vinstr_ctx->kctx->kbdev); +} + +static int kbasep_vinstr_map_kernel_dump_buffer( + struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_va_region *reg; + struct kbase_context *kctx = vinstr_ctx->kctx; + u64 flags, nr_pages; + + flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_WR; + vinstr_ctx->dump_size = kbasep_vinstr_dump_size_ctx(vinstr_ctx); + nr_pages = PFN_UP(vinstr_ctx->dump_size); + + reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, + &vinstr_ctx->gpu_va); + if (!reg) + return -ENOMEM; + + vinstr_ctx->cpu_va = kbase_vmap( + kctx, + vinstr_ctx->gpu_va, + vinstr_ctx->dump_size, + &vinstr_ctx->vmap); + if (!vinstr_ctx->cpu_va) { + kbase_mem_free(kctx, vinstr_ctx->gpu_va); + return -ENOMEM; + } + + return 0; +} + +static void kbasep_vinstr_unmap_kernel_dump_buffer( + struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_context *kctx = vinstr_ctx->kctx; + + kbase_vunmap(kctx, &vinstr_ctx->vmap); + kbase_mem_free(kctx, vinstr_ctx->gpu_va); +} + +/** + * kbasep_vinstr_create_kctx - create kernel context for vinstr + * @vinstr_ctx: vinstr context + * Return: zero on success + */ +static int kbasep_vinstr_create_kctx(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_device *kbdev = vinstr_ctx->kbdev; + struct kbasep_kctx_list_element *element = NULL; + unsigned long flags; + bool enable_backend = false; + int err; + + vinstr_ctx->kctx = kbase_create_context(vinstr_ctx->kbdev, true); + if (!vinstr_ctx->kctx) + return -ENOMEM; + + /* Map the master kernel dump buffer. The HW dumps the counters + * into this memory region. */ + err = kbasep_vinstr_map_kernel_dump_buffer(vinstr_ctx); + if (err) + goto failed_map; + + /* Add kernel context to list of contexts associated with device. */ + element = kzalloc(sizeof(*element), GFP_KERNEL); + if (element) { + element->kctx = vinstr_ctx->kctx; + mutex_lock(&kbdev->kctx_list_lock); + list_add(&element->link, &kbdev->kctx_list); + + /* Inform timeline client about new context. + * Do this while holding the lock to avoid tracepoint + * being created in both body and summary stream. */ + KBASE_TLSTREAM_TL_NEW_CTX( + vinstr_ctx->kctx, + vinstr_ctx->kctx->id, + (u32)(vinstr_ctx->kctx->tgid)); + + mutex_unlock(&kbdev->kctx_list_lock); + } else { + /* Don't treat this as a fail - just warn about it. */ + dev_warn(kbdev->dev, + "couldn't add kctx to kctx_list\n"); + } + + /* Don't enable hardware counters if vinstr is suspended. + * Note that vinstr resume code is run under vinstr context lock, + * lower layer will be enabled as needed on resume. */ + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + if (VINSTR_IDLE == vinstr_ctx->state) + enable_backend = true; + vinstr_ctx->clients_present = true; + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + if (enable_backend) + err = enable_hwcnt(vinstr_ctx); + if (err) + goto failed_enable; + + vinstr_ctx->thread = kthread_run( + kbasep_vinstr_service_task, + vinstr_ctx, + "mali_vinstr_service"); + if (IS_ERR(vinstr_ctx->thread)) { + err = PTR_ERR(vinstr_ctx->thread); + goto failed_kthread; + } + + return 0; + +failed_kthread: + disable_hwcnt(vinstr_ctx); +failed_enable: + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + vinstr_ctx->clients_present = false; + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + kbasep_vinstr_unmap_kernel_dump_buffer(vinstr_ctx); + if (element) { + mutex_lock(&kbdev->kctx_list_lock); + list_del(&element->link); + kfree(element); + mutex_unlock(&kbdev->kctx_list_lock); + KBASE_TLSTREAM_TL_DEL_CTX(vinstr_ctx->kctx); + } +failed_map: + kbase_destroy_context(vinstr_ctx->kctx); + vinstr_ctx->kctx = NULL; + return err; +} + +/** + * kbasep_vinstr_destroy_kctx - destroy vinstr's kernel context + * @vinstr_ctx: vinstr context + */ +static void kbasep_vinstr_destroy_kctx(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_device *kbdev = vinstr_ctx->kbdev; + struct kbasep_kctx_list_element *element; + struct kbasep_kctx_list_element *tmp; + bool found = false; + unsigned long flags; + + /* Release hw counters dumping resources. */ + vinstr_ctx->thread = NULL; + disable_hwcnt(vinstr_ctx); + kbasep_vinstr_unmap_kernel_dump_buffer(vinstr_ctx); + + /* Simplify state transitions by specifying that we have no clients. */ + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + vinstr_ctx->clients_present = false; + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + /* Remove kernel context from the device's contexts list. */ + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry_safe(element, tmp, &kbdev->kctx_list, link) { + if (element->kctx == vinstr_ctx->kctx) { + list_del(&element->link); + kfree(element); + found = true; + } + } + mutex_unlock(&kbdev->kctx_list_lock); + + if (!found) + dev_warn(kbdev->dev, "kctx not in kctx_list\n"); + + /* Destroy context. */ + kbase_destroy_context(vinstr_ctx->kctx); + + /* Inform timeline client about context destruction. */ + KBASE_TLSTREAM_TL_DEL_CTX(vinstr_ctx->kctx); + + vinstr_ctx->kctx = NULL; +} + +/** + * kbasep_vinstr_attach_client - Attach a client to the vinstr core + * @vinstr_ctx: vinstr context + * @buffer_count: requested number of dump buffers + * @bitmap: bitmaps describing which counters should be enabled + * @argp: pointer where notification descriptor shall be stored + * @kernel_buffer: pointer to kernel side buffer + * + * Return: vinstr opaque client handle or NULL on failure + */ +static struct kbase_vinstr_client *kbasep_vinstr_attach_client( + struct kbase_vinstr_context *vinstr_ctx, u32 buffer_count, + u32 bitmap[4], void *argp, void *kernel_buffer) +{ + struct task_struct *thread = NULL; + struct kbase_vinstr_client *cli; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + if (buffer_count > MAX_BUFFER_COUNT + || (buffer_count & (buffer_count - 1))) + return NULL; + + cli = kzalloc(sizeof(*cli), GFP_KERNEL); + if (!cli) + return NULL; + + cli->vinstr_ctx = vinstr_ctx; + cli->buffer_count = buffer_count; + cli->event_mask = + (1 << BASE_HWCNT_READER_EVENT_MANUAL) | + (1 << BASE_HWCNT_READER_EVENT_PERIODIC); + cli->pending = true; + + hwcnt_bitmap_set(cli->bitmap, bitmap); + + mutex_lock(&vinstr_ctx->lock); + + hwcnt_bitmap_union(vinstr_ctx->bitmap, cli->bitmap); + vinstr_ctx->reprogram = true; + + /* If this is the first client, create the vinstr kbase + * context. This context is permanently resident until the + * last client exits. */ + if (!vinstr_ctx->nclients) { + hwcnt_bitmap_set(vinstr_ctx->bitmap, cli->bitmap); + if (kbasep_vinstr_create_kctx(vinstr_ctx) < 0) + goto error; + + vinstr_ctx->reprogram = false; + cli->pending = false; + } + + /* The GPU resets the counter block every time there is a request + * to dump it. We need a per client kernel buffer for accumulating + * the counters. */ + cli->dump_size = kbasep_vinstr_dump_size_ctx(vinstr_ctx); + cli->accum_buffer = kzalloc(cli->dump_size, GFP_KERNEL); + if (!cli->accum_buffer) + goto error; + + /* Prepare buffers. */ + if (cli->buffer_count) { + int *fd = (int *)argp; + size_t tmp; + + /* Allocate area for buffers metadata storage. */ + tmp = sizeof(struct kbase_hwcnt_reader_metadata) * + cli->buffer_count; + cli->dump_buffers_meta = kmalloc(tmp, GFP_KERNEL); + if (!cli->dump_buffers_meta) + goto error; + + /* Allocate required number of dumping buffers. */ + cli->dump_buffers = (char *)__get_free_pages( + GFP_KERNEL | __GFP_ZERO, + get_order(cli->dump_size * cli->buffer_count)); + if (!cli->dump_buffers) + goto error; + + /* Create descriptor for user-kernel data exchange. */ + *fd = anon_inode_getfd( + "[mali_vinstr_desc]", + &vinstr_client_fops, + cli, + O_RDONLY | O_CLOEXEC); + if (0 > *fd) + goto error; + } else if (kernel_buffer) { + cli->kernel_buffer = kernel_buffer; + } else { + cli->legacy_buffer = (void __user *)argp; + } + + atomic_set(&cli->read_idx, 0); + atomic_set(&cli->meta_idx, 0); + atomic_set(&cli->write_idx, 0); + init_waitqueue_head(&cli->waitq); + + vinstr_ctx->nclients++; + list_add(&cli->list, &vinstr_ctx->idle_clients); + + mutex_unlock(&vinstr_ctx->lock); + + return cli; + +error: + kfree(cli->dump_buffers_meta); + if (cli->dump_buffers) + free_pages( + (unsigned long)cli->dump_buffers, + get_order(cli->dump_size * cli->buffer_count)); + kfree(cli->accum_buffer); + if (!vinstr_ctx->nclients && vinstr_ctx->kctx) { + thread = vinstr_ctx->thread; + kbasep_vinstr_destroy_kctx(vinstr_ctx); + } + kfree(cli); + + mutex_unlock(&vinstr_ctx->lock); + + /* Thread must be stopped after lock is released. */ + if (thread) + kthread_stop(thread); + + return NULL; +} + +void kbase_vinstr_detach_client(struct kbase_vinstr_client *cli) +{ + struct kbase_vinstr_context *vinstr_ctx; + struct kbase_vinstr_client *iter, *tmp; + struct task_struct *thread = NULL; + u32 zerobitmap[4] = { 0 }; + int cli_found = 0; + + KBASE_DEBUG_ASSERT(cli); + vinstr_ctx = cli->vinstr_ctx; + KBASE_DEBUG_ASSERT(vinstr_ctx); + + mutex_lock(&vinstr_ctx->lock); + + list_for_each_entry_safe(iter, tmp, &vinstr_ctx->idle_clients, list) { + if (iter == cli) { + vinstr_ctx->reprogram = true; + cli_found = 1; + list_del(&iter->list); + break; + } + } + if (!cli_found) { + list_for_each_entry_safe( + iter, tmp, &vinstr_ctx->waiting_clients, list) { + if (iter == cli) { + vinstr_ctx->reprogram = true; + cli_found = 1; + list_del(&iter->list); + break; + } + } + } + KBASE_DEBUG_ASSERT(cli_found); + + kfree(cli->dump_buffers_meta); + free_pages( + (unsigned long)cli->dump_buffers, + get_order(cli->dump_size * cli->buffer_count)); + kfree(cli->accum_buffer); + kfree(cli); + + vinstr_ctx->nclients--; + if (!vinstr_ctx->nclients) { + thread = vinstr_ctx->thread; + kbasep_vinstr_destroy_kctx(vinstr_ctx); + } + + /* Rebuild context bitmap now that the client has detached */ + hwcnt_bitmap_set(vinstr_ctx->bitmap, zerobitmap); + list_for_each_entry(iter, &vinstr_ctx->idle_clients, list) + hwcnt_bitmap_union(vinstr_ctx->bitmap, iter->bitmap); + list_for_each_entry(iter, &vinstr_ctx->waiting_clients, list) + hwcnt_bitmap_union(vinstr_ctx->bitmap, iter->bitmap); + + mutex_unlock(&vinstr_ctx->lock); + + /* Thread must be stopped after lock is released. */ + if (thread) + kthread_stop(thread); +} +KBASE_EXPORT_TEST_API(kbase_vinstr_detach_client); + +/* Accumulate counters in the dump buffer */ +static void accum_dump_buffer(void *dst, void *src, size_t dump_size) +{ + size_t block_size = NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT; + u32 *d = dst; + u32 *s = src; + size_t i, j; + + for (i = 0; i < dump_size; i += block_size) { + /* skip over the header block */ + d += NR_BYTES_PER_HDR / sizeof(u32); + s += NR_BYTES_PER_HDR / sizeof(u32); + for (j = 0; j < (block_size - NR_BYTES_PER_HDR) / sizeof(u32); j++) { + /* saturate result if addition would result in wraparound */ + if (U32_MAX - *d < *s) + *d = U32_MAX; + else + *d += *s; + d++; + s++; + } + } +} + +/* This is the Midgard v4 patch function. It copies the headers for each + * of the defined blocks from the master kernel buffer and then patches up + * the performance counter enable mask for each of the blocks to exclude + * counters that were not requested by the client. */ +static void patch_dump_buffer_hdr_v4( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_vinstr_client *cli) +{ + u32 *mask; + u8 *dst = cli->accum_buffer; + u8 *src = vinstr_ctx->cpu_va; + u32 nr_cg = vinstr_ctx->kctx->kbdev->gpu_props.num_core_groups; + size_t i, group_size, group; + enum { + SC0_BASE = 0 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + SC1_BASE = 1 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + SC2_BASE = 2 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + SC3_BASE = 3 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + TILER_BASE = 4 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + MMU_L2_BASE = 5 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT, + JM_BASE = 7 * NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT + }; + + group_size = NR_CNT_BLOCKS_PER_GROUP * + NR_CNT_PER_BLOCK * + NR_BYTES_PER_CNT; + for (i = 0; i < nr_cg; i++) { + group = i * group_size; + /* copy shader core headers */ + memcpy(&dst[group + SC0_BASE], &src[group + SC0_BASE], + NR_BYTES_PER_HDR); + memcpy(&dst[group + SC1_BASE], &src[group + SC1_BASE], + NR_BYTES_PER_HDR); + memcpy(&dst[group + SC2_BASE], &src[group + SC2_BASE], + NR_BYTES_PER_HDR); + memcpy(&dst[group + SC3_BASE], &src[group + SC3_BASE], + NR_BYTES_PER_HDR); + + /* copy tiler header */ + memcpy(&dst[group + TILER_BASE], &src[group + TILER_BASE], + NR_BYTES_PER_HDR); + + /* copy mmu header */ + memcpy(&dst[group + MMU_L2_BASE], &src[group + MMU_L2_BASE], + NR_BYTES_PER_HDR); + + /* copy job manager header */ + memcpy(&dst[group + JM_BASE], &src[group + JM_BASE], + NR_BYTES_PER_HDR); + + /* patch the shader core enable mask */ + mask = (u32 *)&dst[group + SC0_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[SHADER_HWCNT_BM]; + mask = (u32 *)&dst[group + SC1_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[SHADER_HWCNT_BM]; + mask = (u32 *)&dst[group + SC2_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[SHADER_HWCNT_BM]; + mask = (u32 *)&dst[group + SC3_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[SHADER_HWCNT_BM]; + + /* patch the tiler core enable mask */ + mask = (u32 *)&dst[group + TILER_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[TILER_HWCNT_BM]; + + /* patch the mmu core enable mask */ + mask = (u32 *)&dst[group + MMU_L2_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[MMU_L2_HWCNT_BM]; + + /* patch the job manager enable mask */ + mask = (u32 *)&dst[group + JM_BASE + PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[JM_HWCNT_BM]; + } +} + +/* This is the Midgard v5 patch function. It copies the headers for each + * of the defined blocks from the master kernel buffer and then patches up + * the performance counter enable mask for each of the blocks to exclude + * counters that were not requested by the client. */ +static void patch_dump_buffer_hdr_v5( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_vinstr_client *cli) +{ + struct kbase_device *kbdev = vinstr_ctx->kctx->kbdev; + u32 i, nr_l2; + u64 core_mask; + u32 *mask; + u8 *dst = cli->accum_buffer; + u8 *src = vinstr_ctx->cpu_va; + size_t block_size = NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT; + + /* copy and patch job manager header */ + memcpy(dst, src, NR_BYTES_PER_HDR); + mask = (u32 *)&dst[PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[JM_HWCNT_BM]; + dst += block_size; + src += block_size; + + /* copy and patch tiler header */ + memcpy(dst, src, NR_BYTES_PER_HDR); + mask = (u32 *)&dst[PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[TILER_HWCNT_BM]; + dst += block_size; + src += block_size; + + /* copy and patch MMU/L2C headers */ + nr_l2 = kbdev->gpu_props.props.l2_props.num_l2_slices; + for (i = 0; i < nr_l2; i++) { + memcpy(dst, src, NR_BYTES_PER_HDR); + mask = (u32 *)&dst[PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[MMU_L2_HWCNT_BM]; + dst += block_size; + src += block_size; + } + + /* copy and patch shader core headers */ + core_mask = kbdev->gpu_props.props.coherency_info.group[0].core_mask; + while (0ull != core_mask) { + memcpy(dst, src, NR_BYTES_PER_HDR); + if (0ull != (core_mask & 1ull)) { + /* if block is not reserved update header */ + mask = (u32 *)&dst[PRFCNT_EN_MASK_OFFSET]; + *mask &= cli->bitmap[SHADER_HWCNT_BM]; + } + dst += block_size; + src += block_size; + + core_mask >>= 1; + } +} + +/** + * accum_clients - accumulate dumped hw counters for all known clients + * @vinstr_ctx: vinstr context + */ +static void accum_clients(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_vinstr_client *iter; + int v4 = 0; + +#ifndef CONFIG_MALI_NO_MALI + v4 = kbase_hw_has_feature(vinstr_ctx->kbdev, BASE_HW_FEATURE_V4); +#endif + + list_for_each_entry(iter, &vinstr_ctx->idle_clients, list) { + /* Don't bother accumulating clients whose hwcnt requests + * have not yet been honoured. */ + if (iter->pending) + continue; + if (v4) + patch_dump_buffer_hdr_v4(vinstr_ctx, iter); + else + patch_dump_buffer_hdr_v5(vinstr_ctx, iter); + accum_dump_buffer( + iter->accum_buffer, + vinstr_ctx->cpu_va, + iter->dump_size); + } + list_for_each_entry(iter, &vinstr_ctx->waiting_clients, list) { + /* Don't bother accumulating clients whose hwcnt requests + * have not yet been honoured. */ + if (iter->pending) + continue; + if (v4) + patch_dump_buffer_hdr_v4(vinstr_ctx, iter); + else + patch_dump_buffer_hdr_v5(vinstr_ctx, iter); + accum_dump_buffer( + iter->accum_buffer, + vinstr_ctx->cpu_va, + iter->dump_size); + } +} + +/*****************************************************************************/ + +/** + * kbasep_vinstr_get_timestamp - return timestamp + * + * Function returns timestamp value based on raw monotonic timer. Value will + * wrap around zero in case of overflow. + * + * Return: timestamp value + */ +static u64 kbasep_vinstr_get_timestamp(void) +{ + struct timespec ts; + + getrawmonotonic(&ts); + return (u64)ts.tv_sec * NSECS_IN_SEC + ts.tv_nsec; +} + +/** + * kbasep_vinstr_add_dump_request - register client's dumping request + * @cli: requesting client + * @waiting_clients: list of pending dumping requests + */ +static void kbasep_vinstr_add_dump_request( + struct kbase_vinstr_client *cli, + struct list_head *waiting_clients) +{ + struct kbase_vinstr_client *tmp; + + if (list_empty(waiting_clients)) { + list_add(&cli->list, waiting_clients); + return; + } + list_for_each_entry(tmp, waiting_clients, list) { + if (tmp->dump_time > cli->dump_time) { + list_add_tail(&cli->list, &tmp->list); + return; + } + } + list_add_tail(&cli->list, waiting_clients); +} + +/** + * kbasep_vinstr_collect_and_accumulate - collect hw counters via low level + * dump and accumulate them for known + * clients + * @vinstr_ctx: vinstr context + * @timestamp: pointer where collection timestamp will be recorded + * + * Return: zero on success + */ +static int kbasep_vinstr_collect_and_accumulate( + struct kbase_vinstr_context *vinstr_ctx, u64 *timestamp) +{ + unsigned long flags; + int rcode; + +#ifdef CONFIG_MALI_NO_MALI + /* The dummy model needs the CPU mapping. */ + gpu_model_set_dummy_prfcnt_base_cpu(vinstr_ctx->cpu_va); +#endif + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + if (VINSTR_IDLE != vinstr_ctx->state) { + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + return -EAGAIN; + } else { + vinstr_ctx->state = VINSTR_DUMPING; + } + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + /* Request HW counters dump. + * Disable preemption to make dump timestamp more accurate. */ + preempt_disable(); + *timestamp = kbasep_vinstr_get_timestamp(); + rcode = kbase_instr_hwcnt_request_dump(vinstr_ctx->kctx); + preempt_enable(); + + if (!rcode) + rcode = kbase_instr_hwcnt_wait_for_dump(vinstr_ctx->kctx); + WARN_ON(rcode); + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + switch (vinstr_ctx->state) + { + case VINSTR_SUSPENDING: + schedule_work(&vinstr_ctx->suspend_work); + break; + case VINSTR_DUMPING: + vinstr_ctx->state = VINSTR_IDLE; + wake_up_all(&vinstr_ctx->suspend_waitq); + break; + default: + break; + } + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + /* Accumulate values of collected counters. */ + if (!rcode) + accum_clients(vinstr_ctx); + + return rcode; +} + +/** + * kbasep_vinstr_fill_dump_buffer - copy accumulated counters to empty kernel + * buffer + * @cli: requesting client + * @timestamp: timestamp when counters were collected + * @event_id: id of event that caused triggered counters collection + * + * Return: zero on success + */ +static int kbasep_vinstr_fill_dump_buffer( + struct kbase_vinstr_client *cli, u64 timestamp, + enum base_hwcnt_reader_event event_id) +{ + unsigned int write_idx = atomic_read(&cli->write_idx); + unsigned int read_idx = atomic_read(&cli->read_idx); + + struct kbase_hwcnt_reader_metadata *meta; + void *buffer; + + /* Check if there is a place to copy HWC block into. */ + if (write_idx - read_idx == cli->buffer_count) + return -1; + write_idx %= cli->buffer_count; + + /* Fill in dump buffer and its metadata. */ + buffer = &cli->dump_buffers[write_idx * cli->dump_size]; + meta = &cli->dump_buffers_meta[write_idx]; + meta->timestamp = timestamp; + meta->event_id = event_id; + meta->buffer_idx = write_idx; + memcpy(buffer, cli->accum_buffer, cli->dump_size); + return 0; +} + +/** + * kbasep_vinstr_fill_dump_buffer_legacy - copy accumulated counters to buffer + * allocated in userspace + * @cli: requesting client + * + * Return: zero on success + * + * This is part of legacy ioctl interface. + */ +static int kbasep_vinstr_fill_dump_buffer_legacy( + struct kbase_vinstr_client *cli) +{ + void __user *buffer = cli->legacy_buffer; + int rcode; + + /* Copy data to user buffer. */ + rcode = copy_to_user(buffer, cli->accum_buffer, cli->dump_size); + if (rcode) { + pr_warn("error while copying buffer to user\n"); + return -EFAULT; + } + return 0; +} + +/** + * kbasep_vinstr_fill_dump_buffer_kernel - copy accumulated counters to buffer + * allocated in kernel space + * @cli: requesting client + * + * Return: zero on success + * + * This is part of the kernel client interface. + */ +static int kbasep_vinstr_fill_dump_buffer_kernel( + struct kbase_vinstr_client *cli) +{ + memcpy(cli->kernel_buffer, cli->accum_buffer, cli->dump_size); + + return 0; +} + +/** + * kbasep_vinstr_reprogram - reprogram hwcnt set collected by inst + * @vinstr_ctx: vinstr context + */ +static void kbasep_vinstr_reprogram( + struct kbase_vinstr_context *vinstr_ctx) +{ + unsigned long flags; + bool suspended = false; + + /* Don't enable hardware counters if vinstr is suspended. */ + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + if (VINSTR_IDLE != vinstr_ctx->state) + suspended = true; + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + if (suspended) + return; + + /* Change to suspended state is done while holding vinstr context + * lock. Below code will then no re-enable the instrumentation. */ + + if (vinstr_ctx->reprogram) { + struct kbase_vinstr_client *iter; + + if (!reprogram_hwcnt(vinstr_ctx)) { + vinstr_ctx->reprogram = false; + list_for_each_entry( + iter, + &vinstr_ctx->idle_clients, + list) + iter->pending = false; + list_for_each_entry( + iter, + &vinstr_ctx->waiting_clients, + list) + iter->pending = false; + } + } +} + +/** + * kbasep_vinstr_update_client - copy accumulated counters to user readable + * buffer and notify the user + * @cli: requesting client + * @timestamp: timestamp when counters were collected + * @event_id: id of event that caused triggered counters collection + * + * Return: zero on success + */ +static int kbasep_vinstr_update_client( + struct kbase_vinstr_client *cli, u64 timestamp, + enum base_hwcnt_reader_event event_id) +{ + int rcode = 0; + + /* Copy collected counters to user readable buffer. */ + if (cli->buffer_count) + rcode = kbasep_vinstr_fill_dump_buffer( + cli, timestamp, event_id); + else if (cli->kernel_buffer) + rcode = kbasep_vinstr_fill_dump_buffer_kernel(cli); + else + rcode = kbasep_vinstr_fill_dump_buffer_legacy(cli); + + if (rcode) + goto exit; + + + /* Notify client. Make sure all changes to memory are visible. */ + wmb(); + atomic_inc(&cli->write_idx); + wake_up_interruptible(&cli->waitq); + + /* Prepare for next request. */ + memset(cli->accum_buffer, 0, cli->dump_size); + +exit: + return rcode; +} + +/** + * kbasep_vinstr_wake_up_callback - vinstr wake up timer wake up function + * + * @hrtimer: high resolution timer + * + * Return: High resolution timer restart enum. + */ +static enum hrtimer_restart kbasep_vinstr_wake_up_callback( + struct hrtimer *hrtimer) +{ + struct kbasep_vinstr_wake_up_timer *timer = + container_of( + hrtimer, + struct kbasep_vinstr_wake_up_timer, + hrtimer); + + KBASE_DEBUG_ASSERT(timer); + + atomic_set(&timer->vinstr_ctx->request_pending, 1); + wake_up_all(&timer->vinstr_ctx->waitq); + + return HRTIMER_NORESTART; +} + +/** + * kbasep_vinstr_service_task - HWC dumping service thread + * + * @data: Pointer to vinstr context structure. + * + * Return: 0 on success; -ENOMEM if timer allocation fails + */ +static int kbasep_vinstr_service_task(void *data) +{ + struct kbase_vinstr_context *vinstr_ctx = data; + struct kbasep_vinstr_wake_up_timer *timer; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + timer = kmalloc(sizeof(*timer), GFP_KERNEL); + + if (!timer) { + dev_warn(vinstr_ctx->kbdev->dev, "Timer allocation failed!\n"); + return -ENOMEM; + } + + hrtimer_init(&timer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + + timer->hrtimer.function = kbasep_vinstr_wake_up_callback; + timer->vinstr_ctx = vinstr_ctx; + + while (!kthread_should_stop()) { + struct kbase_vinstr_client *cli = NULL; + struct kbase_vinstr_client *tmp; + int rcode; + + u64 timestamp = kbasep_vinstr_get_timestamp(); + u64 dump_time = 0; + struct list_head expired_requests; + + /* Hold lock while performing operations on lists of clients. */ + mutex_lock(&vinstr_ctx->lock); + + /* Closing thread must not interact with client requests. */ + if (current == vinstr_ctx->thread) { + atomic_set(&vinstr_ctx->request_pending, 0); + + if (!list_empty(&vinstr_ctx->waiting_clients)) { + cli = list_first_entry( + &vinstr_ctx->waiting_clients, + struct kbase_vinstr_client, + list); + dump_time = cli->dump_time; + } + } + + if (!cli || ((s64)timestamp - (s64)dump_time < 0ll)) { + mutex_unlock(&vinstr_ctx->lock); + + /* Sleep until next dumping event or service request. */ + if (cli) { + u64 diff = dump_time - timestamp; + + hrtimer_start( + &timer->hrtimer, + ns_to_ktime(diff), + HRTIMER_MODE_REL); + } + wait_event( + vinstr_ctx->waitq, + atomic_read( + &vinstr_ctx->request_pending) || + kthread_should_stop()); + hrtimer_cancel(&timer->hrtimer); + continue; + } + + rcode = kbasep_vinstr_collect_and_accumulate(vinstr_ctx, + ×tamp); + + INIT_LIST_HEAD(&expired_requests); + + /* Find all expired requests. */ + list_for_each_entry_safe( + cli, + tmp, + &vinstr_ctx->waiting_clients, + list) { + s64 tdiff = + (s64)(timestamp + DUMPING_RESOLUTION) - + (s64)cli->dump_time; + if (tdiff >= 0ll) { + list_del(&cli->list); + list_add(&cli->list, &expired_requests); + } else { + break; + } + } + + /* Fill data for each request found. */ + list_for_each_entry_safe(cli, tmp, &expired_requests, list) { + /* Ensure that legacy buffer will not be used from + * this kthread context. */ + BUG_ON(0 == cli->buffer_count); + /* Expect only periodically sampled clients. */ + BUG_ON(0 == cli->dump_interval); + + if (!rcode) + kbasep_vinstr_update_client( + cli, + timestamp, + BASE_HWCNT_READER_EVENT_PERIODIC); + + /* Set new dumping time. Drop missed probing times. */ + do { + cli->dump_time += cli->dump_interval; + } while (cli->dump_time < timestamp); + + list_del(&cli->list); + kbasep_vinstr_add_dump_request( + cli, + &vinstr_ctx->waiting_clients); + } + + /* Reprogram counters set if required. */ + kbasep_vinstr_reprogram(vinstr_ctx); + + mutex_unlock(&vinstr_ctx->lock); + } + + kfree(timer); + + return 0; +} + +/*****************************************************************************/ + +/** + * kbasep_vinstr_hwcnt_reader_buffer_ready - check if client has ready buffers + * @cli: pointer to vinstr client structure + * + * Return: non-zero if client has at least one dumping buffer filled that was + * not notified to user yet + */ +static int kbasep_vinstr_hwcnt_reader_buffer_ready( + struct kbase_vinstr_client *cli) +{ + KBASE_DEBUG_ASSERT(cli); + return atomic_read(&cli->write_idx) != atomic_read(&cli->meta_idx); +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_get_buffer - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @buffer: pointer to userspace buffer + * @size: size of buffer + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_get_buffer( + struct kbase_vinstr_client *cli, void __user *buffer, + size_t size) +{ + unsigned int meta_idx = atomic_read(&cli->meta_idx); + unsigned int idx = meta_idx % cli->buffer_count; + + struct kbase_hwcnt_reader_metadata *meta = &cli->dump_buffers_meta[idx]; + + /* Metadata sanity check. */ + KBASE_DEBUG_ASSERT(idx == meta->buffer_idx); + + if (sizeof(struct kbase_hwcnt_reader_metadata) != size) + return -EINVAL; + + /* Check if there is any buffer available. */ + if (atomic_read(&cli->write_idx) == meta_idx) + return -EAGAIN; + + /* Check if previously taken buffer was put back. */ + if (atomic_read(&cli->read_idx) != meta_idx) + return -EBUSY; + + /* Copy next available buffer's metadata to user. */ + if (copy_to_user(buffer, meta, size)) + return -EFAULT; + + atomic_inc(&cli->meta_idx); + + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_put_buffer - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @buffer: pointer to userspace buffer + * @size: size of buffer + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_put_buffer( + struct kbase_vinstr_client *cli, void __user *buffer, + size_t size) +{ + unsigned int read_idx = atomic_read(&cli->read_idx); + unsigned int idx = read_idx % cli->buffer_count; + + struct kbase_hwcnt_reader_metadata meta; + + if (sizeof(struct kbase_hwcnt_reader_metadata) != size) + return -EINVAL; + + /* Check if any buffer was taken. */ + if (atomic_read(&cli->meta_idx) == read_idx) + return -EPERM; + + /* Check if correct buffer is put back. */ + if (copy_from_user(&meta, buffer, size)) + return -EFAULT; + if (idx != meta.buffer_idx) + return -EINVAL; + + atomic_inc(&cli->read_idx); + + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_set_interval - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @interval: periodic dumping interval (disable periodic dumping if zero) + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_set_interval( + struct kbase_vinstr_client *cli, u32 interval) +{ + struct kbase_vinstr_context *vinstr_ctx = cli->vinstr_ctx; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + mutex_lock(&vinstr_ctx->lock); + + list_del(&cli->list); + + cli->dump_interval = interval; + + /* If interval is non-zero, enable periodic dumping for this client. */ + if (cli->dump_interval) { + if (DUMPING_RESOLUTION > cli->dump_interval) + cli->dump_interval = DUMPING_RESOLUTION; + cli->dump_time = + kbasep_vinstr_get_timestamp() + cli->dump_interval; + + kbasep_vinstr_add_dump_request( + cli, &vinstr_ctx->waiting_clients); + + atomic_set(&vinstr_ctx->request_pending, 1); + wake_up_all(&vinstr_ctx->waitq); + } else { + list_add(&cli->list, &vinstr_ctx->idle_clients); + } + + mutex_unlock(&vinstr_ctx->lock); + + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_event_mask - return event mask for event id + * @event_id: id of event + * Return: event_mask or zero if event is not supported or maskable + */ +static u32 kbasep_vinstr_hwcnt_reader_event_mask( + enum base_hwcnt_reader_event event_id) +{ + u32 event_mask = 0; + + switch (event_id) { + case BASE_HWCNT_READER_EVENT_PREJOB: + case BASE_HWCNT_READER_EVENT_POSTJOB: + /* These event are maskable. */ + event_mask = (1 << event_id); + break; + + case BASE_HWCNT_READER_EVENT_MANUAL: + case BASE_HWCNT_READER_EVENT_PERIODIC: + /* These event are non-maskable. */ + default: + /* These event are not supported. */ + break; + } + + return event_mask; +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_enable_event - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @event_id: id of event to enable + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_enable_event( + struct kbase_vinstr_client *cli, + enum base_hwcnt_reader_event event_id) +{ + struct kbase_vinstr_context *vinstr_ctx = cli->vinstr_ctx; + u32 event_mask; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + event_mask = kbasep_vinstr_hwcnt_reader_event_mask(event_id); + if (!event_mask) + return -EINVAL; + + mutex_lock(&vinstr_ctx->lock); + cli->event_mask |= event_mask; + mutex_unlock(&vinstr_ctx->lock); + + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_disable_event - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @event_id: id of event to disable + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_disable_event( + struct kbase_vinstr_client *cli, + enum base_hwcnt_reader_event event_id) +{ + struct kbase_vinstr_context *vinstr_ctx = cli->vinstr_ctx; + u32 event_mask; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + event_mask = kbasep_vinstr_hwcnt_reader_event_mask(event_id); + if (!event_mask) + return -EINVAL; + + mutex_lock(&vinstr_ctx->lock); + cli->event_mask &= ~event_mask; + mutex_unlock(&vinstr_ctx->lock); + + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl_get_hwver - hwcnt reader's ioctl command + * @cli: pointer to vinstr client structure + * @hwver: pointer to user buffer where hw version will be stored + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl_get_hwver( + struct kbase_vinstr_client *cli, u32 __user *hwver) +{ +#ifndef CONFIG_MALI_NO_MALI + struct kbase_vinstr_context *vinstr_ctx = cli->vinstr_ctx; +#endif + + u32 ver = 5; + +#ifndef CONFIG_MALI_NO_MALI + KBASE_DEBUG_ASSERT(vinstr_ctx); + if (kbase_hw_has_feature(vinstr_ctx->kbdev, BASE_HW_FEATURE_V4)) + ver = 4; +#endif + + return put_user(ver, hwver); +} + +/** + * kbasep_vinstr_hwcnt_reader_ioctl - hwcnt reader's ioctl + * @filp: pointer to file structure + * @cmd: user command + * @arg: command's argument + * + * Return: zero on success + */ +static long kbasep_vinstr_hwcnt_reader_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + long rcode = 0; + struct kbase_vinstr_client *cli; + + KBASE_DEBUG_ASSERT(filp); + + cli = filp->private_data; + KBASE_DEBUG_ASSERT(cli); + + if (unlikely(KBASE_HWCNT_READER != _IOC_TYPE(cmd))) + return -EINVAL; + + switch (cmd) { + case KBASE_HWCNT_READER_GET_API_VERSION: + rcode = put_user(HWCNT_READER_API, (u32 __user *)arg); + break; + case KBASE_HWCNT_READER_GET_HWVER: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_hwver( + cli, (u32 __user *)arg); + break; + case KBASE_HWCNT_READER_GET_BUFFER_SIZE: + KBASE_DEBUG_ASSERT(cli->vinstr_ctx); + rcode = put_user( + (u32)cli->vinstr_ctx->dump_size, + (u32 __user *)arg); + break; + case KBASE_HWCNT_READER_DUMP: + rcode = kbase_vinstr_hwc_dump( + cli, BASE_HWCNT_READER_EVENT_MANUAL); + break; + case KBASE_HWCNT_READER_CLEAR: + rcode = kbase_vinstr_hwc_clear(cli); + break; + case KBASE_HWCNT_READER_GET_BUFFER: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_buffer( + cli, (void __user *)arg, _IOC_SIZE(cmd)); + break; + case KBASE_HWCNT_READER_PUT_BUFFER: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_put_buffer( + cli, (void __user *)arg, _IOC_SIZE(cmd)); + break; + case KBASE_HWCNT_READER_SET_INTERVAL: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_set_interval( + cli, (u32)arg); + break; + case KBASE_HWCNT_READER_ENABLE_EVENT: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_enable_event( + cli, (enum base_hwcnt_reader_event)arg); + break; + case KBASE_HWCNT_READER_DISABLE_EVENT: + rcode = kbasep_vinstr_hwcnt_reader_ioctl_disable_event( + cli, (enum base_hwcnt_reader_event)arg); + break; + default: + rcode = -EINVAL; + break; + } + + return rcode; +} + +/** + * kbasep_vinstr_hwcnt_reader_poll - hwcnt reader's poll + * @filp: pointer to file structure + * @wait: pointer to poll table + * Return: POLLIN if data can be read without blocking, otherwise zero + */ +static unsigned int kbasep_vinstr_hwcnt_reader_poll(struct file *filp, + poll_table *wait) +{ + struct kbase_vinstr_client *cli; + + KBASE_DEBUG_ASSERT(filp); + KBASE_DEBUG_ASSERT(wait); + + cli = filp->private_data; + KBASE_DEBUG_ASSERT(cli); + + poll_wait(filp, &cli->waitq, wait); + if (kbasep_vinstr_hwcnt_reader_buffer_ready(cli)) + return POLLIN; + return 0; +} + +/** + * kbasep_vinstr_hwcnt_reader_mmap - hwcnt reader's mmap + * @filp: pointer to file structure + * @vma: pointer to vma structure + * Return: zero on success + */ +static int kbasep_vinstr_hwcnt_reader_mmap(struct file *filp, + struct vm_area_struct *vma) +{ + struct kbase_vinstr_client *cli; + unsigned long size, addr, pfn, offset; + unsigned long vm_size = vma->vm_end - vma->vm_start; + + KBASE_DEBUG_ASSERT(filp); + KBASE_DEBUG_ASSERT(vma); + + cli = filp->private_data; + KBASE_DEBUG_ASSERT(cli); + + size = cli->buffer_count * cli->dump_size; + + if (vma->vm_pgoff > (size >> PAGE_SHIFT)) + return -EINVAL; + + offset = vma->vm_pgoff << PAGE_SHIFT; + if (vm_size > size - offset) + return -EINVAL; + + addr = __pa((unsigned long)cli->dump_buffers + offset); + pfn = addr >> PAGE_SHIFT; + + return remap_pfn_range( + vma, + vma->vm_start, + pfn, + vm_size, + vma->vm_page_prot); +} + +/** + * kbasep_vinstr_hwcnt_reader_release - hwcnt reader's release + * @inode: pointer to inode structure + * @filp: pointer to file structure + * Return always return zero + */ +static int kbasep_vinstr_hwcnt_reader_release(struct inode *inode, + struct file *filp) +{ + struct kbase_vinstr_client *cli; + + KBASE_DEBUG_ASSERT(inode); + KBASE_DEBUG_ASSERT(filp); + + cli = filp->private_data; + KBASE_DEBUG_ASSERT(cli); + + kbase_vinstr_detach_client(cli); + return 0; +} + +/*****************************************************************************/ + +/** + * kbasep_vinstr_kick_scheduler - trigger scheduler cycle + * @kbdev: pointer to kbase device structure + */ +static void kbasep_vinstr_kick_scheduler(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long flags; + + down(&js_devdata->schedule_sem); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_backend_slot_update(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + up(&js_devdata->schedule_sem); +} + +/** + * kbasep_vinstr_suspend_worker - worker suspending vinstr module + * @data: pointer to work structure + */ +static void kbasep_vinstr_suspend_worker(struct work_struct *data) +{ + struct kbase_vinstr_context *vinstr_ctx; + unsigned long flags; + + vinstr_ctx = container_of(data, struct kbase_vinstr_context, + suspend_work); + + mutex_lock(&vinstr_ctx->lock); + + if (vinstr_ctx->kctx) + disable_hwcnt(vinstr_ctx); + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + vinstr_ctx->state = VINSTR_SUSPENDED; + wake_up_all(&vinstr_ctx->suspend_waitq); + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + mutex_unlock(&vinstr_ctx->lock); + + /* Kick GPU scheduler to allow entering protected mode. + * This must happen after vinstr was suspended. */ + kbasep_vinstr_kick_scheduler(vinstr_ctx->kbdev); +} + +/** + * kbasep_vinstr_suspend_worker - worker resuming vinstr module + * @data: pointer to work structure + */ +static void kbasep_vinstr_resume_worker(struct work_struct *data) +{ + struct kbase_vinstr_context *vinstr_ctx; + unsigned long flags; + + vinstr_ctx = container_of(data, struct kbase_vinstr_context, + resume_work); + + mutex_lock(&vinstr_ctx->lock); + + if (vinstr_ctx->kctx) + enable_hwcnt(vinstr_ctx); + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + vinstr_ctx->state = VINSTR_IDLE; + wake_up_all(&vinstr_ctx->suspend_waitq); + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + mutex_unlock(&vinstr_ctx->lock); + + /* Kick GPU scheduler to allow entering protected mode. + * Note that scheduler state machine might requested re-entry to + * protected mode before vinstr was resumed. + * This must happen after vinstr was release. */ + kbasep_vinstr_kick_scheduler(vinstr_ctx->kbdev); +} + +/*****************************************************************************/ + +struct kbase_vinstr_context *kbase_vinstr_init(struct kbase_device *kbdev) +{ + struct kbase_vinstr_context *vinstr_ctx; + + vinstr_ctx = kzalloc(sizeof(*vinstr_ctx), GFP_KERNEL); + if (!vinstr_ctx) + return NULL; + + INIT_LIST_HEAD(&vinstr_ctx->idle_clients); + INIT_LIST_HEAD(&vinstr_ctx->waiting_clients); + mutex_init(&vinstr_ctx->lock); + spin_lock_init(&vinstr_ctx->state_lock); + vinstr_ctx->kbdev = kbdev; + vinstr_ctx->thread = NULL; + vinstr_ctx->state = VINSTR_IDLE; + vinstr_ctx->suspend_cnt = 0; + INIT_WORK(&vinstr_ctx->suspend_work, kbasep_vinstr_suspend_worker); + INIT_WORK(&vinstr_ctx->resume_work, kbasep_vinstr_resume_worker); + init_waitqueue_head(&vinstr_ctx->suspend_waitq); + + atomic_set(&vinstr_ctx->request_pending, 0); + init_waitqueue_head(&vinstr_ctx->waitq); + + return vinstr_ctx; +} + +void kbase_vinstr_term(struct kbase_vinstr_context *vinstr_ctx) +{ + struct kbase_vinstr_client *cli; + + /* Stop service thread first. */ + if (vinstr_ctx->thread) + kthread_stop(vinstr_ctx->thread); + + /* Wait for workers. */ + flush_work(&vinstr_ctx->suspend_work); + flush_work(&vinstr_ctx->resume_work); + + while (1) { + struct list_head *list = &vinstr_ctx->idle_clients; + + if (list_empty(list)) { + list = &vinstr_ctx->waiting_clients; + if (list_empty(list)) + break; + } + + cli = list_first_entry(list, struct kbase_vinstr_client, list); + list_del(&cli->list); + kfree(cli->accum_buffer); + kfree(cli); + vinstr_ctx->nclients--; + } + KBASE_DEBUG_ASSERT(!vinstr_ctx->nclients); + if (vinstr_ctx->kctx) + kbasep_vinstr_destroy_kctx(vinstr_ctx); + kfree(vinstr_ctx); +} + +int kbase_vinstr_hwcnt_reader_setup(struct kbase_vinstr_context *vinstr_ctx, + struct kbase_uk_hwcnt_reader_setup *setup) +{ + struct kbase_vinstr_client *cli; + u32 bitmap[4]; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + KBASE_DEBUG_ASSERT(setup); + KBASE_DEBUG_ASSERT(setup->buffer_count); + + bitmap[SHADER_HWCNT_BM] = setup->shader_bm; + bitmap[TILER_HWCNT_BM] = setup->tiler_bm; + bitmap[MMU_L2_HWCNT_BM] = setup->mmu_l2_bm; + bitmap[JM_HWCNT_BM] = setup->jm_bm; + + cli = kbasep_vinstr_attach_client( + vinstr_ctx, + setup->buffer_count, + bitmap, + &setup->fd, + NULL); + + if (!cli) + return -ENOMEM; + + return 0; +} + +int kbase_vinstr_legacy_hwc_setup( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_vinstr_client **cli, + struct kbase_uk_hwcnt_setup *setup) +{ + KBASE_DEBUG_ASSERT(vinstr_ctx); + KBASE_DEBUG_ASSERT(setup); + KBASE_DEBUG_ASSERT(cli); + + if (setup->dump_buffer) { + u32 bitmap[4]; + + bitmap[SHADER_HWCNT_BM] = setup->shader_bm; + bitmap[TILER_HWCNT_BM] = setup->tiler_bm; + bitmap[MMU_L2_HWCNT_BM] = setup->mmu_l2_bm; + bitmap[JM_HWCNT_BM] = setup->jm_bm; + + if (*cli) + return -EBUSY; + + *cli = kbasep_vinstr_attach_client( + vinstr_ctx, + 0, + bitmap, + (void *)(long)setup->dump_buffer, + NULL); + + if (!(*cli)) + return -ENOMEM; + } else { + if (!*cli) + return -EINVAL; + + kbase_vinstr_detach_client(*cli); + *cli = NULL; + } + + return 0; +} + +struct kbase_vinstr_client *kbase_vinstr_hwcnt_kernel_setup( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_uk_hwcnt_reader_setup *setup, + void *kernel_buffer) +{ + u32 bitmap[4]; + + if (!vinstr_ctx || !setup || !kernel_buffer) + return NULL; + + bitmap[SHADER_HWCNT_BM] = setup->shader_bm; + bitmap[TILER_HWCNT_BM] = setup->tiler_bm; + bitmap[MMU_L2_HWCNT_BM] = setup->mmu_l2_bm; + bitmap[JM_HWCNT_BM] = setup->jm_bm; + + return kbasep_vinstr_attach_client( + vinstr_ctx, + 0, + bitmap, + NULL, + kernel_buffer); +} +KBASE_EXPORT_TEST_API(kbase_vinstr_hwcnt_kernel_setup); + +int kbase_vinstr_hwc_dump(struct kbase_vinstr_client *cli, + enum base_hwcnt_reader_event event_id) +{ + int rcode = 0; + struct kbase_vinstr_context *vinstr_ctx; + u64 timestamp; + u32 event_mask; + + if (!cli) + return -EINVAL; + + vinstr_ctx = cli->vinstr_ctx; + KBASE_DEBUG_ASSERT(vinstr_ctx); + + KBASE_DEBUG_ASSERT(event_id < BASE_HWCNT_READER_EVENT_COUNT); + event_mask = 1 << event_id; + + mutex_lock(&vinstr_ctx->lock); + + if (event_mask & cli->event_mask) { + rcode = kbasep_vinstr_collect_and_accumulate( + vinstr_ctx, + ×tamp); + if (rcode) + goto exit; + + rcode = kbasep_vinstr_update_client(cli, timestamp, event_id); + if (rcode) + goto exit; + + kbasep_vinstr_reprogram(vinstr_ctx); + } + +exit: + mutex_unlock(&vinstr_ctx->lock); + + return rcode; +} +KBASE_EXPORT_TEST_API(kbase_vinstr_hwc_dump); + +int kbase_vinstr_hwc_clear(struct kbase_vinstr_client *cli) +{ + struct kbase_vinstr_context *vinstr_ctx; + int rcode; + u64 unused; + + if (!cli) + return -EINVAL; + + vinstr_ctx = cli->vinstr_ctx; + KBASE_DEBUG_ASSERT(vinstr_ctx); + + mutex_lock(&vinstr_ctx->lock); + + rcode = kbasep_vinstr_collect_and_accumulate(vinstr_ctx, &unused); + if (rcode) + goto exit; + rcode = kbase_instr_hwcnt_clear(vinstr_ctx->kctx); + if (rcode) + goto exit; + memset(cli->accum_buffer, 0, cli->dump_size); + + kbasep_vinstr_reprogram(vinstr_ctx); + +exit: + mutex_unlock(&vinstr_ctx->lock); + + return rcode; +} + +int kbase_vinstr_try_suspend(struct kbase_vinstr_context *vinstr_ctx) +{ + unsigned long flags; + int ret = -EAGAIN; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + switch (vinstr_ctx->state) { + case VINSTR_SUSPENDED: + vinstr_ctx->suspend_cnt++; + /* overflow shall not happen */ + BUG_ON(0 == vinstr_ctx->suspend_cnt); + ret = 0; + break; + + case VINSTR_IDLE: + if (vinstr_ctx->clients_present) { + vinstr_ctx->state = VINSTR_SUSPENDING; + schedule_work(&vinstr_ctx->suspend_work); + } else { + vinstr_ctx->state = VINSTR_SUSPENDED; + + vinstr_ctx->suspend_cnt++; + /* overflow shall not happen */ + WARN_ON(0 == vinstr_ctx->suspend_cnt); + ret = 0; + } + break; + + case VINSTR_DUMPING: + vinstr_ctx->state = VINSTR_SUSPENDING; + break; + + case VINSTR_SUSPENDING: + /* fall through */ + case VINSTR_RESUMING: + break; + + default: + BUG(); + break; + } + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); + + return ret; +} + +void kbase_vinstr_suspend(struct kbase_vinstr_context *vinstr_ctx) +{ + wait_event(vinstr_ctx->suspend_waitq, + (0 == kbase_vinstr_try_suspend(vinstr_ctx))); +} + +void kbase_vinstr_resume(struct kbase_vinstr_context *vinstr_ctx) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(vinstr_ctx); + + spin_lock_irqsave(&vinstr_ctx->state_lock, flags); + BUG_ON(VINSTR_SUSPENDING == vinstr_ctx->state); + if (VINSTR_SUSPENDED == vinstr_ctx->state) { + BUG_ON(0 == vinstr_ctx->suspend_cnt); + vinstr_ctx->suspend_cnt--; + if (0 == vinstr_ctx->suspend_cnt) { + if (vinstr_ctx->clients_present) { + vinstr_ctx->state = VINSTR_RESUMING; + schedule_work(&vinstr_ctx->resume_work); + } else { + vinstr_ctx->state = VINSTR_IDLE; + } + } + } + spin_unlock_irqrestore(&vinstr_ctx->state_lock, flags); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.h b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.h new file mode 100644 index 000000000000..6207d25aef06 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.h @@ -0,0 +1,155 @@ +/* + * + * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_VINSTR_H_ +#define _KBASE_VINSTR_H_ + +#include +#include + +/*****************************************************************************/ + +struct kbase_vinstr_context; +struct kbase_vinstr_client; + +/*****************************************************************************/ + +/** + * kbase_vinstr_init() - initialize the vinstr core + * @kbdev: kbase device + * + * Return: pointer to the vinstr context on success or NULL on failure + */ +struct kbase_vinstr_context *kbase_vinstr_init(struct kbase_device *kbdev); + +/** + * kbase_vinstr_term() - terminate the vinstr core + * @vinstr_ctx: vinstr context + */ +void kbase_vinstr_term(struct kbase_vinstr_context *vinstr_ctx); + +/** + * kbase_vinstr_hwcnt_reader_setup - configure hw counters reader + * @vinstr_ctx: vinstr context + * @setup: reader's configuration + * + * Return: zero on success + */ +int kbase_vinstr_hwcnt_reader_setup( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_uk_hwcnt_reader_setup *setup); + +/** + * kbase_vinstr_legacy_hwc_setup - configure hw counters for dumping + * @vinstr_ctx: vinstr context + * @cli: pointer where to store pointer to new vinstr client structure + * @setup: hwc configuration + * + * Return: zero on success + */ +int kbase_vinstr_legacy_hwc_setup( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_vinstr_client **cli, + struct kbase_uk_hwcnt_setup *setup); + +/** + * kbase_vinstr_hwcnt_kernel_setup - configure hw counters for kernel side + * client + * @vinstr_ctx: vinstr context + * @setup: reader's configuration + * @kernel_buffer: pointer to dump buffer + * + * setup->buffer_count and setup->fd are not used for kernel side clients. + * + * Return: pointer to client structure, or NULL on failure + */ +struct kbase_vinstr_client *kbase_vinstr_hwcnt_kernel_setup( + struct kbase_vinstr_context *vinstr_ctx, + struct kbase_uk_hwcnt_reader_setup *setup, + void *kernel_buffer); + +/** + * kbase_vinstr_hwc_dump - issue counter dump for vinstr client + * @cli: pointer to vinstr client + * @event_id: id of event that triggered hwcnt dump + * + * Return: zero on success + */ +int kbase_vinstr_hwc_dump( + struct kbase_vinstr_client *cli, + enum base_hwcnt_reader_event event_id); + +/** + * kbase_vinstr_hwc_clear - performs a reset of the hardware counters for + * a given kbase context + * @cli: pointer to vinstr client + * + * Return: zero on success + */ +int kbase_vinstr_hwc_clear(struct kbase_vinstr_client *cli); + +/** + * kbase_vinstr_try_suspend - try suspending operation of a given vinstr context + * @vinstr_ctx: vinstr context + * + * Return: 0 on success, or negative if state change is in progress + * + * Warning: This API call is non-generic. It is meant to be used only by + * job scheduler state machine. + * + * Function initiates vinstr switch to suspended state. Once it was called + * vinstr enters suspending state. If function return non-zero value, it + * indicates that state switch is not complete and function must be called + * again. On state switch vinstr will trigger job scheduler state machine + * cycle. + */ +int kbase_vinstr_try_suspend(struct kbase_vinstr_context *vinstr_ctx); + +/** + * kbase_vinstr_suspend - suspends operation of a given vinstr context + * @vinstr_ctx: vinstr context + * + * Function initiates vinstr switch to suspended state. Then it blocks until + * operation is completed. + */ +void kbase_vinstr_suspend(struct kbase_vinstr_context *vinstr_ctx); + +/** + * kbase_vinstr_resume - resumes operation of a given vinstr context + * @vinstr_ctx: vinstr context + * + * Function can be called only if it was preceded by a successful call + * to kbase_vinstr_suspend. + */ +void kbase_vinstr_resume(struct kbase_vinstr_context *vinstr_ctx); + +/** + * kbase_vinstr_dump_size - Return required size of dump buffer + * @kbdev: device pointer + * + * Return : buffer size in bytes + */ +size_t kbase_vinstr_dump_size(struct kbase_device *kbdev); + +/** + * kbase_vinstr_detach_client - Detach a client from the vinstr core + * @cli: pointer to vinstr client + */ +void kbase_vinstr_detach_client(struct kbase_vinstr_client *cli); + +#endif /* _KBASE_VINSTR_H_ */ + diff --git a/drivers/gpu/arm/bifrost/mali_linux_kbase_trace.h b/drivers/gpu/arm/bifrost/mali_linux_kbase_trace.h new file mode 100644 index 000000000000..5d6b4021d626 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_linux_kbase_trace.h @@ -0,0 +1,201 @@ +/* + * + * (C) COPYRIGHT 2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#if !defined(_TRACE_MALI_KBASE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_KBASE_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali + +#include + +DECLARE_EVENT_CLASS(mali_slot_template, + TP_PROTO(int jobslot, unsigned int info_val), + TP_ARGS(jobslot, info_val), + TP_STRUCT__entry( + __field(unsigned int, jobslot) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->jobslot = jobslot; + __entry->info_val = info_val; + ), + TP_printk("jobslot=%u info=%u", __entry->jobslot, __entry->info_val) +); + +#define DEFINE_MALI_SLOT_EVENT(name) \ +DEFINE_EVENT(mali_slot_template, mali_##name, \ + TP_PROTO(int jobslot, unsigned int info_val), \ + TP_ARGS(jobslot, info_val)) +DEFINE_MALI_SLOT_EVENT(JM_SUBMIT); +DEFINE_MALI_SLOT_EVENT(JM_JOB_DONE); +DEFINE_MALI_SLOT_EVENT(JM_UPDATE_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_CHECK_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_SOFT_OR_HARD_STOP); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_EVICT); +DEFINE_MALI_SLOT_EVENT(JM_BEGIN_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JM_END_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_SUBMIT_TO_BLOCKED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_CURRENT); +DEFINE_MALI_SLOT_EVENT(JD_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_CORES_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_INUSE_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_AFFINITY_WOULD_VIOLATE); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_RETRY_NEEDED); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB_IRQ); +#undef DEFINE_MALI_SLOT_EVENT + +DECLARE_EVENT_CLASS(mali_refcount_template, + TP_PROTO(int refcount, unsigned int info_val), + TP_ARGS(refcount, info_val), + TP_STRUCT__entry( + __field(unsigned int, refcount) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->refcount = refcount; + __entry->info_val = info_val; + ), + TP_printk("refcount=%u info=%u", __entry->refcount, __entry->info_val) +); + +#define DEFINE_MALI_REFCOUNT_EVENT(name) \ +DEFINE_EVENT(mali_refcount_template, mali_##name, \ + TP_PROTO(int refcount, unsigned int info_val), \ + TP_ARGS(refcount, info_val)) +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX_NOLOCK); +DEFINE_MALI_REFCOUNT_EVENT(JS_ADD_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_REMOVE_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_RELEASE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_TRY_SCHEDULE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_INIT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TERM_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_ENQUEUE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_DEQUEUE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TRY_EVICT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_ADD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_REMOVE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_FOREACH_CTX_JOBS); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_ACTIVE); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_IDLE); +#undef DEFINE_MALI_REFCOUNT_EVENT + +DECLARE_EVENT_CLASS(mali_add_template, + TP_PROTO(int gpu_addr, unsigned int info_val), + TP_ARGS(gpu_addr, info_val), + TP_STRUCT__entry( + __field(unsigned int, gpu_addr) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->gpu_addr = gpu_addr; + __entry->info_val = info_val; + ), + TP_printk("gpu_addr=%u info=%u", __entry->gpu_addr, __entry->info_val) +); + +#define DEFINE_MALI_ADD_EVENT(name) \ +DEFINE_EVENT(mali_add_template, mali_##name, \ + TP_PROTO(int gpu_addr, unsigned int info_val), \ + TP_ARGS(gpu_addr, info_val)) +DEFINE_MALI_ADD_EVENT(CORE_CTX_DESTROY); +DEFINE_MALI_ADD_EVENT(CORE_CTX_HWINSTR_TERM); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_DONE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_SOFT_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_HARD_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_SAMPLE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_CLEAN_INV_CACHES); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER_END); +DEFINE_MALI_ADD_EVENT(JD_CANCEL_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE); +DEFINE_MALI_ADD_EVENT(JD_CANCEL); +DEFINE_MALI_ADD_EVENT(JD_ZAP_CONTEXT); +DEFINE_MALI_ADD_EVENT(JM_IRQ); +DEFINE_MALI_ADD_EVENT(JM_IRQ_END); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS_DONE); +DEFINE_MALI_ADD_EVENT(JM_ZAP_NON_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_DONE); +DEFINE_MALI_ADD_EVENT(JM_SUBMIT_AFTER_RESET); +DEFINE_MALI_ADD_EVENT(JM_JOB_COMPLETE); +DEFINE_MALI_ADD_EVENT(JS_FAST_START_EVICTS_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_CTX); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_END); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_START); +DEFINE_MALI_ADD_EVENT(JS_POLICY_ENQUEUE_JOB); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_DESIRED); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERING_UP); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERED_UP); +DEFINE_MALI_ADD_EVENT(PM_PWRON); +DEFINE_MALI_ADD_EVENT(PM_PWRON_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWRON_L2); +DEFINE_MALI_ADD_EVENT(PM_PWROFF); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_L2); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_L2); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED_TILER); +DEFINE_MALI_ADD_EVENT(PM_UNREQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_RELEASE_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_GPU_ON); +DEFINE_MALI_ADD_EVENT(PM_GPU_OFF); +DEFINE_MALI_ADD_EVENT(PM_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_INIT); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_TERM); +DEFINE_MALI_ADD_EVENT(PM_CA_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_WAKE_WAITERS); +#undef DEFINE_MALI_ADD_EVENT + +#endif /* _TRACE_MALI_KBASE_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mali_linux_kbase_trace + +/* This part must be outside protection */ +#include diff --git a/drivers/gpu/arm/bifrost/mali_linux_trace.h b/drivers/gpu/arm/bifrost/mali_linux_trace.h new file mode 100644 index 000000000000..2be06a552768 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_linux_trace.h @@ -0,0 +1,189 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#if !defined(_TRACE_MALI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali +#define TRACE_INCLUDE_FILE mali_linux_trace + +#include + +#define MALI_JOB_SLOTS_EVENT_CHANGED + +/** + * mali_job_slots_event - called from mali_kbase_core_linux.c + * @event_id: ORed together bitfields representing a type of event, made with the GATOR_MAKE_EVENT() macro. + */ +TRACE_EVENT(mali_job_slots_event, + TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, + unsigned char job_id), + TP_ARGS(event_id, tgid, pid, job_id), + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned int, tgid) + __field(unsigned int, pid) + __field(unsigned char, job_id) + ), + TP_fast_assign( + __entry->event_id = event_id; + __entry->tgid = tgid; + __entry->pid = pid; + __entry->job_id = job_id; + ), + TP_printk("event=%u tgid=%u pid=%u job_id=%u", + __entry->event_id, __entry->tgid, __entry->pid, __entry->job_id) +); + +/** + * mali_pm_status - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache) + * @value: 64bits bitmask reporting either power status of the cores (1-ON, 0-OFF) + */ +TRACE_EVENT(mali_pm_status, + TP_PROTO(unsigned int event_id, unsigned long long value), + TP_ARGS(event_id, value), + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned long long, value) + ), + TP_fast_assign( + __entry->event_id = event_id; + __entry->value = value; + ), + TP_printk("event %u = %llu", __entry->event_id, __entry->value) +); + +/** + * mali_pm_power_on - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache) + * @value: 64bits bitmask reporting the cores to power up + */ +TRACE_EVENT(mali_pm_power_on, + TP_PROTO(unsigned int event_id, unsigned long long value), + TP_ARGS(event_id, value), + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned long long, value) + ), + TP_fast_assign( + __entry->event_id = event_id; + __entry->value = value; + ), + TP_printk("event %u = %llu", __entry->event_id, __entry->value) +); + +/** + * mali_pm_power_off - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache) + * @value: 64bits bitmask reporting the cores to power down + */ +TRACE_EVENT(mali_pm_power_off, + TP_PROTO(unsigned int event_id, unsigned long long value), + TP_ARGS(event_id, value), + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned long long, value) + ), + TP_fast_assign( + __entry->event_id = event_id; + __entry->value = value; + ), + TP_printk("event %u = %llu", __entry->event_id, __entry->value) +); + +/** + * mali_page_fault_insert_pages - Called by page_fault_worker() + * it reports an MMU page fault resulting in new pages being mapped. + * @event_id: MMU address space number. + * @value: number of newly allocated pages + */ +TRACE_EVENT(mali_page_fault_insert_pages, + TP_PROTO(int event_id, unsigned long value), + TP_ARGS(event_id, value), + TP_STRUCT__entry( + __field(int, event_id) + __field(unsigned long, value) + ), + TP_fast_assign( + __entry->event_id = event_id; + __entry->value = value; + ), + TP_printk("event %d = %lu", __entry->event_id, __entry->value) +); + +/** + * mali_mmu_as_in_use - Called by assign_and_activate_kctx_addr_space() + * it reports that a certain MMU address space is in use now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_in_use, + TP_PROTO(int event_id), + TP_ARGS(event_id), + TP_STRUCT__entry( + __field(int, event_id) + ), + TP_fast_assign( + __entry->event_id = event_id; + ), + TP_printk("event=%d", __entry->event_id) +); + +/** + * mali_mmu_as_released - Called by kbasep_js_runpool_release_ctx_internal() + * it reports that a certain MMU address space has been released now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_released, + TP_PROTO(int event_id), + TP_ARGS(event_id), + TP_STRUCT__entry( + __field(int, event_id) + ), + TP_fast_assign( + __entry->event_id = event_id; + ), + TP_printk("event=%d", __entry->event_id) +); + +/** + * mali_total_alloc_pages_change - Called by kbase_atomic_add_pages() + * and by kbase_atomic_sub_pages() + * it reports that the total number of allocated pages is changed. + * @event_id: number of pages to be added or subtracted (according to the sign). + */ +TRACE_EVENT(mali_total_alloc_pages_change, + TP_PROTO(long long int event_id), + TP_ARGS(event_id), + TP_STRUCT__entry( + __field(long long int, event_id) + ), + TP_fast_assign( + __entry->event_id = event_id; + ), + TP_printk("event=%lld", __entry->event_id) +); + +#endif /* _TRACE_MALI_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include diff --git a/drivers/gpu/arm/bifrost/mali_malisw.h b/drivers/gpu/arm/bifrost/mali_malisw.h new file mode 100644 index 000000000000..99452933eab4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_malisw.h @@ -0,0 +1,131 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Kernel-wide include for common macros and types. + */ + +#ifndef _MALISW_H_ +#define _MALISW_H_ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) +#define U8_MAX ((u8)~0U) +#define S8_MAX ((s8)(U8_MAX>>1)) +#define S8_MIN ((s8)(-S8_MAX - 1)) +#define U16_MAX ((u16)~0U) +#define S16_MAX ((s16)(U16_MAX>>1)) +#define S16_MIN ((s16)(-S16_MAX - 1)) +#define U32_MAX ((u32)~0U) +#define S32_MAX ((s32)(U32_MAX>>1)) +#define S32_MIN ((s32)(-S32_MAX - 1)) +#define U64_MAX ((u64)~0ULL) +#define S64_MAX ((s64)(U64_MAX>>1)) +#define S64_MIN ((s64)(-S64_MAX - 1)) +#endif /* LINUX_VERSION_CODE */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) +#define SIZE_MAX (~(size_t)0) +#endif /* LINUX_VERSION_CODE */ + +/** + * MIN - Return the lesser of two values. + * + * As a macro it may evaluate its arguments more than once. + * Refer to MAX macro for more details + */ +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +/** + * MAX - Return the greater of two values. + * + * As a macro it may evaluate its arguments more than once. + * If called on the same two arguments as MIN it is guaranteed to return + * the one that MIN didn't return. This is significant for types where not + * all values are comparable e.g. NaNs in floating-point types. But if you want + * to retrieve the min and max of two values, consider using a conditional swap + * instead. + */ +#define MAX(x, y) ((x) < (y) ? (y) : (x)) + +/** + * @hideinitializer + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define CSTD_UNUSED(x) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for use where "no behavior" is desired. This is useful + * when compile time macros turn a function-like macro in to a no-op, but + * where having no statement is otherwise invalid. + */ +#define CSTD_NOP(...) ((void)#__VA_ARGS__) + +/** + * Function-like macro for converting a pointer in to a u64 for storing into + * an external data structure. This is commonly used when pairing a 32-bit + * CPU with a 64-bit peripheral, such as a Midgard GPU. C's type promotion + * is complex and a straight cast does not work reliably as pointers are + * often considered as signed. + */ +#define PTR_TO_U64(x) ((uint64_t)((uintptr_t)(x))) + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro. + * @code + * #define MY_MACRO 32 + * CSTD_STR1( MY_MACRO ) + * > "MY_MACRO" + * @endcode + */ +#define CSTD_STR1(x) #x + +/** + * @hideinitializer + * Function-like macro for stringizing a macro's value. This should not be used + * if the macro is defined in a way which may have no value; use the + * alternative @c CSTD_STR2N macro should be used instead. + * @code + * #define MY_MACRO 32 + * CSTD_STR2( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2(x) CSTD_STR1(x) + +/** + * Specify an assertion value which is evaluated at compile time. Recommended + * usage is specification of a @c static @c INLINE function containing all of + * the assertions thus: + * + * @code + * static INLINE [module]_compile_time_assertions( void ) + * { + * COMPILE_TIME_ASSERT( sizeof(uintptr_t) == sizeof(intptr_t) ); + * } + * @endcode + * + * @note Use @c static not @c STATIC. We never want to turn off this @c static + * specification for testing purposes. + */ +#define CSTD_COMPILE_TIME_ASSERT(expr) \ + do { switch (0) { case 0: case (expr):; } } while (false) + +#endif /* _MALISW_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_midg_coherency.h b/drivers/gpu/arm/bifrost/mali_midg_coherency.h new file mode 100644 index 000000000000..a509cbd5f175 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_midg_coherency.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT 2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _MIDG_COHERENCY_H_ +#define _MIDG_COHERENCY_H_ + +#define COHERENCY_ACE_LITE 0 +#define COHERENCY_ACE 1 +#define COHERENCY_NONE 31 +#define COHERENCY_FEATURE_BIT(x) (1 << (x)) + +#endif /* _MIDG_COHERENCY_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_midg_regmap.h b/drivers/gpu/arm/bifrost/mali_midg_regmap.h new file mode 100644 index 000000000000..554ed8dcb3eb --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_midg_regmap.h @@ -0,0 +1,611 @@ +/* + * + * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _MIDGARD_REGMAP_H_ +#define _MIDGARD_REGMAP_H_ + +#include "mali_midg_coherency.h" +#include "mali_kbase_gpu_id.h" + +/* + * Begin Register Offsets + */ + +#define GPU_CONTROL_BASE 0x0000 +#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) +#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ +#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */ +#define SUSPEND_SIZE 0x008 /* (RO) Fixed-function suspend buffer + size */ +#define TILER_FEATURES 0x00C /* (RO) Tiler Features */ +#define MEM_FEATURES 0x010 /* (RO) Memory system features */ +#define MMU_FEATURES 0x014 /* (RO) MMU features */ +#define AS_PRESENT 0x018 /* (RO) Address space slots present */ +#define JS_PRESENT 0x01C /* (RO) Job slots present */ +#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */ +#define GPU_IRQ_CLEAR 0x024 /* (WO) */ +#define GPU_IRQ_MASK 0x028 /* (RW) */ +#define GPU_IRQ_STATUS 0x02C /* (RO) */ + +/* IRQ flags */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. Intended to use with SOFT_RESET + commands which may take time. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down + and the power manager is idle. */ + +#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ + +#define GPU_IRQ_REG_ALL (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \ + | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED) + +#define GPU_COMMAND 0x030 /* (WO) */ +#define GPU_STATUS 0x034 /* (RO) */ +#define LATEST_FLUSH 0x038 /* (RO) */ + +#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */ +#define GPU_DBGEN (1 << 8) /* DBGEN wire status */ + +#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */ +#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */ +#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */ + +#define PWR_KEY 0x050 /* (WO) Power manager key register */ +#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */ +#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */ + +#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */ +#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */ +#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */ +#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */ +#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */ +#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */ +#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */ + +#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */ +#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */ +#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */ +#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */ + +#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ +#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ +#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */ +#define THREAD_FEATURES 0x0AC /* (RO) Thread features */ + +#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */ +#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */ +#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */ + +#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) + +#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */ +#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */ +#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */ +#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */ +#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */ +#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */ +#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */ +#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */ +#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */ +#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */ +#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */ +#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */ +#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */ +#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */ +#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */ +#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */ + +#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2)) + +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ + +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */ + +#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */ + +#define STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */ +#define STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */ + + +#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ +#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ + +#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ +#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ + +#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ +#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ + +#define STACK_READY_LO 0xE10 /* (RO) Core stack ready bitmap, low word */ +#define STACK_READY_HI 0xE14 /* (RO) Core stack ready bitmap, high word */ + + +#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ +#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ + +#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ +#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ + +#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ +#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ + +#define STACK_PWRON_LO 0xE20 /* (RO) Core stack power on bitmap, low word */ +#define STACK_PWRON_HI 0xE24 /* (RO) Core stack power on bitmap, high word */ + + +#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */ +#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */ + +#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */ +#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */ + +#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */ +#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */ + +#define STACK_PWROFF_LO 0xE30 /* (RO) Core stack power off bitmap, low word */ +#define STACK_PWROFF_HI 0xE34 /* (RO) Core stack power off bitmap, high word */ + + +#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */ +#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */ + +#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */ +#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */ + +#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */ +#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */ + +#define STACK_PWRTRANS_LO 0xE40 /* (RO) Core stack power transition bitmap, low word */ +#define STACK_PWRTRANS_HI 0xE44 /* (RO) Core stack power transition bitmap, high word */ + + +#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */ +#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */ + +#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */ +#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */ + +#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */ +#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */ + +#define COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */ +#define COHERENCY_ENABLE 0x304 /* (RW) Coherency enable */ + +#define JM_CONFIG 0xF00 /* (RW) Job Manager configuration register (Implementation specific register) */ +#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration settings (Implementation specific register) */ +#define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration settings (Implementation specific register) */ +#define L2_MMU_CONFIG 0xF0C /* (RW) Configuration of the L2 cache and MMU (Implementation specific register) */ + +#define JOB_CONTROL_BASE 0x1000 + +#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) + +#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */ +#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ +#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ +#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */ +#define JOB_IRQ_JS_STATE 0x010 /* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */ +#define JOB_IRQ_THROTTLE 0x014 /* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS is NOT affected by this, just the delivery of the interrupt. */ + +#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */ +#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */ +#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */ +#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */ +#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */ +#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */ +#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */ +#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */ +#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */ +#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */ +#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */ +#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */ +#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */ +#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */ +#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */ +#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */ + +#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) + +#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ +#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ +#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ +#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ +#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ +#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ +#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ +#define JS_XAFFINITY 0x1C /* (RO) Extended affinity mask for job + slot n */ + +#define JS_COMMAND 0x20 /* (WO) Command register for job slot n */ +#define JS_STATUS 0x24 /* (RO) Status register for job slot n */ + +#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ +#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ + +#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ +#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ +#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ +#define JS_XAFFINITY_NEXT 0x5C /* (RW) Next extended affinity mask for + job slot n */ + +#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ + +#define JS_FLUSH_ID_NEXT 0x70 /* (RW) Next job slot n cache flush ID */ + +#define MEMORY_MANAGEMENT_BASE 0x2000 +#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r)) + +#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */ +#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */ +#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */ +#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */ + +#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ +#define MMU_AS1 0x440 /* Configuration registers for address space 1 */ +#define MMU_AS2 0x480 /* Configuration registers for address space 2 */ +#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */ +#define MMU_AS4 0x500 /* Configuration registers for address space 4 */ +#define MMU_AS5 0x540 /* Configuration registers for address space 5 */ +#define MMU_AS6 0x580 /* Configuration registers for address space 6 */ +#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */ +#define MMU_AS8 0x600 /* Configuration registers for address space 8 */ +#define MMU_AS9 0x640 /* Configuration registers for address space 9 */ +#define MMU_AS10 0x680 /* Configuration registers for address space 10 */ +#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */ +#define MMU_AS12 0x700 /* Configuration registers for address space 12 */ +#define MMU_AS13 0x740 /* Configuration registers for address space 13 */ +#define MMU_AS14 0x780 /* Configuration registers for address space 14 */ +#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */ + +#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) + +#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ +#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ +#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ +#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ +#define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */ +#define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */ +#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */ +#define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */ +#define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */ +#define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */ +#define AS_STATUS 0x28 /* (RO) Status flags for address space n */ + + +/* (RW) Translation table configuration for address space n, low word */ +#define AS_TRANSCFG_LO 0x30 +/* (RW) Translation table configuration for address space n, high word */ +#define AS_TRANSCFG_HI 0x34 +/* (RO) Secondary fault address for address space n, low word */ +#define AS_FAULTEXTRA_LO 0x38 +/* (RO) Secondary fault address for address space n, high word */ +#define AS_FAULTEXTRA_HI 0x3C + +/* End Register Offsets */ + +/* + * MMU_IRQ_RAWSTAT register values. Values are valid also for + MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers. + */ + +#define MMU_PAGE_FAULT_FLAGS 16 + +/* Macros returning a bitmask to retrieve page fault or bus error flags from + * MMU registers */ +#define MMU_PAGE_FAULT(n) (1UL << (n)) +#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS)) + +/* + * Begin LPAE MMU TRANSTAB register values + */ +#define AS_TRANSTAB_LPAE_ADDR_SPACE_MASK 0xfffff000 +#define AS_TRANSTAB_LPAE_ADRMODE_UNMAPPED (0u << 0) +#define AS_TRANSTAB_LPAE_ADRMODE_IDENTITY (1u << 1) +#define AS_TRANSTAB_LPAE_ADRMODE_TABLE (3u << 0) +#define AS_TRANSTAB_LPAE_READ_INNER (1u << 2) +#define AS_TRANSTAB_LPAE_SHARE_OUTER (1u << 4) + +#define AS_TRANSTAB_LPAE_ADRMODE_MASK 0x00000003 + +/* + * Begin AARCH64 MMU TRANSTAB register values + */ +#define MMU_HW_OUTA_BITS 40 +#define AS_TRANSTAB_BASE_MASK ((1ULL << MMU_HW_OUTA_BITS) - (1ULL << 4)) + +/* + * Begin MMU STATUS register values + */ +#define AS_STATUS_AS_ACTIVE 0x01 + +#define AS_FAULTSTATUS_EXCEPTION_CODE_MASK (0x7<<3) +#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSLATION_FAULT (0x0<<3) +#define AS_FAULTSTATUS_EXCEPTION_CODE_PERMISSION_FAULT (0x1<<3) +#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSTAB_BUS_FAULT (0x2<<3) +#define AS_FAULTSTATUS_EXCEPTION_CODE_ACCESS_FLAG (0x3<<3) + +#define AS_FAULTSTATUS_EXCEPTION_CODE_ADDRESS_SIZE_FAULT (0x4<<3) +#define AS_FAULTSTATUS_EXCEPTION_CODE_MEMORY_ATTRIBUTES_FAULT (0x5<<3) + +#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC (0x0<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3<<8) + +/* + * Begin MMU TRANSCFG register values + */ + +#define AS_TRANSCFG_ADRMODE_LEGACY 0 +#define AS_TRANSCFG_ADRMODE_UNMAPPED 1 +#define AS_TRANSCFG_ADRMODE_IDENTITY 2 +#define AS_TRANSCFG_ADRMODE_AARCH64_4K 6 +#define AS_TRANSCFG_ADRMODE_AARCH64_64K 8 + +#define AS_TRANSCFG_ADRMODE_MASK 0xF + + +/* + * Begin TRANSCFG register values + */ +#define AS_TRANSCFG_PTW_MEMATTR_MASK (3 << 24) +#define AS_TRANSCFG_PTW_MEMATTR_NON_CACHEABLE (1 << 24) +#define AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK (2 << 24) + +#define AS_TRANSCFG_PTW_SH_MASK ((3 << 28)) +#define AS_TRANSCFG_PTW_SH_OS (2 << 28) +#define AS_TRANSCFG_PTW_SH_IS (3 << 28) + +/* + * Begin Command Values + */ + +/* JS_COMMAND register commands */ +#define JS_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */ +#define JS_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */ +#define JS_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */ +#define JS_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */ +#define JS_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */ +#define JS_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */ + +#define JS_COMMAND_MASK 0x07 /* Mask of bits currently in use by the HW */ + +/* AS_COMMAND register commands */ +#define AS_COMMAND_NOP 0x00 /* NOP Operation */ +#define AS_COMMAND_UPDATE 0x01 /* Broadcasts the values in AS_TRANSTAB and ASn_MEMATTR to all MMUs */ +#define AS_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */ +#define AS_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs + (deprecated - only for use with T60x) */ +#define AS_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then + flush all L2 caches then issue a flush region command to all MMUs */ + +/* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */ +#define JS_CONFIG_START_FLUSH_NO_ACTION (0u << 0) +#define JS_CONFIG_START_FLUSH_CLEAN (1u << 8) +#define JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8) +#define JS_CONFIG_START_MMU (1u << 10) +#define JS_CONFIG_JOB_CHAIN_FLAG (1u << 11) +#define JS_CONFIG_END_FLUSH_NO_ACTION JS_CONFIG_START_FLUSH_NO_ACTION +#define JS_CONFIG_END_FLUSH_CLEAN (1u << 12) +#define JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12) +#define JS_CONFIG_ENABLE_FLUSH_REDUCTION (1u << 14) +#define JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK (1u << 15) +#define JS_CONFIG_THREAD_PRI(n) ((n) << 16) + +/* JS_XAFFINITY register values */ +#define JS_XAFFINITY_XAFFINITY_ENABLE (1u << 0) +#define JS_XAFFINITY_TILER_ENABLE (1u << 8) +#define JS_XAFFINITY_CACHE_ENABLE (1u << 16) + +/* JS_STATUS register values */ + +/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h. + * The values are separated to avoid dependency of userspace and kernel code. + */ + +/* Group of values representing the job status insead a particular fault */ +#define JS_STATUS_NO_EXCEPTION_BASE 0x00 +#define JS_STATUS_INTERRUPTED (JS_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */ +#define JS_STATUS_STOPPED (JS_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */ +#define JS_STATUS_TERMINATED (JS_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */ + +/* General fault values */ +#define JS_STATUS_FAULT_BASE 0x40 +#define JS_STATUS_CONFIG_FAULT (JS_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */ +#define JS_STATUS_POWER_FAULT (JS_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */ +#define JS_STATUS_READ_FAULT (JS_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */ +#define JS_STATUS_WRITE_FAULT (JS_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */ +#define JS_STATUS_AFFINITY_FAULT (JS_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */ +#define JS_STATUS_BUS_FAULT (JS_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */ + +/* Instruction or data faults */ +#define JS_STATUS_INSTRUCTION_FAULT_BASE 0x50 +#define JS_STATUS_INSTR_INVALID_PC (JS_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */ +#define JS_STATUS_INSTR_INVALID_ENC (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */ +#define JS_STATUS_INSTR_TYPE_MISMATCH (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */ +#define JS_STATUS_INSTR_OPERAND_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */ +#define JS_STATUS_INSTR_TLS_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */ +#define JS_STATUS_INSTR_BARRIER_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */ +#define JS_STATUS_INSTR_ALIGN_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */ +/* NOTE: No fault with 0x57 code defined in spec. */ +#define JS_STATUS_DATA_INVALID_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */ +#define JS_STATUS_TILE_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */ +#define JS_STATUS_ADDRESS_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */ + +/* Other faults */ +#define JS_STATUS_MEMORY_FAULT_BASE 0x60 +#define JS_STATUS_OUT_OF_MEMORY (JS_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */ +#define JS_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */ + +/* GPU_COMMAND values */ +#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */ +#define GPU_COMMAND_SOFT_RESET 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */ +#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */ +#define GPU_COMMAND_PRFCNT_CLEAR 0x03 /* Clear all performance counters, setting them all to zero. */ +#define GPU_COMMAND_PRFCNT_SAMPLE 0x04 /* Sample all performance counters, writing them out to memory */ +#define GPU_COMMAND_CYCLE_COUNT_START 0x05 /* Starts the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CYCLE_COUNT_STOP 0x06 /* Stops the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */ +#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */ +#define GPU_COMMAND_SET_PROTECTED_MODE 0x09 /* Places the GPU in protected mode */ + +/* End Command Values */ + +/* GPU_STATUS values */ +#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ +#define GPU_STATUS_PROTECTED_MODE_ACTIVE (1 << 7) /* Set if protected mode is active */ + +/* PRFCNT_CONFIG register values */ +#define PRFCNT_CONFIG_MODE_SHIFT 0 /* Counter mode position. */ +#define PRFCNT_CONFIG_AS_SHIFT 4 /* Address space bitmap position. */ +#define PRFCNT_CONFIG_SETSELECT_SHIFT 8 /* Set select position. */ + +#define PRFCNT_CONFIG_MODE_OFF 0 /* The performance counters are disabled. */ +#define PRFCNT_CONFIG_MODE_MANUAL 1 /* The performance counters are enabled, but are only written out when a PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. */ +#define PRFCNT_CONFIG_MODE_TILE 2 /* The performance counters are enabled, and are written out each time a tile finishes rendering. */ + +/* AS_MEMATTR values: */ +/* Use GPU implementation-defined caching policy. */ +#define AS_MEMATTR_IMPL_DEF_CACHE_POLICY 0x88ull +/* The attribute set to force all resources to be cached. */ +#define AS_MEMATTR_FORCE_TO_CACHE_ALL 0x8Full +/* Inner write-alloc cache setup, no outer caching */ +#define AS_MEMATTR_WRITE_ALLOC 0x8Dull + +/* Set to implementation defined, outer caching */ +#define AS_MEMATTR_AARCH64_OUTER_IMPL_DEF 0x88ull +/* Set to write back memory, outer caching */ +#define AS_MEMATTR_AARCH64_OUTER_WA 0x8Dull + +/* Use GPU implementation-defined caching policy. */ +#define AS_MEMATTR_LPAE_IMPL_DEF_CACHE_POLICY 0x48ull +/* The attribute set to force all resources to be cached. */ +#define AS_MEMATTR_LPAE_FORCE_TO_CACHE_ALL 0x4Full +/* Inner write-alloc cache setup, no outer caching */ +#define AS_MEMATTR_LPAE_WRITE_ALLOC 0x4Dull +/* Set to implementation defined, outer caching */ +#define AS_MEMATTR_LPAE_OUTER_IMPL_DEF 0x88ull +/* Set to write back memory, outer caching */ +#define AS_MEMATTR_LPAE_OUTER_WA 0x8Dull + +/* Symbols for default MEMATTR to use + * Default is - HW implementation defined caching */ +#define AS_MEMATTR_INDEX_DEFAULT 0 +#define AS_MEMATTR_INDEX_DEFAULT_ACE 3 + +/* HW implementation defined caching */ +#define AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0 +/* Force cache on */ +#define AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1 +/* Write-alloc */ +#define AS_MEMATTR_INDEX_WRITE_ALLOC 2 +/* Outer coherent, inner implementation defined policy */ +#define AS_MEMATTR_INDEX_OUTER_IMPL_DEF 3 +/* Outer coherent, write alloc inner */ +#define AS_MEMATTR_INDEX_OUTER_WA 4 + +/* JS_FEATURES register */ + +#define JS_FEATURE_NULL_JOB (1u << 1) +#define JS_FEATURE_SET_VALUE_JOB (1u << 2) +#define JS_FEATURE_CACHE_FLUSH_JOB (1u << 3) +#define JS_FEATURE_COMPUTE_JOB (1u << 4) +#define JS_FEATURE_VERTEX_JOB (1u << 5) +#define JS_FEATURE_GEOMETRY_JOB (1u << 6) +#define JS_FEATURE_TILER_JOB (1u << 7) +#define JS_FEATURE_FUSED_JOB (1u << 8) +#define JS_FEATURE_FRAGMENT_JOB (1u << 9) + +/* End JS_FEATURES register */ + +/* L2_MMU_CONFIG register */ +#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT (23) +#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY (0x1 << L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT (24) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) + +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT (26) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +/* End L2_MMU_CONFIG register */ + +/* THREAD_* registers */ + +/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */ +#define IMPLEMENTATION_UNSPECIFIED 0 +#define IMPLEMENTATION_SILICON 1 +#define IMPLEMENTATION_FPGA 2 +#define IMPLEMENTATION_MODEL 3 + +/* Default values when registers are not supported by the implemented hardware */ +#define THREAD_MT_DEFAULT 256 +#define THREAD_MWS_DEFAULT 256 +#define THREAD_MBS_DEFAULT 256 +#define THREAD_MR_DEFAULT 1024 +#define THREAD_MTQ_DEFAULT 4 +#define THREAD_MTGS_DEFAULT 10 + +/* End THREAD_* registers */ + +/* SHADER_CONFIG register */ + +#define SC_ALT_COUNTERS (1ul << 3) +#define SC_OVERRIDE_FWD_PIXEL_KILL (1ul << 4) +#define SC_SDC_DISABLE_OQ_DISCARD (1ul << 6) +#define SC_LS_ALLOW_ATTR_TYPES (1ul << 16) +#define SC_LS_PAUSEBUFFER_DISABLE (1ul << 16) +#define SC_TLS_HASH_ENABLE (1ul << 17) +#define SC_LS_ATTR_CHECK_DISABLE (1ul << 18) +#define SC_ENABLE_TEXGRD_FLAGS (1ul << 25) +/* End SHADER_CONFIG register */ + +/* TILER_CONFIG register */ + +#define TC_CLOCK_GATE_OVERRIDE (1ul << 0) + +/* End TILER_CONFIG register */ + +/* JM_CONFIG register */ + +#define JM_TIMESTAMP_OVERRIDE (1ul << 0) +#define JM_CLOCK_GATE_OVERRIDE (1ul << 1) +#define JM_JOB_THROTTLE_ENABLE (1ul << 2) +#define JM_JOB_THROTTLE_LIMIT_SHIFT (3) +#define JM_MAX_JOB_THROTTLE_LIMIT (0x3F) +#define JM_FORCE_COHERENCY_FEATURES_SHIFT (2) +#define JM_IDVS_GROUP_SIZE_SHIFT (16) +#define JM_MAX_IDVS_GROUP_SIZE (0x3F) +/* End JM_CONFIG register */ + + +#endif /* _MIDGARD_REGMAP_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_timeline.h b/drivers/gpu/arm/bifrost/mali_timeline.h new file mode 100644 index 000000000000..bd5f6614b6bb --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_timeline.h @@ -0,0 +1,396 @@ +/* + * + * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali_timeline + +#if !defined(_MALI_TIMELINE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _MALI_TIMELINE_H + +#include + +TRACE_EVENT(mali_timeline_atoms_in_flight, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int tgid, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + tgid, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, tgid) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->tgid = tgid; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i", CTX_SET_NR_ATOMS_IN_FLIGHT, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->count) +); + + +TRACE_EVENT(mali_timeline_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->atom_id, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_gpu_slot_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_slot_action, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int active), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + active), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, active) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->active = active; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->active) + +); + +TRACE_EVENT(mali_timeline_l2_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int state), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + state), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, state) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->state = state; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->state) + +); +TRACE_EVENT(mali_timeline_pm_event, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int pm_event_type, + unsigned int pm_event_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + pm_event_type, + pm_event_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, pm_event_type) + __field(unsigned int, pm_event_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->pm_event_type = pm_event_type; + __entry->pm_event_id = pm_event_id; + ), + + TP_printk("%i,%i.%.9i,0,%i,%u", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->pm_event_type, __entry->pm_event_id) + +); + +TRACE_EVENT(mali_timeline_slot_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_pm_checktrans, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int trans_code, + int trans_id), + + TP_ARGS(ts_sec, + ts_nsec, + trans_code, + trans_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, trans_code) + __field(int, trans_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->trans_code = trans_code; + __entry->trans_id = trans_id; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->trans_code, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->trans_id) + +); + +TRACE_EVENT(mali_timeline_context_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,0,%i", SW_SET_CONTEXT_ACTIVE, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->count) +); + +#endif /* _MALI_TIMELINE_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include + diff --git a/drivers/gpu/arm/bifrost/mali_uk.h b/drivers/gpu/arm/bifrost/mali_uk.h new file mode 100644 index 000000000000..841d03fb5873 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_uk.h @@ -0,0 +1,141 @@ +/* + * + * (C) COPYRIGHT 2010, 2012-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_uk.h + * Types and definitions that are common across OSs for both the user + * and kernel side of the User-Kernel interface. + */ + +#ifndef _UK_H_ +#define _UK_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @defgroup uk_api User-Kernel Interface API + * + * The User-Kernel Interface abstracts the communication mechanism between the user and kernel-side code of device + * drivers developed as part of the Midgard DDK. Currently that includes the Base driver and the UMP driver. + * + * It exposes an OS independent API to user-side code (UKU) which routes functions calls to an OS-independent + * kernel-side API (UKK) via an OS-specific communication mechanism. + * + * This API is internal to the Midgard DDK and is not exposed to any applications. + * + * @{ + */ + +/** + * These are identifiers for kernel-side drivers implementing a UK interface, aka UKK clients. The + * UK module maps this to an OS specific device name, e.g. "gpu_base" -> "GPU0:". Specify this + * identifier to select a UKK client to the uku_open() function. + * + * When a new UKK client driver is created a new identifier needs to be added to the uk_client_id + * enumeration and the uku_open() implemenation for the various OS ports need to be updated to + * provide a mapping of the identifier to the OS specific device name. + * + */ +enum uk_client_id { + /** + * Value used to identify the Base driver UK client. + */ + UK_CLIENT_MALI_T600_BASE, + + /** The number of uk clients supported. This must be the last member of the enum */ + UK_CLIENT_COUNT +}; + +/** + * Each function callable through the UK interface has a unique number. + * Functions provided by UK clients start from number UK_FUNC_ID. + * Numbers below UK_FUNC_ID are used for internal UK functions. + */ +enum uk_func { + UKP_FUNC_ID_CHECK_VERSION, /**< UKK Core internal function */ + /** + * Each UK client numbers the functions they provide starting from + * number UK_FUNC_ID. This number is then eventually assigned to the + * id field of the union uk_header structure when preparing to make a + * UK call. See your UK client for a list of their function numbers. + */ + UK_FUNC_ID = 512 +}; + +/** + * Arguments for a UK call are stored in a structure. This structure consists + * of a fixed size header and a payload. The header carries a 32-bit number + * identifying the UK function to be called (see uk_func). When the UKK client + * receives this header and executed the requested UK function, it will use + * the same header to store the result of the function in the form of a + * int return code. The size of this structure is such that the + * first member of the payload following the header can be accessed efficiently + * on a 32 and 64-bit kernel and the structure has the same size regardless + * of a 32 or 64-bit kernel. The uk_kernel_size_type type should be defined + * accordingly in the OS specific mali_uk_os.h header file. + */ +union uk_header { + /** + * 32-bit number identifying the UK function to be called. + * Also see uk_func. + */ + u32 id; + /** + * The int return code returned by the called UK function. + * See the specification of the particular UK function you are + * calling for the meaning of the error codes returned. All + * UK functions return 0 on success. + */ + u32 ret; + /* + * Used to ensure 64-bit alignment of this union. Do not remove. + * This field is used for padding and does not need to be initialized. + */ + u64 sizer; +}; + +/** + * This structure carries a 16-bit major and minor number and is sent along with an internal UK call + * used during uku_open to identify the versions of the UK module in use by the user-side and kernel-side. + */ +struct uku_version_check_args { + union uk_header header; + /**< UK call header */ + u16 major; + /**< This field carries the user-side major version on input and the kernel-side major version on output */ + u16 minor; + /**< This field carries the user-side minor version on input and the kernel-side minor version on output. */ + u8 padding[4]; +}; + +/** @} end group uk_api */ + +/** @} *//* end group base_api */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _UK_H_ */ diff --git a/drivers/gpu/arm/bifrost/platform/Kconfig b/drivers/gpu/arm/bifrost/platform/Kconfig new file mode 100644 index 000000000000..38835d3d1531 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/Kconfig @@ -0,0 +1,24 @@ +# +# (C) COPYRIGHT 2012-2013, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +# Add your platform specific Kconfig file here +# +# "drivers/gpu/arm/midgard/platform/xxx/Kconfig" +# +# Where xxx is the platform name is the name set in MALI_PLATFORM_NAME +# + diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild b/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild new file mode 100644 index 000000000000..d40d7982ff04 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +mali_kbase-y += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_devicetree.o \ + $(MALI_PLATFORM_DIR)/mali_kbase_runtime_pm.o diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_devicetree.c b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_devicetree.c new file mode 100644 index 000000000000..29ccc29e4125 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_devicetree.c @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT 2015, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + +static struct kbase_platform_config dummy_platform_config; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &dummy_platform_config; +} + +int kbase_platform_register(void) +{ + return 0; +} + +void kbase_platform_unregister(void) +{ +} diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h new file mode 100644 index 000000000000..2ceca34945b9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h @@ -0,0 +1,80 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX (5000) +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN (5000) + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (NULL) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; + +/** + * Autosuspend delay + * + * The delay time (in milliseconds) to be used for autosuspend + */ +#define AUTO_SUSPEND_DELAY (100) diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c new file mode 100644 index 000000000000..9fe37c8d835e --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c @@ -0,0 +1,121 @@ +/* + * + * (C) COPYRIGHT 2015, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include "mali_kbase_config_platform.h" + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret = 1; /* Assume GPU has been powered off */ + int error; + + dev_dbg(kbdev->dev, "pm_callback_power_on %p\n", + (void *)kbdev->dev->pm_domain); + + error = pm_runtime_get_sync(kbdev->dev); + if (error == 1) { + /* + * Let core know that the chip has not been + * powered off, so we can save on re-initialization. + */ + ret = 0; + } + + dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error); + + return ret; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ + dev_dbg(kbdev->dev, "pm_callback_power_off\n"); + + pm_runtime_mark_last_busy(kbdev->dev); + pm_runtime_put_autosuspend(kbdev->dev); +} + +int kbase_device_runtime_init(struct kbase_device *kbdev) +{ + int ret = 0; + + dev_dbg(kbdev->dev, "kbase_device_runtime_init\n"); + + pm_runtime_set_autosuspend_delay(kbdev->dev, AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(kbdev->dev); + + pm_runtime_set_active(kbdev->dev); + pm_runtime_enable(kbdev->dev); + + if (!pm_runtime_enabled(kbdev->dev)) { + dev_warn(kbdev->dev, "pm_runtime not enabled"); + ret = -ENOSYS; + } + + return ret; +} + +void kbase_device_runtime_disable(struct kbase_device *kbdev) +{ + dev_dbg(kbdev->dev, "kbase_device_runtime_disable\n"); + pm_runtime_disable(kbdev->dev); +} + +static int pm_callback_runtime_on(struct kbase_device *kbdev) +{ + dev_dbg(kbdev->dev, "pm_callback_runtime_on\n"); + + return 0; +} + +static void pm_callback_runtime_off(struct kbase_device *kbdev) +{ + dev_dbg(kbdev->dev, "pm_callback_runtime_off\n"); +} + +static void pm_callback_resume(struct kbase_device *kbdev) +{ + int ret = pm_callback_runtime_on(kbdev); + + WARN_ON(ret); +} + +static void pm_callback_suspend(struct kbase_device *kbdev) +{ + pm_callback_runtime_off(kbdev); +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = pm_callback_suspend, + .power_resume_callback = pm_callback_resume, +#ifdef KBASE_PM_RUNTIME + .power_runtime_init_callback = kbase_device_runtime_init, + .power_runtime_term_callback = kbase_device_runtime_disable, + .power_runtime_on_callback = pm_callback_runtime_on, + .power_runtime_off_callback = pm_callback_runtime_off, +#else /* KBASE_PM_RUNTIME */ + .power_runtime_init_callback = NULL, + .power_runtime_term_callback = NULL, + .power_runtime_on_callback = NULL, + .power_runtime_off_callback = NULL, +#endif /* KBASE_PM_RUNTIME */ +}; + + diff --git a/drivers/gpu/arm/bifrost/platform/mali_kbase_platform_common.h b/drivers/gpu/arm/bifrost/platform/mali_kbase_platform_common.h new file mode 100644 index 000000000000..7cb3be7f78ce --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/mali_kbase_platform_common.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @brief Entry point to transfer control to a platform for early initialization + * + * This function is called early on in the initialization during execution of + * @ref kbase_driver_init. + * + * @return Zero to indicate success non-zero for failure. + */ +int kbase_platform_early_init(void); diff --git a/drivers/gpu/arm/bifrost/platform/vexpress/Kbuild b/drivers/gpu/arm/bifrost/platform/vexpress/Kbuild new file mode 100644 index 000000000000..d9d5e9085231 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress/Kbuild @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2012-2013, 2016-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +mali_kbase-y += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \ + $(MALI_PLATFORM_DIR)/mali_kbase_cpu_vexpress.o \ + mali_kbase_platform_fake.o diff --git a/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_platform.h new file mode 100644 index 000000000000..02835f129aa3 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_platform.h @@ -0,0 +1,75 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase_cpu_vexpress.h" + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX kbase_get_platform_max_freq() +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN kbase_get_platform_min_freq() + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_get_vexpress_cpu_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_vexpress.c b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_vexpress.c new file mode 100644 index 000000000000..15ce2bc5eea5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_config_vexpress.c @@ -0,0 +1,85 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" +#include "mali_kbase_config_platform.h" + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.c b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.c new file mode 100644 index 000000000000..4665f98cbbe4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.c @@ -0,0 +1,279 @@ +/* + * + * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +/* the following three values used for reading + * HBI value of the LogicTile daughterboard */ +#define VE_MOTHERBOARD_PERIPHERALS_SMB_CS7 (0x10000000) +#define VE_SYS_PROC_ID1_OFFSET (0x00000088) +#define VE_LOGIC_TILE_HBI_MASK (0x00000FFF) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1<> + FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[10:7] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << + FCLK_PB_DIVIDE_BIT_SHIFT)) >> + FCLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 1)) { + /* CFGRW0[1] - CLKOC */ + /* CFGRW0[6:3] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << + FCLK_PA_DIVIDE_BIT_SHIFT)) >> + FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[14:11] */ + pc_divide = ((reg_val & (FEED_REG_BIT_MASK << + FCLK_PC_DIVIDE_BIT_SHIFT)) >> + FCLK_PC_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 2)) { + /* CFGRW0[2] - FACLK */ + /* CFGRW0[18:15] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << + AXICLK_PA_DIVIDE_BIT_SHIFT)) >> + AXICLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[22:19] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << + AXICLK_PB_DIVIDE_BIT_SHIFT)) >> + AXICLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + err = -EIO; + } + +set_reg_error: +ongoing_request: + raw_spin_unlock(&syscfg_lock); + *cpu_clock /= HZ_IN_MHZ; + + if (!err) + cpu_clock_speed = *cpu_clock; + + iounmap(scc_reg); + +scc_reg_map_failed: + iounmap(syscfg_reg); + +syscfg_reg_map_failed: + + return err; +} + +/** + * kbase_get_platform_logic_tile_type - determines which LogicTile type + * is used by Versatile Express + * + * When platform_config build parameter is specified as vexpress, i.e., + * platform_config=vexpress, GPU frequency may vary dependent on the + * particular platform. The GPU frequency depends on the LogicTile type. + * + * This function determines which LogicTile type is used by the platform by + * reading the HBI value of the daughterboard which holds the LogicTile: + * + * 0x217 HBI0217 Virtex-6 + * 0x192 HBI0192 Virtex-5 + * 0x247 HBI0247 Virtex-7 + * + * Return: HBI value of the logic tile daughterboard, zero if not accessible + */ +static u32 kbase_get_platform_logic_tile_type(void) +{ + void __iomem *syscfg_reg = NULL; + u32 sys_procid1 = 0; + + syscfg_reg = ioremap(VE_MOTHERBOARD_PERIPHERALS_SMB_CS7 + VE_SYS_PROC_ID1_OFFSET, 4); + if (NULL != syscfg_reg) { + sys_procid1 = readl(syscfg_reg); + iounmap(syscfg_reg); + } + + return sys_procid1 & VE_LOGIC_TILE_HBI_MASK; +} + +u32 kbase_get_platform_min_freq(void) +{ + u32 ve_logic_tile = kbase_get_platform_logic_tile_type(); + + switch (ve_logic_tile) { + case 0x217: + /* Virtex 6, HBI0217 */ + return VE_VIRTEX6_GPU_FREQ_MIN; + case 0x247: + /* Virtex 7, HBI0247 */ + return VE_VIRTEX7_GPU_FREQ_MIN; + default: + /* all other logic tiles, i.e., Virtex 5 HBI0192 + * or unsuccessful reading from the platform - + * fall back to some default value */ + return VE_DEFAULT_GPU_FREQ_MIN; + } +} + +u32 kbase_get_platform_max_freq(void) +{ + u32 ve_logic_tile = kbase_get_platform_logic_tile_type(); + + switch (ve_logic_tile) { + case 0x217: + /* Virtex 6, HBI0217 */ + return VE_VIRTEX6_GPU_FREQ_MAX; + case 0x247: + /* Virtex 7, HBI0247 */ + return VE_VIRTEX7_GPU_FREQ_MAX; + default: + /* all other logic tiles, i.e., Virtex 5 HBI0192 + * or unsuccessful reading from the platform - + * fall back to some default value */ + return VE_DEFAULT_GPU_FREQ_MAX; + } +} diff --git a/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.h b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.h new file mode 100644 index 000000000000..da865698133a --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress/mali_kbase_cpu_vexpress.h @@ -0,0 +1,38 @@ +/* + * + * (C) COPYRIGHT 2012-2013, 2015-2016 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_CPU_VEXPRESS_H_ +#define _KBASE_CPU_VEXPRESS_H_ + +/** + * Versatile Express implementation of @ref kbase_cpu_clk_speed_func. + */ +int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock); + +/** + * Get the minimum GPU frequency for the attached logic tile + */ +u32 kbase_get_platform_min_freq(void); + +/** + * Get the maximum GPU frequency for the attached logic tile + */ +u32 kbase_get_platform_max_freq(void); + +#endif /* _KBASE_CPU_VEXPRESS_H_ */ diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/Kbuild b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/Kbuild new file mode 100644 index 000000000000..df87c74f43ba --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2013-2014, 2016-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +mali_kbase-y += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \ + mali_kbase_platform_fake.o diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h new file mode 100644 index 000000000000..0efbf3962f98 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 5000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 5000 + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_cpuprops_get_default_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c new file mode 100644 index 000000000000..3ff0930fb4a3 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c @@ -0,0 +1,79 @@ +/* + * + * (C) COPYRIGHT 2011-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0x2f010000, + .end = 0x2f010000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/Kbuild b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/Kbuild new file mode 100644 index 000000000000..d9d5e9085231 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/Kbuild @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2012-2013, 2016-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +mali_kbase-y += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \ + $(MALI_PLATFORM_DIR)/mali_kbase_cpu_vexpress.o \ + mali_kbase_platform_fake.o diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h new file mode 100644 index 000000000000..dbdf21e009f9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h @@ -0,0 +1,75 @@ +/* + * + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase_cpu_vexpress.h" + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 10000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 10000 + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_get_vexpress_cpu_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c new file mode 100644 index 000000000000..76ffe4a1e59e --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c @@ -0,0 +1,83 @@ +/* + * + * (C) COPYRIGHT 2011-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 75, + .mmu_irq_number = 76, + .gpu_irq_number = 77, + .io_memory_region = { + .start = 0x2F000000, + .end = 0x2F000000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + diff --git a/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c new file mode 100644 index 000000000000..816dff49835f --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1< + +/** + * @addtogroup uk_api User-Kernel Interface API + * @{ + */ + +/** + * @addtogroup uk_api_kernel UKK (Kernel side) + * @{ + */ + +/** + * Internal OS specific data structure associated with each UKK session. Part + * of a ukk_session object. + */ +typedef struct ukkp_session { + int dummy; /**< No internal OS specific data at this time */ +} ukkp_session; + +/** @} end group uk_api_kernel */ + +/** @} end group uk_api */ + +#endif /* _UKK_OS_H__ */ diff --git a/drivers/gpu/arm/bifrost/protected_mode_switcher.h b/drivers/gpu/arm/bifrost/protected_mode_switcher.h new file mode 100644 index 000000000000..5dc2f3ba8cf6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/protected_mode_switcher.h @@ -0,0 +1,64 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _PROTECTED_MODE_SWITCH_H_ +#define _PROTECTED_MODE_SWITCH_H_ + +struct protected_mode_device; + +/** + * struct protected_mode_ops - Callbacks for protected mode switch operations + * + * @protected_mode_enable: Callback to enable protected mode for device + * @protected_mode_disable: Callback to disable protected mode for device + */ +struct protected_mode_ops { + /** + * protected_mode_enable() - Enable protected mode on device + * @dev: The struct device + * + * Return: 0 on success, non-zero on error + */ + int (*protected_mode_enable)( + struct protected_mode_device *protected_dev); + + /** + * protected_mode_disable() - Disable protected mode on device, and + * reset device + * @dev: The struct device + * + * Return: 0 on success, non-zero on error + */ + int (*protected_mode_disable)( + struct protected_mode_device *protected_dev); +}; + +/** + * struct protected_mode_device - Device structure for protected mode devices + * + * @ops - Callbacks associated with this device + * @data - Pointer to device private data + * + * This structure should be registered with the platform device using + * platform_set_drvdata(). + */ +struct protected_mode_device { + struct protected_mode_ops ops; + void *data; +}; + +#endif /* _PROTECTED_MODE_SWITCH_H_ */ diff --git a/drivers/gpu/arm/bifrost/sconscript b/drivers/gpu/arm/bifrost/sconscript new file mode 100644 index 000000000000..e738dd7a3869 --- /dev/null +++ b/drivers/gpu/arm/bifrost/sconscript @@ -0,0 +1,72 @@ +# +# (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import sys +Import('env') + +SConscript( 'tests/sconscript' ) + +mock_test = 0 + +# Source files required for kbase. +kbase_src = [ + Glob('*.c'), + Glob('backend/*/*.c'), + Glob('internal/*/*.c'), + Glob('ipa/*.c'), + Glob('platform/%s/*.c' % env['platform_config']), +] + +if env['platform_config']=='juno_soc': + kbase_src += [Glob('platform/devicetree/*.c')] +else: + kbase_src += [Glob('platform/%s/*.c' % env['platform_config'])] + +if Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock') and env['unit'] == '1': + kbase_src += [Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock/*.c')] + mock_test = 1 + +make_args = env.kernel_get_config_defines(ret_list = True) + [ + 'PLATFORM=%s' % env['platform'], + 'MALI_ERROR_INJECT_ON=%s' % env['error_inject'], + 'MALI_KERNEL_TEST_API=%s' % env['debug'], + 'MALI_UNIT_TEST=%s' % env['unit'], + 'MALI_RELEASE_NAME=%s' % env['mali_release_name'], + 'MALI_MOCK_TEST=%s' % mock_test, + 'MALI_CUSTOMER_RELEASE=%s' % env['release'], + 'MALI_INSTRUMENTATION_LEVEL=%s' % env['instr'], + 'MALI_COVERAGE=%s' % env['coverage'], +] + +kbase = env.BuildKernelModule('$STATIC_LIB_PATH/mali_kbase.ko', kbase_src, + make_args = make_args) + +# Add a dependency on kds.ko. +# Only necessary when KDS is not built into the kernel. +# +if env['os'] != 'android': + if not env.KernelConfigEnabled("CONFIG_KDS"): + env.Depends(kbase, '$STATIC_LIB_PATH/kds.ko') + +# need Module.symvers from ump.ko build +if int(env['ump']) == 1: + env.Depends(kbase, '$STATIC_LIB_PATH/ump.ko') + +if 'smc_protected_mode_switcher' in env: + env.Depends('$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/smc_protected_mode_switcher.ko') + +env.KernelObjTarget('kbase', kbase) + +env.AppendUnique(BASE=['cutils_linked_list']) diff --git a/drivers/gpu/arm/bifrost/tests/Kbuild b/drivers/gpu/arm/bifrost/tests/Kbuild new file mode 100644 index 000000000000..b4bed0473439 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/Kbuild @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +obj-$(CONFIG_MALI_KUTF) += kutf/ +obj-$(CONFIG_MALI_IRQ_LATENCY) += mali_kutf_irq_test/ diff --git a/drivers/gpu/arm/bifrost/tests/Kconfig b/drivers/gpu/arm/bifrost/tests/Kconfig new file mode 100644 index 000000000000..da0515c065de --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/Kconfig @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +source "drivers/gpu/arm/midgard/tests/kutf/Kconfig" +source "drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig" diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers.h new file mode 100644 index 000000000000..3f1dfc244d30 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers.h @@ -0,0 +1,216 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_HELPERS_H_ +#define _KERNEL_UTF_HELPERS_H_ + +/* kutf_helpers.h + * Test helper functions for the kernel UTF test infrastructure. + * + * This collection of helper functions are provided as 'stock' implementation + * helpers for certain features of kutf. Tests can implement common/boilerplate + * functionality using these, whilst still providing them the option of + * implementing completely custom functions themselves to use those kutf + * features. + */ + +#include +#include +#include + +/** + * enum kutf_helper_textbuf_flag - flags for textbufs + * @KUTF_HELPER_TEXTBUF_FLAG_DYING: Test is dying, textbuf should not allow + * writes, nor block on empty. + */ +enum kutf_helper_textbuf_flag { + KUTF_HELPER_TEXTBUF_FLAG_DYING = (1u << 0), +}; + +/** + * struct kutf_helper_textbuf_line - Structure representing a line of text + * + * The string itself is stored immediately after this. + * + * @node: List node for the textbuf's textbuf_list + * @str_size: Length of the string buffer, including the \0 terminator + * @str: 'Flexible array' for the string representing the line + */ +struct kutf_helper_textbuf_line { + struct list_head node; + int str_size; + char str[]; +}; + +/** + * struct kutf_helper_textbuf - Structure to representing sequential lines of + * text + * @lock: mutex to hold whilst accessing the structure + * @nr_user_clients: Number of userspace clients connected via an open() + * call + * @mempool: mempool for allocating lines + * @scratchpad: scratch area for receiving text of size max_line_size + * @used_bytes: number of valid bytes in the scratchpad + * @prev_pos: Previous position userspace has accessed + * @prev_line_pos: Previous start of line position userspace has accessed + * @textbuf_list: List head to store all the lines of text + * @max_line_size: Maximum size in memory allowed for a line of text + * @max_nr_lines: Maximum number of lines permitted in this textbuf + * @nr_lines: Number of entries in textbuf_list + * @flags: Flags indicating state of the textbuf, using values + * from enum kutf_helper_textbuf_flag + * @user_opened_wq: Waitq for when there's at least one userspace client + * connected to the textbuf via an open() call + * @not_full_wq: Waitq for when the textbuf can be enqueued into/can + * consume data from userspace + * @not_empty_wq: Waitq for when the textbuf can be dequeued from/can + * produce data for userspace + */ + +struct kutf_helper_textbuf { + struct mutex lock; + int nr_user_clients; + struct kutf_mempool *mempool; + char *scratchpad; + int used_bytes; + loff_t prev_pos; + loff_t prev_line_pos; + struct list_head textbuf_list; + int max_line_size; + int max_nr_lines; + int nr_lines; + unsigned long flags; + wait_queue_head_t user_opened_wq; + wait_queue_head_t not_full_wq; + wait_queue_head_t not_empty_wq; + +}; + +/* stock callbacks for userspace to read from/write to the 'data' file as a + * textbuf */ +extern struct kutf_userdata_ops kutf_helper_textbuf_userdata_ops; + +/** + * kutf_helper_textbuf_init() - init a textbuf for use as a 'data' file + * consumer/producer + * @textbuf: textbuf to initialize + * @mempool: mempool to allocate from + * @max_line_size: maximum line size expected to/from userspace + * @max_nr_lines: maximum number of lines to expect to/from userspace + * + * Initialize a textbuf so that it can consume writes made to the 'data' file, + * and produce reads for userspace on the 'data' file. Tests may then read the + * lines written by userspace, or fill the buffer so it may be read back by + * userspace. + * + * The caller should write the @textbuf pointer into the kutf_context's + * userdata_producer_priv or userdata_consumer_priv member during fixture + * creation. + * + * Usually a test will have separate textbufs for userspace to write to and + * read from. Using the same one for both will echo back to the user what they + * are writing. + * + * Lines are understood as being separated by the '\n' character, but no '\n' + * characters will be observed by the test + * + * @max_line_size puts an upper bound on the size of lines in a textbuf, + * including the \0 terminator. Lines exceeding this will be truncated, + * effectively ignoring incoming data until the next '\n' + * + * Combining this with @max_nr_lines puts an upper bound on the size of the + * file read in + * + * Return: 0 on success, or negative value on error. + */ +int kutf_helper_textbuf_init(struct kutf_helper_textbuf *textbuf, + struct kutf_mempool *mempool, int max_line_size, + int max_nr_lines); + +/** + * kutf_helper_textbuf_wait_for_user() - wait for userspace to open the 'data' + * file + * @textbuf: textbuf to wait on + * + * This can be used to synchronize with userspace so that subsequent calls to + * kutf_helper_textbuf_dequeue() and kutf_helper_textbuf_enqueue() should + * succeed. + * + * Waiting is done on a timeout. + * + * There is of course no guarantee that userspace will keep the file open after + * this, but any error in the dequeue/enqueue functions afterwards can be + * treated as such rather than "we're still waiting for userspace to begin" + * + * Return: 0 if waited successfully, -ETIMEDOUT if we exceeded the + * timeout, or some other negative value if there was an + * error during waiting. + */ + +int kutf_helper_textbuf_wait_for_user(struct kutf_helper_textbuf *textbuf); + + +/** + * kutf_helper_textbuf_dequeue() - dequeue a line from a textbuf + * @textbuf: textbuf dequeue a line as a string from + * @str_size: pointer to storage to receive the size of the string, + * which includes the '\0' terminator, or NULL if not + * required + * + * Dequeue (remove) a line from the start of the textbuf as a string, and + * return it. + * + * If no lines are available, then this will block until a line has been + * submitted. If a userspace client is not connected and there are no remaining + * lines, then this function returns NULL instead. + * + * The memory for the string comes from the kutf_mempool given during + * initialization of the textbuf, and shares the same lifetime as it. + * + * Return: pointer to the next line of the textbuf. NULL indicated + * all userspace clients disconnected. An error value to be + * checked with IS_ERR() family of functions if a signal or + * some other error occurred + */ +char *kutf_helper_textbuf_dequeue(struct kutf_helper_textbuf *textbuf, + int *str_size); + +/** + * kutf_helper_textbuf_enqueue() - enqueue a line to a textbuf + * @textbuf: textbuf to enqueue a line as a string to + * @enqueue_str: pointer to the string to enqueue to the textbuf + * @buf_max_size: maximum size of the buffer holding @enqueue_str + * + * Enqueue (add) a line to the end of a textbuf as a string. + * + * The caller should avoid placing '\n' characters in their strings, as these + * will not be split into multiple lines. + * + * A copy of the string will be made into the textbuf, so @enqueue_str can be + * freed immediately after if.the caller wishes to do so. + * + * If the maximum amount of lines has been reached, then this will block until + * a line has been removed to make space. If a userspace client is not + * connected and there is no space available, then this function returns + * -EBUSY. + * + * Return: 0 on success, or negative value on error + */ +int kutf_helper_textbuf_enqueue(struct kutf_helper_textbuf *textbuf, + char *enqueue_str, int buf_max_size); + +#endif /* _KERNEL_UTF_HELPERS_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers_user.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers_user.h new file mode 100644 index 000000000000..759bf717c7cd --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_helpers_user.h @@ -0,0 +1,179 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_HELPERS_USER_H_ +#define _KERNEL_UTF_HELPERS_USER_H_ + +/* kutf_helpers.h + * Test helper functions for the kernel UTF test infrastructure, whose + * implementation mirrors that of similar functions for kutf-userside + */ + +#include +#include + + +#define KUTF_HELPER_MAX_VAL_NAME_LEN 255 + +enum kutf_helper_valtype { + KUTF_HELPER_VALTYPE_INVALID, + KUTF_HELPER_VALTYPE_U64, + KUTF_HELPER_VALTYPE_STR, + + KUTF_HELPER_VALTYPE_COUNT /* Must be last */ +}; + +struct kutf_helper_named_val { + enum kutf_helper_valtype type; + char *val_name; + union { + u64 val_u64; + char *val_str; + } u; +}; + +/* Extra error values for certain helpers when we want to distinguish between + * Linux's own error values too. + * + * These can only be used on certain functions returning an int type that are + * documented as returning one of these potential values, they cannot be used + * from functions return a ptr type, since we can't decode it with PTR_ERR + * + * No negative values are used - Linux error codes should be used instead, and + * indicate a problem in accessing the data file itself (are generally + * unrecoverable) + * + * Positive values indicate correct access but invalid parsing (can be + * recovered from assuming data in the future is correct) */ +enum kutf_helper_err { + /* No error - must be zero */ + KUTF_HELPER_ERR_NONE = 0, + /* Named value parsing encountered an invalid name */ + KUTF_HELPER_ERR_INVALID_NAME, + /* Named value parsing of string or u64 type encountered extra + * characters after the value (after the last digit for a u64 type or + * after the string end delimiter for string type) */ + KUTF_HELPER_ERR_CHARS_AFTER_VAL, + /* Named value parsing of string type couldn't find the string end + * delimiter. + * + * This cannot be encountered when the NAME="value" message exceeds the + * textbuf's maximum line length, because such messages are not checked + * for an end string delimiter */ + KUTF_HELPER_ERR_NO_END_DELIMITER, + /* Named value didn't parse as any of the known types */ + KUTF_HELPER_ERR_INVALID_VALUE, +}; + + +/* textbuf Send named NAME=value pair, u64 value + * + * NAME must match [A-Z0-9_]\+ and can be up to MAX_VAL_NAME_LEN characters long + * + * This is assuming the kernel-side test is using the 'textbuf' helpers + * + * Any failure will be logged on the suite's current test fixture + * + * Returns 0 on success, non-zero on failure + */ +int kutf_helper_textbuf_send_named_u64(struct kutf_context *context, + struct kutf_helper_textbuf *textbuf, char *val_name, u64 val); + +/* Get the maximum length of a string that can be represented as a particular + * NAME="value" pair without string-value truncation in the kernel's buffer + * + * Given val_name and the kernel buffer's size, this can be used to determine + * the maximum length of a string that can be sent as val_name="value" pair + * without having the string value truncated. Any string longer than this will + * be truncated at some point during communication to this size. + * + * The calculation is valid both for sending strings of val_str_len to kernel, + * and for receiving a string that was originally val_str_len from the kernel. + * + * It is assumed that valname is a valid name for + * kutf_test_helpers_textbuf_send_named_str(), and no checking will be made to + * ensure this. + * + * Returns the maximum string length that can be represented, or a negative + * value if the NAME="value" encoding itself wouldn't fit in kern_buf_sz + */ +int kutf_helper_textbuf_max_str_len_for_kern(char *val_name, int kern_buf_sz); + +/* textbuf Send named NAME="str" pair + * + * no escaping allowed in str. Any of the following characters will terminate + * the string: '"' '\\' '\n' + * + * NAME must match [A-Z0-9_]\+ and can be up to MAX_VAL_NAME_LEN characters long + * + * This is assuming the kernel-side test is using the 'textbuf' helpers + * + * Any failure will be logged on the suite's current test fixture + * + * Returns 0 on success, non-zero on failure */ +int kutf_helper_textbuf_send_named_str(struct kutf_context *context, + struct kutf_helper_textbuf *textbuf, char *val_name, + char *val_str); + +/* textbuf Receive named NAME=value pair + * + * This can receive u64 and string values - check named_val->type + * + * If you are not planning on dynamic handling of the named value's name and + * type, then kutf_test_helpers_textbuf_receive_check_val() is more useful as a + * convenience function. + * + * String members of named_val will come from memory allocated on the fixture's mempool + * + * Returns 0 on success. Negative value on failure to receive from the 'data' + * file, positive value indicates an enum kutf_helper_err value for correct + * reception of data but invalid parsing */ +int kutf_helper_textbuf_receive_named_val(struct kutf_helper_named_val *named_val, + struct kutf_helper_textbuf *textbuf); + +/* textbuf Receive and validate NAME=value pair + * + * As with kutf_test_helpers_textbuf_receive_named_val, but validate that the + * name and type are as expected, as a convenience for a common pattern found + * in tests. + * + * NOTE: this only returns an error value if there was actually a problem + * receiving data. + * + * NOTE: If the underlying data was received correctly, but: + * - isn't of the expected name + * - isn't the expected type + * - isn't correctly parsed for the type + * then the following happens: + * - failure result is recorded + * - named_val->type will be KUTF_HELPER_VALTYPE_INVALID + * - named_val->u will contain some default value that should be relatively + * harmless for the test, including being writable in the case of string + * values + * - return value will be 0 to indicate success + * + * The rationale behind this is that we'd prefer to continue the rest of the + * test with failures propagated, rather than hitting a timeout */ +int kutf_helper_textbuf_receive_check_val(struct kutf_helper_named_val *named_val, + struct kutf_context *context, struct kutf_helper_textbuf *textbuf, + char *expect_val_name, enum kutf_helper_valtype expect_val_type); + +/* Output a named value to kmsg */ +void kutf_helper_output_named_val(struct kutf_helper_named_val *named_val); + + +#endif /* _KERNEL_UTF_HELPERS_USER_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_mem.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_mem.h new file mode 100644 index 000000000000..584c9dd4bc13 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_mem.h @@ -0,0 +1,68 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_MEM_H_ +#define _KERNEL_UTF_MEM_H_ + +/* kutf_mem.h + * Functions for management of memory pools in the kernel. + * + * This module implements a memory pool allocator, allowing a test + * implementation to allocate linked allocations which can then be freed by a + * single free which releases all of the resources held by the entire pool. + * + * Note that it is not possible to free single resources within the pool once + * allocated. + */ + +#include +#include + +/** + * struct kutf_mempool - the memory pool context management structure + * @head: list head on which the allocations in this context are added to + * @lock: mutex for concurrent allocation from multiple threads + * + */ +struct kutf_mempool { + struct list_head head; + struct mutex lock; +}; + +/** + * kutf_mempool_init() - Initialize a memory pool. + * @pool: Memory pool structure to initialize, provided by the user + * + * Return: zero on success + */ +int kutf_mempool_init(struct kutf_mempool *pool); + +/** + * kutf_mempool_alloc() - Allocate memory from a pool + * @pool: Memory pool to allocate from + * @size: Size of memory wanted in number of bytes + * + * Return: Pointer to memory on success, NULL on failure. + */ +void *kutf_mempool_alloc(struct kutf_mempool *pool, size_t size); + +/** + * kutf_mempool_destroy() - Destroy a memory pool, freeing all memory within it. + * @pool: The memory pool to free + */ +void kutf_mempool_destroy(struct kutf_mempool *pool); +#endif /* _KERNEL_UTF_MEM_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_resultset.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_resultset.h new file mode 100644 index 000000000000..1cc85f1b7a46 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_resultset.h @@ -0,0 +1,121 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_RESULTSET_H_ +#define _KERNEL_UTF_RESULTSET_H_ + +/* kutf_resultset.h + * Functions and structures for handling test results and result sets. + * + * This section of the kernel UTF contains structures and functions used for the + * management of Results and Result Sets. + */ + +/** + * enum kutf_result_status - Status values for a single Test error. + * @KUTF_RESULT_BENCHMARK: Result is a meta-result containing benchmark + * results. + * @KUTF_RESULT_SKIP: The test was skipped. + * @KUTF_RESULT_UNKNOWN: The test has an unknown result. + * @KUTF_RESULT_PASS: The test result passed. + * @KUTF_RESULT_DEBUG: The test result passed, but raised a debug + * message. + * @KUTF_RESULT_INFO: The test result passed, but raised + * an informative message. + * @KUTF_RESULT_WARN: The test result passed, but raised a warning + * message. + * @KUTF_RESULT_FAIL: The test result failed with a non-fatal error. + * @KUTF_RESULT_FATAL: The test result failed with a fatal error. + * @KUTF_RESULT_ABORT: The test result failed due to a non-UTF + * assertion failure. + * @KUTF_RESULT_COUNT: The current number of possible status messages. + */ +enum kutf_result_status { + KUTF_RESULT_BENCHMARK = -3, + KUTF_RESULT_SKIP = -2, + KUTF_RESULT_UNKNOWN = -1, + + KUTF_RESULT_PASS = 0, + KUTF_RESULT_DEBUG = 1, + KUTF_RESULT_INFO = 2, + KUTF_RESULT_WARN = 3, + KUTF_RESULT_FAIL = 4, + KUTF_RESULT_FATAL = 5, + KUTF_RESULT_ABORT = 6, + + KUTF_RESULT_COUNT +}; + +/* The maximum size of a kutf_result_status result when + * converted to a string + */ +#define KUTF_ERROR_MAX_NAME_SIZE 21 + +#ifdef __KERNEL__ + +#include + +/** + * struct kutf_result - Represents a single test result. + * @node: Next result in the list of results. + * @status: The status summary (pass / warn / fail / etc). + * @message: A more verbose status message. + */ +struct kutf_result { + struct list_head node; + enum kutf_result_status status; + const char *message; +}; + +/** + * kutf_create_result_set() - Create a new result set + * to which results can be added. + * + * Return: The created resultset. + */ +struct kutf_result_set *kutf_create_result_set(void); + +/** + * kutf_add_result() - Add a result to the end of an existing resultset. + * + * @mempool: The memory pool to allocate the result storage from. + * @set: The resultset to add the result to. + * @status: The result status to add. + * @message: The result message to add. + */ +void kutf_add_result(struct kutf_mempool *mempool, struct kutf_result_set *set, + enum kutf_result_status status, const char *message); + +/** + * kutf_remove_result() - Remove a result from the head of a resultset. + * @set: The resultset. + * + * Return: result or NULL if there are no further results in the resultset. + */ +struct kutf_result *kutf_remove_result( + struct kutf_result_set *set); + +/** + * kutf_destroy_result_set() - Free a previously created resultset. + * + * @results: The result set whose resources to free. + */ +void kutf_destroy_result_set(struct kutf_result_set *results); + +#endif /* __KERNEL__ */ + +#endif /* _KERNEL_UTF_RESULTSET_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_suite.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_suite.h new file mode 100644 index 000000000000..cba2b2d84d62 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_suite.h @@ -0,0 +1,568 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_SUITE_H_ +#define _KERNEL_UTF_SUITE_H_ + +/* kutf_suite.h + * Functions for management of test suites. + * + * This collection of data structures, macros, and functions are used to + * create Test Suites, Tests within those Test Suites, and Fixture variants + * of each test. + */ + +#include + +#include +#include + +/** + * Pseudo-flag indicating an absence of any specified test class. Note that + * tests should not be annotated with this constant as it is simply a zero + * value; tests without a more specific class must be marked with the flag + * KUTF_F_TEST_GENERIC. + */ +#define KUTF_F_TEST_NONE ((unsigned int)(0)) + +/** + * Class indicating this test is a smoke test. + * A given set of smoke tests should be quick to run, enabling rapid turn-around + * of "regress-on-commit" test runs. + */ +#define KUTF_F_TEST_SMOKETEST ((unsigned int)(1 << 1)) + +/** + * Class indicating this test is a performance test. + * These tests typically produce a performance metric, such as "time to run" or + * "frames per second", + */ +#define KUTF_F_TEST_PERFORMANCE ((unsigned int)(1 << 2)) + +/** + * Class indicating that this test is a deprecated test. + * These tests have typically been replaced by an alternative test which is + * more efficient, or has better coverage. + */ +#define KUTF_F_TEST_DEPRECATED ((unsigned int)(1 << 3)) + +/** + * Class indicating that this test is a known failure. + * These tests have typically been run and failed, but marking them as a known + * failure means it is easier to triage results. + * + * It is typically more convenient to triage known failures using the + * results database and web UI, as this means there is no need to modify the + * test code. + */ +#define KUTF_F_TEST_EXPECTED_FAILURE ((unsigned int)(1 << 4)) + +/** + * Class indicating that this test is a generic test, which is not a member of + * a more specific test class. Tests which are not created with a specific set + * of filter flags by the user are assigned this test class by default. + */ +#define KUTF_F_TEST_GENERIC ((unsigned int)(1 << 5)) + +/** + * Class indicating this test is a resource allocation failure test. + * A resource allocation failure test will test that an error code is + * correctly propagated when an allocation fails. + */ +#define KUTF_F_TEST_RESFAIL ((unsigned int)(1 << 6)) + +/** + * Additional flag indicating that this test is an expected failure when + * run in resource failure mode. These tests are never run when running + * the low resource mode. + */ +#define KUTF_F_TEST_EXPECTED_FAILURE_RF ((unsigned int)(1 << 7)) + +/** + * Flag reserved for user-defined filter zero. + */ +#define KUTF_F_TEST_USER_0 ((unsigned int)(1 << 24)) + +/** + * Flag reserved for user-defined filter one. + */ +#define KUTF_F_TEST_USER_1 ((unsigned int)(1 << 25)) + +/** + * Flag reserved for user-defined filter two. + */ +#define KUTF_F_TEST_USER_2 ((unsigned int)(1 << 26)) + +/** + * Flag reserved for user-defined filter three. + */ +#define KUTF_F_TEST_USER_3 ((unsigned int)(1 << 27)) + +/** + * Flag reserved for user-defined filter four. + */ +#define KUTF_F_TEST_USER_4 ((unsigned int)(1 << 28)) + +/** + * Flag reserved for user-defined filter five. + */ +#define KUTF_F_TEST_USER_5 ((unsigned int)(1 << 29)) + +/** + * Flag reserved for user-defined filter six. + */ +#define KUTF_F_TEST_USER_6 ((unsigned int)(1 << 30)) + +/** + * Flag reserved for user-defined filter seven. + */ +#define KUTF_F_TEST_USER_7 ((unsigned int)(1 << 31)) + +/** + * Pseudo-flag indicating that all test classes should be executed. + */ +#define KUTF_F_TEST_ALL ((unsigned int)(0xFFFFFFFFU)) + +/** + * union kutf_callback_data - Union used to store test callback data + * @ptr_value: pointer to the location where test callback data + * are stored + * @u32_value: a number which represents test callback data + */ +union kutf_callback_data { + void *ptr_value; + u32 u32_value; +}; + +/** + * struct kutf_userdata_ops- Structure defining methods to exchange data + * with userspace via the 'data' file + * @open: Function used to notify when the 'data' file was opened + * @release: Function used to notify when the 'data' file was closed + * @notify_ended: Function used to notify when the test has ended. + * @consumer: Function used to consume writes from userspace + * @producer: Function used to produce data for userspace to read + * + * All ops can be NULL. + */ +struct kutf_userdata_ops { + int (*open)(void *priv); + void (*release)(void *priv); + void (*notify_ended)(void *priv); + ssize_t (*consumer)(void *priv, const char __user *userbuf, + size_t userbuf_len, loff_t *ppos); + ssize_t (*producer)(void *priv, char __user *userbuf, + size_t userbuf_len, loff_t *ppos); +}; + +/** + * struct kutf_context - Structure representing a kernel test context + * @kref: Refcount for number of users of this context + * @suite: Convenience pointer to the suite this context + * is running + * @test_fix: The fixture that is being run in this context + * @fixture_pool: The memory pool used for the duration of + * the fixture/text context. + * @fixture: The user provided fixture structure. + * @fixture_index: The index (id) of the current fixture. + * @fixture_name: The name of the current fixture (or NULL if unnamed). + * @test_data: Any user private data associated with this test + * @result_set: All the results logged by this test context + * @status: The status of the currently running fixture. + * @expected_status: The expected status on exist of the currently + * running fixture. + * @userdata_consumer_priv: Parameter to pass into kutf_userdata_ops + * consumer function. Must not be NULL if a + * consumer function was specified + * @userdata_producer_priv: Parameter to pass into kutf_userdata_ops + * producer function. Must not be NULL if a + * producer function was specified + * @userdata_dentry: The debugfs file for userdata exchange + */ +struct kutf_context { + struct kref kref; + struct kutf_suite *suite; + struct kutf_test_fixture *test_fix; + struct kutf_mempool fixture_pool; + void *fixture; + unsigned int fixture_index; + const char *fixture_name; + union kutf_callback_data test_data; + struct kutf_result_set *result_set; + enum kutf_result_status status; + enum kutf_result_status expected_status; + void *userdata_consumer_priv; + void *userdata_producer_priv; + struct dentry *userdata_dentry; +}; + +/** + * struct kutf_suite - Structure representing a kernel test suite + * @app: The application this suite belongs to. + * @name: The name of this suite. + * @suite_data: Any user private data associated with this + * suite. + * @create_fixture: Function used to create a new fixture instance + * @remove_fixture: Function used to destroy a new fixture instance + * @fixture_variants: The number of variants (must be at least 1). + * @suite_default_flags: Suite global filter flags which are set on + * all tests. + * @node: List node for suite_list + * @dir: The debugfs directory for this suite + * @test_list: List head to store all the tests which are + * part of this suite + */ +struct kutf_suite { + struct kutf_application *app; + const char *name; + union kutf_callback_data suite_data; + void *(*create_fixture)(struct kutf_context *context); + void (*remove_fixture)(struct kutf_context *context); + unsigned int fixture_variants; + unsigned int suite_default_flags; + struct list_head node; + struct dentry *dir; + struct list_head test_list; +}; + +/* ============================================================================ + Application functions +============================================================================ */ + +/** + * kutf_create_application() - Create an in kernel test application. + * @name: The name of the test application. + * + * Return: pointer to the kutf_application on success or NULL + * on failure + */ +struct kutf_application *kutf_create_application(const char *name); + +/** + * kutf_destroy_application() - Destroy an in kernel test application. + * + * @app: The test application to destroy. + */ +void kutf_destroy_application(struct kutf_application *app); + +/* ============================================================================ + Suite functions +============================================================================ */ + +/** + * kutf_create_suite() - Create a kernel test suite. + * @app: The test application to create the suite in. + * @name: The name of the suite. + * @fixture_count: The number of fixtures to run over the test + * functions in this suite + * @create_fixture: Callback used to create a fixture. The returned value + * is stored in the fixture pointer in the context for + * use in the test functions. + * @remove_fixture: Callback used to remove a previously created fixture. + * + * Suite names must be unique. Should two suites with the same name be + * registered with the same application then this function will fail, if they + * are registered with different applications then the function will not detect + * this and the call will succeed. + * + * Return: pointer to the created kutf_suite on success or NULL + * on failure + */ +struct kutf_suite *kutf_create_suite( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context)); + +/** + * kutf_create_suite_with_filters() - Create a kernel test suite with user + * defined default filters. + * @app: The test application to create the suite in. + * @name: The name of the suite. + * @fixture_count: The number of fixtures to run over the test + * functions in this suite + * @create_fixture: Callback used to create a fixture. The returned value + * is stored in the fixture pointer in the context for + * use in the test functions. + * @remove_fixture: Callback used to remove a previously created fixture. + * @filters: Filters to apply to a test if it doesn't provide its own + * + * Suite names must be unique. Should two suites with the same name be + * registered with the same application then this function will fail, if they + * are registered with different applications then the function will not detect + * this and the call will succeed. + * + * Return: pointer to the created kutf_suite on success or NULL on failure + */ +struct kutf_suite *kutf_create_suite_with_filters( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context), + unsigned int filters); + +/** + * kutf_create_suite_with_filters_and_data() - Create a kernel test suite with + * user defined default filters. + * @app: The test application to create the suite in. + * @name: The name of the suite. + * @fixture_count: The number of fixtures to run over the test + * functions in this suite + * @create_fixture: Callback used to create a fixture. The returned value + * is stored in the fixture pointer in the context for + * use in the test functions. + * @remove_fixture: Callback used to remove a previously created fixture. + * @filters: Filters to apply to a test if it doesn't provide its own + * @suite_data: Suite specific callback data, provided during the + * running of the test in the kutf_context + * + * Return: pointer to the created kutf_suite on success or NULL + * on failure + */ +struct kutf_suite *kutf_create_suite_with_filters_and_data( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data suite_data); + +/** + * kutf_add_test() - Add a test to a kernel test suite. + * @suite: The suite to add the test to. + * @id: The ID of the test. + * @name: The name of the test. + * @execute: Callback to the test function to run. + * + * Note: As no filters are provided the test will use the suite filters instead + */ +void kutf_add_test(struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context)); + +/** + * kutf_add_test_with_filters() - Add a test to a kernel test suite with filters + * @suite: The suite to add the test to. + * @id: The ID of the test. + * @name: The name of the test. + * @execute: Callback to the test function to run. + * @filters: A set of filtering flags, assigning test categories. + */ +void kutf_add_test_with_filters(struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters); + +/** + * kutf_add_test_with_filters_and_data() - Add a test to a kernel test suite + * with filters. + * @suite: The suite to add the test to. + * @id: The ID of the test. + * @name: The name of the test. + * @execute: Callback to the test function to run. + * @filters: A set of filtering flags, assigning test categories. + * @test_data: Test specific callback data, provided during the + * running of the test in the kutf_context + */ +void kutf_add_test_with_filters_and_data( + struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data test_data); + +/** + * kutf_add_test_with_filters_data_and_userdata() - Add a test to a kernel test suite with filters and setup for + * receiving data from userside + * @suite: The suite to add the test to. + * @id: The ID of the test. + * @name: The name of the test. + * @execute: Callback to the test function to run. + * @filters: A set of filtering flags, assigning test categories. + * @test_data: Test specific callback data, provided during the + * running of the test in the kutf_context + * @userdata_ops: Callbacks to use for sending and receiving data to + * userspace. A copy of the struct kutf_userdata_ops is + * taken. Each callback can be NULL. + * + */ +void kutf_add_test_with_filters_data_and_userdata( + struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data test_data, + struct kutf_userdata_ops *userdata_ops); + + +/* ============================================================================ + Test functions +============================================================================ */ +/** + * kutf_test_log_result_external() - Log a result which has been created + * externally into a in a standard form + * recognized by the log parser. + * @context: The test context the test is running in + * @message: The message for this result + * @new_status: The result status of this log message + */ +void kutf_test_log_result_external( + struct kutf_context *context, + const char *message, + enum kutf_result_status new_status); + +/** + * kutf_test_expect_abort() - Tell the kernel that you expect the current + * fixture to produce an abort. + * @context: The test context this test is running in. + */ +void kutf_test_expect_abort(struct kutf_context *context); + +/** + * kutf_test_expect_fatal() - Tell the kernel that you expect the current + * fixture to produce a fatal error. + * @context: The test context this test is running in. + */ +void kutf_test_expect_fatal(struct kutf_context *context); + +/** + * kutf_test_expect_fail() - Tell the kernel that you expect the current + * fixture to fail. + * @context: The test context this test is running in. + */ +void kutf_test_expect_fail(struct kutf_context *context); + +/** + * kutf_test_expect_warn() - Tell the kernel that you expect the current + * fixture to produce a warning. + * @context: The test context this test is running in. + */ +void kutf_test_expect_warn(struct kutf_context *context); + +/** + * kutf_test_expect_pass() - Tell the kernel that you expect the current + * fixture to pass. + * @context: The test context this test is running in. + */ +void kutf_test_expect_pass(struct kutf_context *context); + +/** + * kutf_test_skip() - Tell the kernel that the test should be skipped. + * @context: The test context this test is running in. + */ +void kutf_test_skip(struct kutf_context *context); + +/** + * kutf_test_skip_msg() - Tell the kernel that this test has been skipped, + * supplying a reason string. + * @context: The test context this test is running in. + * @message: A message string containing the reason for the skip. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a prebaked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_skip_msg(struct kutf_context *context, const char *message); + +/** + * kutf_test_pass() - Tell the kernel that this test has passed. + * @context: The test context this test is running in. + * @message: A message string containing the reason for the pass. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_pass(struct kutf_context *context, char const *message); + +/** + * kutf_test_debug() - Send a debug message + * @context: The test context this test is running in. + * @message: A message string containing the debug information. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_debug(struct kutf_context *context, char const *message); + +/** + * kutf_test_info() - Send an information message + * @context: The test context this test is running in. + * @message: A message string containing the information message. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_info(struct kutf_context *context, char const *message); + +/** + * kutf_test_warn() - Send a warning message + * @context: The test context this test is running in. + * @message: A message string containing the warning message. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_warn(struct kutf_context *context, char const *message); + +/** + * kutf_test_fail() - Tell the kernel that a test has failed + * @context: The test context this test is running in. + * @message: A message string containing the failure message. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_fail(struct kutf_context *context, char const *message); + +/** + * kutf_test_fatal() - Tell the kernel that a test has triggered a fatal error + * @context: The test context this test is running in. + * @message: A message string containing the fatal error message. + * + * Note: The message must not be freed during the lifetime of the test run. + * This means it should either be a pre-baked string, or if a dynamic string + * is required it must be created with kutf_dsprintf which will store + * the resultant string in a buffer who's lifetime is the same as the test run. + */ +void kutf_test_fatal(struct kutf_context *context, char const *message); + +/** + * kutf_test_abort() - Tell the kernel that a test triggered an abort in the test + * + * @context: The test context this test is running in. + */ +void kutf_test_abort(struct kutf_context *context); + +#endif /* _KERNEL_UTF_SUITE_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_utils.h b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_utils.h new file mode 100644 index 000000000000..c458c1f73802 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/include/kutf/kutf_utils.h @@ -0,0 +1,55 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KERNEL_UTF_UTILS_H_ +#define _KERNEL_UTF_UTILS_H_ + +/* kutf_utils.h + * Utilities for the kernel UTF test infrastructure. + * + * This collection of library functions are provided for use by kernel UTF + * and users of kernel UTF which don't directly fit within the other + * code modules. + */ + +#include + +/** + * Maximum size of the message strings within kernel UTF, messages longer then + * this will be truncated. + */ +#define KUTF_MAX_DSPRINTF_LEN 1024 + +/** + * kutf_dsprintf() - dynamic sprintf + * @pool: memory pool to allocate from + * @fmt: The format string describing the string to document. + * @... The parameters to feed in to the format string. + * + * This function implements sprintf which dynamically allocates memory to store + * the string. The library will free the memory containing the string when the + * result set is cleared or destroyed. + * + * Note The returned string may be truncated to fit an internal temporary + * buffer, which is KUTF_MAX_DSPRINTF_LEN bytes in length. + * + * Return: Returns pointer to allocated string, or NULL on error. + */ +const char *kutf_dsprintf(struct kutf_mempool *pool, + const char *fmt, ...); + +#endif /* _KERNEL_UTF_UTILS_H_ */ diff --git a/drivers/gpu/arm/bifrost/tests/kutf/Kbuild b/drivers/gpu/arm/bifrost/tests/kutf/Kbuild new file mode 100644 index 000000000000..97f80057224f --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/Kbuild @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ccflags-y += -I$(src)/../include + +obj-$(CONFIG_MALI_KUTF) += kutf.o + +kutf-y := kutf_mem.o kutf_resultset.o kutf_suite.o kutf_utils.o kutf_helpers.o kutf_helpers_user.o diff --git a/drivers/gpu/arm/bifrost/tests/kutf/Kconfig b/drivers/gpu/arm/bifrost/tests/kutf/Kconfig new file mode 100644 index 000000000000..6a87bdbf746e --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/Kconfig @@ -0,0 +1,22 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +config MALI_KUTF + tristate "Mali Kernel Unit Test Framework" + default m + help + Enables MALI testing framework. To compile it as a module, + choose M here - this will generate a single module called kutf. diff --git a/drivers/gpu/arm/bifrost/tests/kutf/Makefile b/drivers/gpu/arm/bifrost/tests/kutf/Makefile new file mode 100644 index 000000000000..010c92ca39b9 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/Makefile @@ -0,0 +1,29 @@ +# +# (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) $(SCONS_CONFIGS) EXTRA_CFLAGS=-I$(CURDIR)/../include modules + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers.c new file mode 100644 index 000000000000..793d58c789ff --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers.c @@ -0,0 +1,768 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF test helpers */ +#include + +/* 10s timeout for user thread to open the 'data' file once the test is started */ +#define USERDATA_WAIT_TIMEOUT_MS 10000 +#include +#include +#include +#include +#include +#include + + +int kutf_helper_textbuf_init(struct kutf_helper_textbuf *textbuf, + struct kutf_mempool *mempool, int max_line_size, + int max_nr_lines) +{ + textbuf->scratchpad = kutf_mempool_alloc(mempool, max_line_size); + + if (!textbuf->scratchpad) + return -ENOMEM; + + mutex_init(&textbuf->lock); + textbuf->nr_user_clients = 0; + textbuf->mempool = mempool; + textbuf->used_bytes = 0; + textbuf->prev_pos = 0; + textbuf->prev_line_pos = 0; + INIT_LIST_HEAD(&textbuf->textbuf_list); + textbuf->max_line_size = max_line_size; + textbuf->max_nr_lines = max_nr_lines; + textbuf->nr_lines = 0; + textbuf->flags = 0ul; + init_waitqueue_head(&textbuf->user_opened_wq); + init_waitqueue_head(&textbuf->not_full_wq); + init_waitqueue_head(&textbuf->not_empty_wq); + + return 0; +} +EXPORT_SYMBOL(kutf_helper_textbuf_init); + +/** + * kutf_helper_textbuf_open() - Notify that userspace has opened the 'data' + * file for a textbuf + * + * @priv: private pointer from a kutf_userdata_exchange, which + * should be a pointer to a struct kutf_helper_textbuf + * + * Return: 0 on success, or negative value on error. + */ +static int kutf_helper_textbuf_open(void *priv) +{ + struct kutf_helper_textbuf *textbuf = priv; + int ret; + + ret = mutex_lock_interruptible(&textbuf->lock); + if (ret) + return -ERESTARTSYS; + + ++(textbuf->nr_user_clients); + wake_up(&textbuf->user_opened_wq); + + mutex_unlock(&textbuf->lock); + return ret; +} + +/** + * kutf_helper_textbuf_release() - Notify that userspace has closed the 'data' + * file for a textbuf + * + * @priv: private pointer from a kutf_userdata_exchange, which + * should be a pointer to a struct kutf_helper_textbuf + */ +static void kutf_helper_textbuf_release(void *priv) +{ + struct kutf_helper_textbuf *textbuf = priv; + + /* Shouldn't use interruptible variants here because if a signal is + * pending, we can't abort and restart the call */ + mutex_lock(&textbuf->lock); + + --(textbuf->nr_user_clients); + if (!textbuf->nr_user_clients) { + /* All clients disconnected, wakeup kernel-side waiters */ + wake_up(&textbuf->not_full_wq); + wake_up(&textbuf->not_empty_wq); + } + + mutex_unlock(&textbuf->lock); +} + +/** + * kutf_helper_textbuf_notify_test_ended() - Notify that the test has ended + * + * @priv: private pointer from a kutf_userdata_exchange, which + * should be a pointer to a struct kutf_helper_textbuf + * + * After this call, userspace should be allowed to finish remaining reads but + * not make new ones, and not be allowed to make new writes. + */ +static void kutf_helper_textbuf_notify_test_ended(void *priv) +{ + struct kutf_helper_textbuf *textbuf = priv; + + /* Shouldn't use interruptible variants here because if a signal is + * pending, we can't abort and restart the call */ + mutex_lock(&textbuf->lock); + + textbuf->flags |= KUTF_HELPER_TEXTBUF_FLAG_DYING; + + /* Consumers waiting due to being full should wake up and abort */ + wake_up(&textbuf->not_full_wq); + /* Producers waiting due to being empty should wake up and abort */ + wake_up(&textbuf->not_empty_wq); + + mutex_unlock(&textbuf->lock); +} + +/* Collect text in a textbuf scratchpad up to (but excluding) specified + * newline_off, and add it as a textbuf_line + * + * newline_off is permissible to be at the character after the end of the + * scratchpad (i.e. equal to textbuf->max_line_size), for handling when the + * line was longer than the size of the scratchpad. Nevertheless, the resulting + * size of the line is kept at textbuf->max_line_size, including the '\0' + * terminator. That is, the string length will be textbuf->max_line_size-1. + * + * Remaining characters strictly after newline_off are moved to the beginning + * of the scratchpad, to allow space for a longer line to be collected. This + * means the character specified at newline_off will be removed from/no longer + * be within the valid region of the scratchpad + * + * Returns number of bytes the scratchpad was shortened by, or an error + * otherwise + */ +static size_t collect_line(struct kutf_helper_textbuf *textbuf, int newline_off) +{ + /* '\n' terminator will be replaced as '\0' */ + int str_buf_size; + struct kutf_helper_textbuf_line *textbuf_line; + char *str_start; + int bytes_remain; + char *scratch = textbuf->scratchpad; + int nextline_off; + + str_buf_size = newline_off + 1; + if (str_buf_size > textbuf->max_line_size) + str_buf_size = textbuf->max_line_size; + + /* String is stored immediately after the line */ + textbuf_line = kutf_mempool_alloc(textbuf->mempool, str_buf_size + sizeof(struct kutf_helper_textbuf_line)); + if (!textbuf_line) + return -ENOMEM; + + str_start = &textbuf_line->str[0]; + + /* Copy in string, excluding the terminating '\n' character, replacing + * it with '\0' */ + strncpy(str_start, scratch, str_buf_size - 1); + str_start[str_buf_size-1] = '\0'; + textbuf_line->str_size = str_buf_size; + + /* Append to the textbuf */ + list_add_tail(&textbuf_line->node, &textbuf->textbuf_list); + ++(textbuf->nr_lines); + + /* Move the rest of the scratchpad to the start */ + nextline_off = newline_off + 1; + if (nextline_off > textbuf->used_bytes) + nextline_off = textbuf->used_bytes; + + bytes_remain = textbuf->used_bytes - nextline_off; + memmove(scratch, scratch + nextline_off, bytes_remain); + textbuf->used_bytes = bytes_remain; + + /* Wakeup anyone blocked on empty */ + wake_up(&textbuf->not_empty_wq); + + return nextline_off; +} + +/* Buffer size for truncating a string to its newline. + * Allocated on the stack, so keep it moderately small (within PAGE_SIZE) */ +#define TRUNCATE_BUF_SZ 512 + +/* Discard input from a userbuf up to a newline, then collect what was in the + * scratchpad into a new textbuf line */ +static ssize_t collect_longline_truncate(struct kutf_helper_textbuf *textbuf, + const char __user *userbuf, size_t userbuf_len) +{ + ssize_t bytes_processed = 0; + + while (userbuf_len > 0) { + int userbuf_copy_sz = userbuf_len; + size_t res; + char *newline_ptr; + char truncate_buf[TRUNCATE_BUF_SZ]; + + if (userbuf_len > TRUNCATE_BUF_SZ) + userbuf_copy_sz = TRUNCATE_BUF_SZ; + else + userbuf_copy_sz = (int)userbuf_len; + + /* copy what we can */ + res = copy_from_user(truncate_buf, userbuf, userbuf_copy_sz); + if (res == userbuf_copy_sz) + return -EFAULT; + userbuf_copy_sz -= res; + + /* Search for newline in what was copied */ + newline_ptr = strnchr(truncate_buf, userbuf_copy_sz, '\n'); + + if (newline_ptr) { + ssize_t sres; + /* Newline found: collect scratchpad and exit out */ + int newline_off = newline_ptr - truncate_buf; + + sres = collect_line(textbuf, textbuf->used_bytes); + if (sres < 0) + return sres; + + bytes_processed += newline_off + 1; + break; + } + + /* Newline not yet found: advance to the next part to copy */ + userbuf += userbuf_copy_sz; + userbuf_len -= userbuf_copy_sz; + bytes_processed += userbuf_copy_sz; + } + + return bytes_processed; +} + +/** + * kutf_helper_textbuf_consume() - 'data' file consumer function for writing to + * a textbuf + * @priv: private pointer from a kutf_userdata_exchange, which + * should be a pointer to a struct kutf_helper_textbuf to + * write into + * @userbuf: the userspace buffer to read from + * @userbuf_len: size of the userspace buffer + * @ppos: the current position in the buffer + * + * This consumer function is used as a write consumer for the 'data' file, + * receiving data that has been written to the 'data' file by userspace. It + * will read from the userspace buffer @userbuf and separates it into '\n' + * delimited lines for the textbuf pointed to by @priv . + * + * If there is insufficient space in textbuf, then it will block until there is + * space - for example, a kernel-side test calls + * kutf_helper_textbuf_dequeue(). Since this is expected to be called in the + * context of a syscall, the call can only be cancelled by sending an + * appropriate signal to the userspace process. + * + * The current position @ppos is advanced by the number of bytes successfully + * read. + * + * Return: the number of bytes read, or negative value on error. + */ +static ssize_t kutf_helper_textbuf_consume(void *priv, + const char __user *userbuf, size_t userbuf_len, loff_t *ppos) +{ + struct kutf_helper_textbuf *textbuf = priv; + int userbuf_copy_sz; + char *next_newline_ptr; + size_t bytes_processed = 0; + int newdata_off; + ssize_t ret; + + ret = mutex_lock_interruptible(&textbuf->lock); + if (ret) + return -ERESTARTSYS; + + /* Validate input */ + if (*ppos < 0) { + ret = -EINVAL; + goto out_unlock; + } + if (!userbuf_len) { + ret = 0; + goto out_unlock; + } + + while (textbuf->nr_lines >= textbuf->max_nr_lines && + !(textbuf->flags & KUTF_HELPER_TEXTBUF_FLAG_DYING)) { + /* Block on kernel-side dequeue making space available + * NOTE: should also handle O_NONBLOCK */ + mutex_unlock(&textbuf->lock); + ret = wait_event_interruptible(textbuf->not_full_wq, + (textbuf->nr_lines < textbuf->max_nr_lines || + (textbuf->flags & KUTF_HELPER_TEXTBUF_FLAG_DYING))); + if (ret) + return -ERESTARTSYS; + ret = mutex_lock_interruptible(&textbuf->lock); + if (ret) + return -ERESTARTSYS; + } + + if (textbuf->flags & KUTF_HELPER_TEXTBUF_FLAG_DYING) { + ret = -ENODEV; + goto out_unlock; + } + + if (textbuf->prev_pos != *ppos && textbuf->used_bytes) { + /* Seeking causes a new line to occur: + * Truncate what data was there into a textbuf-line, and reset + * the buffer */ + ret = collect_line(textbuf, textbuf->used_bytes); + if (ret < 0) + goto finish; + } else if (textbuf->used_bytes >= (textbuf->max_line_size - 1)) { + /* Line too long discard input until we find a '\n' */ + ret = collect_longline_truncate(textbuf, userbuf, userbuf_len); + + if (ret < 0) + goto finish; + + /* Update userbuf with how much was processed, which may be the + * entire buffer now */ + userbuf += ret; + userbuf_len -= ret; + bytes_processed += ret; + + /* If there's buffer remaining and we fault later (e.g. can't + * read or OOM) ensure ppos is updated */ + *ppos += ret; + + /* recheck in case entire buffer processed */ + if (!userbuf_len) + goto finish; + } + + /* An extra line may've been added, ensure we don't overfill */ + if (textbuf->nr_lines >= textbuf->max_nr_lines) + goto finish_noerr; + + userbuf_copy_sz = userbuf_len; + + /* Copy in as much as we can */ + if (userbuf_copy_sz > textbuf->max_line_size - textbuf->used_bytes) + userbuf_copy_sz = textbuf->max_line_size - textbuf->used_bytes; + + ret = copy_from_user(textbuf->scratchpad + textbuf->used_bytes, userbuf, userbuf_copy_sz); + if (ret == userbuf_copy_sz) { + ret = -EFAULT; + goto finish; + } + userbuf_copy_sz -= ret; + + newdata_off = textbuf->used_bytes; + textbuf->used_bytes += userbuf_copy_sz; + + while (textbuf->used_bytes && textbuf->nr_lines < textbuf->max_nr_lines) { + int new_bytes_remain = textbuf->used_bytes - newdata_off; + /* Find a new line - only the new part should be checked */ + next_newline_ptr = strnchr(textbuf->scratchpad + newdata_off, new_bytes_remain, '\n'); + + if (next_newline_ptr) { + int newline_off = next_newline_ptr - textbuf->scratchpad; + + /* if found, collect up to it, then memmove the rest */ + /* reset positions and see if we can fill any further */ + /* repeat until run out of data or line is filled */ + ret = collect_line(textbuf, newline_off); + + /* If filled up or OOM, rollback the remaining new + * data. Instead we'll try to grab it next time we're + * called */ + if (textbuf->nr_lines >= textbuf->max_nr_lines || ret < 0) + textbuf->used_bytes = newdata_off; + + if (ret < 0) + goto finish; + + /* Fix up ppos etc in case we'll be ending the loop */ + *ppos += ret - newdata_off; + bytes_processed += ret - newdata_off; + newdata_off = 0; + } else { + /* there's bytes left, but no new-line, so try to fill up next time */ + *ppos += new_bytes_remain; + bytes_processed += new_bytes_remain; + break; + } + } + +finish_noerr: + ret = bytes_processed; +finish: + textbuf->prev_pos = *ppos; +out_unlock: + mutex_unlock(&textbuf->lock); + + return ret; +} + +/** + * kutf_helper_textbuf_produce() - 'data' file producer function for reading + * from a textbuf + * @priv: private pointer from a kutf_userdata_exchange, which + * should be a pointer to a struct kutf_helper_textbuf to + * read from + * @userbuf: the userspace buffer to write to + * @userbuf_len: size of the userspace buffer + * @ppos: the current position in the buffer + * + * This producer function is used as a read producer for the 'data' file, + * allowing userspace to read from the 'data' file. It will write to the + * userspace buffer @userbuf, taking lines from the textbuf pointed to by + * @priv, separating each line with '\n'. + * + * If there is no data in the textbuf, then it will block until some appears - + * for example, a kernel-side test calls kutf_helper_textbuf_enqueue(). Since + * this is expected to be called in the context of a syscall, the call can only + * be cancelled by sending an appropriate signal to the userspace process. + * + * The current position @ppos is advanced by the number of bytes successfully + * written. + * + * Return: the number of bytes written, or negative value on error + */ +static ssize_t kutf_helper_textbuf_produce(void *priv, char __user *userbuf, + size_t userbuf_len, loff_t *ppos) +{ + struct kutf_helper_textbuf *textbuf = priv; + loff_t pos_offset; + struct kutf_helper_textbuf_line *line = NULL; + int line_start_pos; + size_t bytes_processed = 0; + ssize_t ret; + int copy_length; + + ret = mutex_lock_interruptible(&textbuf->lock); + if (ret) + return -ERESTARTSYS; + + /* Validate input */ + if (*ppos < 0) { + ret = -EINVAL; + goto finish; + } + if (!userbuf_len) { + ret = 0; + goto finish; + } + + /* Seeking to before the beginning of the line will have the effect of + * resetting the position to the start of the current data, since we've + * already discarded previous data */ + if (*ppos < textbuf->prev_line_pos) + textbuf->prev_line_pos = *ppos; + + while (!line) { + int needs_wake = 0; + + pos_offset = *ppos - textbuf->prev_line_pos; + line_start_pos = 0; + + /* Find the line for the offset, emptying the textbuf as we go */ + while (!list_empty(&textbuf->textbuf_list)) { + int line_end_pos; + + line = list_first_entry(&textbuf->textbuf_list, struct kutf_helper_textbuf_line, node); + + /* str_size used in line_end_pos because lines implicitly have + * a '\n', but we count the '\0' string terminator as that */ + line_end_pos = line_start_pos + line->str_size; + + if (pos_offset < line_end_pos) + break; + + line_start_pos += line->str_size; + /* Only discard a line when we're sure it's finished + * with, to avoid awkward rollback conditions if we've + * had to block */ + list_del(&line->node); + --(textbuf->nr_lines); + line = NULL; + needs_wake = 1; + } + + /* Update the start of the line pos for next time we're called */ + textbuf->prev_line_pos += line_start_pos; + + /* If space was freed up, wake waiters */ + if (needs_wake) + wake_up(&textbuf->not_full_wq); +; + if (!line) { + /* Only check before waiting, to ensure if the test + * does the last enqueue and immediately finishes, then + * we'll go back round the loop to receive the line + * instead of just dying straight away */ + if (textbuf->flags & KUTF_HELPER_TEXTBUF_FLAG_DYING) { + /* Indicate EOF rather than an error */ + ret = 0; + goto finish; + } + + /* No lines found, block for new ones + * NOTE: should also handle O_NONBLOCK */ + mutex_unlock(&textbuf->lock); + ret = wait_event_interruptible(textbuf->not_empty_wq, + (textbuf->nr_lines > 0 || + (textbuf->flags & KUTF_HELPER_TEXTBUF_FLAG_DYING))); + + /* signals here are not restartable */ + if (ret) + return ret; + ret = mutex_lock_interruptible(&textbuf->lock); + if (ret) + return ret; + } + + } + + + /* Find offset within the line, guaranteed to be within line->str_size */ + pos_offset -= line_start_pos; + + while (userbuf_len && line) { + /* Copy at most to the end of string, excluding terminator */ + copy_length = line->str_size - 1 - pos_offset; + if (copy_length > userbuf_len) + copy_length = userbuf_len; + + if (copy_length) { + ret = copy_to_user(userbuf, &line->str[pos_offset], copy_length); + if (ret == copy_length) { + ret = -EFAULT; + goto finish; + } + copy_length -= ret; + + userbuf += copy_length; + userbuf_len -= copy_length; + bytes_processed += copy_length; + *ppos += copy_length; + if (ret) + goto finish_noerr; + } + + /* Add terminator if one was needed */ + if (userbuf_len) { + copy_length = 1; + ret = copy_to_user(userbuf, "\n", copy_length); + if (ret == copy_length) { + ret = -EFAULT; + goto finish; + } + copy_length -= ret; + + userbuf += copy_length; + userbuf_len -= copy_length; + bytes_processed += copy_length; + *ppos += copy_length; + } else { + /* string wasn't completely copied this time - try to + * finish it next call */ + break; + } + + /* Line Completed - only now can safely delete it */ + textbuf->prev_line_pos += line->str_size; + list_del(&line->node); + --(textbuf->nr_lines); + line = NULL; + /* Space freed up, wake up waiters */ + wake_up(&textbuf->not_full_wq); + + /* Pick the next line */ + if (!list_empty(&textbuf->textbuf_list)) { + line = list_first_entry(&textbuf->textbuf_list, struct kutf_helper_textbuf_line, node); + pos_offset = 0; + } + /* if no more lines, we've copied at least some bytes, so only + * need to block on new lines the next time we're called */ + } + +finish_noerr: + ret = bytes_processed; +finish: + mutex_unlock(&textbuf->lock); + + return ret; +} + +int kutf_helper_textbuf_wait_for_user(struct kutf_helper_textbuf *textbuf) +{ + int err; + unsigned long now; + unsigned long timeout_jiffies = msecs_to_jiffies(USERDATA_WAIT_TIMEOUT_MS); + unsigned long time_end; + int ret = 0; + + /* Mutex locking using non-interruptible variants, since a signal to + * the user process will generally have to wait until we finish the + * test, because we can't restart the test. The exception is where + * we're blocked on a waitq */ + mutex_lock(&textbuf->lock); + + now = jiffies; + time_end = now + timeout_jiffies; + + while (!textbuf->nr_user_clients && time_before_eq(now, time_end)) { + unsigned long time_to_wait = time_end - now; + /* No users yet, block or timeout */ + mutex_unlock(&textbuf->lock); + /* Use interruptible here - in case we block for a long time + * and want to kill the user process */ + err = wait_event_interruptible_timeout(textbuf->user_opened_wq, + (textbuf->nr_user_clients > 0), time_to_wait); + /* Any error is not restartable due to how kutf runs tests */ + if (err < 0) + return -EINTR; + mutex_lock(&textbuf->lock); + + now = jiffies; + } + if (!textbuf->nr_user_clients) + ret = -ETIMEDOUT; + + mutex_unlock(&textbuf->lock); + + return ret; +} +EXPORT_SYMBOL(kutf_helper_textbuf_wait_for_user); + +char *kutf_helper_textbuf_dequeue(struct kutf_helper_textbuf *textbuf, + int *str_size) +{ + struct kutf_helper_textbuf_line *line; + char *ret = NULL; + + /* Mutex locking using non-interruptible variants, since a signal to + * the user process will generally have to wait until we finish the + * test, because we can't restart the test. The exception is where + * we're blocked on a waitq */ + mutex_lock(&textbuf->lock); + + while (list_empty(&textbuf->textbuf_list)) { + int err; + + if (!textbuf->nr_user_clients) { + /* No user-side clients - error */ + goto out; + } + + /* No lines found, block for new ones from user-side consumer */ + mutex_unlock(&textbuf->lock); + /* Use interruptible here - in case we block for a long time + * and want to kill the user process */ + err = wait_event_interruptible(textbuf->not_empty_wq, + (textbuf->nr_lines > 0 || !textbuf->nr_user_clients)); + /* Any error is not restartable due to how kutf runs tests */ + if (err) + return ERR_PTR(-EINTR); + mutex_lock(&textbuf->lock); + } + + line = list_first_entry(&textbuf->textbuf_list, struct kutf_helper_textbuf_line, node); + list_del(&line->node); + --(textbuf->nr_lines); + /* Space freed up, wake up waiters */ + wake_up(&textbuf->not_full_wq); + + if (str_size) + *str_size = line->str_size; + + ret = &line->str[0]; + +out: + mutex_unlock(&textbuf->lock); + return ret; +} +EXPORT_SYMBOL(kutf_helper_textbuf_dequeue); + +int kutf_helper_textbuf_enqueue(struct kutf_helper_textbuf *textbuf, + char *enqueue_str, int buf_max_size) +{ + struct kutf_helper_textbuf_line *textbuf_line; + int str_size = strnlen(enqueue_str, buf_max_size) + 1; + char *str_start; + int ret = 0; + + /* Mutex locking using non-interruptible variants, since a signal to + * the user process will generally have to wait until we finish the + * test, because we can't restart the test. The exception is where + * we're blocked on a waitq */ + mutex_lock(&textbuf->lock); + + if (str_size > textbuf->max_line_size) + str_size = textbuf->max_line_size; + + while (textbuf->nr_lines >= textbuf->max_nr_lines) { + if (!textbuf->nr_user_clients) { + /* No user-side clients - error */ + ret = -EBUSY; + goto out; + } + + /* Block on user-side producer making space available */ + mutex_unlock(&textbuf->lock); + /* Use interruptible here - in case we block for a long time + * and want to kill the user process */ + ret = wait_event_interruptible(textbuf->not_full_wq, + (textbuf->nr_lines < textbuf->max_nr_lines || !textbuf->nr_user_clients)); + /* Any error is not restartable due to how kutf runs tests */ + if (ret) + return -EINTR; + mutex_lock(&textbuf->lock); + } + + /* String is stored immediately after the line */ + textbuf_line = kutf_mempool_alloc(textbuf->mempool, str_size + sizeof(struct kutf_helper_textbuf_line)); + if (!textbuf_line) { + ret = -ENOMEM; + goto out; + } + + str_start = &textbuf_line->str[0]; + + /* Copy in string */ + strncpy(str_start, enqueue_str, str_size); + /* Enforce the '\0' termination */ + str_start[str_size-1] = '\0'; + textbuf_line->str_size = str_size; + + /* Append to the textbuf */ + list_add_tail(&textbuf_line->node, &textbuf->textbuf_list); + ++(textbuf->nr_lines); + + /* Wakeup anyone blocked on empty */ + wake_up(&textbuf->not_empty_wq); + +out: + mutex_unlock(&textbuf->lock); + return ret; +} +EXPORT_SYMBOL(kutf_helper_textbuf_enqueue); + + +struct kutf_userdata_ops kutf_helper_textbuf_userdata_ops = { + .open = kutf_helper_textbuf_open, + .release = kutf_helper_textbuf_release, + .notify_ended = kutf_helper_textbuf_notify_test_ended, + .consumer = kutf_helper_textbuf_consume, + .producer = kutf_helper_textbuf_produce, +}; +EXPORT_SYMBOL(kutf_helper_textbuf_userdata_ops); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c new file mode 100644 index 000000000000..cf3b00563c5f --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c @@ -0,0 +1,460 @@ +/* + * + * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF test helpers that mirror those for kutf-userside */ +#include +#include + +#include +#include + +const char *valtype_names[] = { + "INVALID", + "U64", + "STR", +}; + +static const char *get_val_type_name(enum kutf_helper_valtype valtype) +{ + /* enums can be signed or unsigned (implementation dependant), so + * enforce it to prevent: + * a) "<0 comparison on unsigned type" warning - if we did both upper + * and lower bound check + * b) incorrect range checking if it was a signed type - if we did + * upper bound check only */ + unsigned int type_idx = (unsigned int)valtype; + + if (type_idx >= (unsigned int)KUTF_HELPER_VALTYPE_COUNT) + type_idx = (unsigned int)KUTF_HELPER_VALTYPE_INVALID; + + return valtype_names[type_idx]; +} + +/* Check up to str_len chars of val_str to see if it's a valid value name: + * + * - Has between 1 and KUTF_HELPER_MAX_VAL_NAME_LEN characters before the \0 terminator + * - And, each char is in the character set [A-Z0-9_] */ +static int validate_val_name(char *val_str, int str_len) +{ + int i = 0; + + for (i = 0; str_len && i <= KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0'; ++i, --str_len) { + char val_chr = val_str[i]; + + if (val_chr >= 'A' && val_chr <= 'Z') + continue; + if (val_chr >= '0' && val_chr <= '9') + continue; + if (val_chr == '_') + continue; + + /* Character not in the set [A-Z0-9_] - report error */ + return 1; + } + + /* Names of 0 length are not valid */ + if (i == 0) + return 1; + /* Length greater than KUTF_HELPER_MAX_VAL_NAME_LEN not allowed */ + if (i > KUTF_HELPER_MAX_VAL_NAME_LEN || (i == KUTF_HELPER_MAX_VAL_NAME_LEN && val_str[i] != '\0')) + return 1; + + return 0; +} + +/* Find the length of the valid part of the string when it will be in quotes + * e.g. "str" + * + * That is, before any '\\', '\n' or '"' characters. This is so we don't have + * to escape the string */ +static int find_quoted_string_valid_len(char *str) +{ + char *ptr; + const char *check_chars = "\\\n\""; + + ptr = strpbrk(str, check_chars); + if (ptr) + return ptr-str; + + return strlen(str); +} + +#define MAX_U64_HEX_LEN 16 +/* (Name size) + ("=0x" size) + (64-bit hex value size) + (terminator) */ +#define NAMED_U64_VAL_BUF_SZ (KUTF_HELPER_MAX_VAL_NAME_LEN + 3 + MAX_U64_HEX_LEN + 1) + +int kutf_helper_textbuf_send_named_u64(struct kutf_context *context, + struct kutf_helper_textbuf *textbuf, char *val_name, u64 val) +{ + int ret = 1; + char msgbuf[NAMED_U64_VAL_BUF_SZ]; + const char *errmsg = NULL; + + if (validate_val_name(val_name, KUTF_HELPER_MAX_VAL_NAME_LEN + 1)) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send u64 value named '%s': Invalid value name", val_name); + goto out_err; + } + + ret = snprintf(msgbuf, NAMED_U64_VAL_BUF_SZ, "%s=0x%llx", val_name, val); + if (ret >= NAMED_U64_VAL_BUF_SZ || ret < 0) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send u64 value named '%s': snprintf() problem buffer size==%d ret=%d", + val_name, NAMED_U64_VAL_BUF_SZ, ret); + goto out_err; + } + msgbuf[NAMED_U64_VAL_BUF_SZ-1] = '\0'; + + ret = kutf_helper_textbuf_enqueue(textbuf, msgbuf, NAMED_U64_VAL_BUF_SZ); + if (ret) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send u64 value named '%s': send returned %d", + val_name, ret); + goto out_err; + } + + return ret; +out_err: + kutf_test_fail(context, errmsg); + return ret; +} +EXPORT_SYMBOL(kutf_helper_textbuf_send_named_u64); + +#define NAMED_VALUE_SEP "=" +#define NAMED_STR_START_DELIM NAMED_VALUE_SEP "\"" +#define NAMED_STR_END_DELIM "\"" + +int kutf_helper_textbuf_max_str_len_for_kern(char *val_name, + int kern_buf_sz) +{ + int val_name_len = strlen(val_name); + int start_delim_len = strlen(NAMED_STR_START_DELIM); + int max_msg_len = kern_buf_sz - 1; + int max_str_len; + + /* We do not include the end delimiter. Providing there is a line + * ending character when sending the message, the end delimiter can be + * truncated off safely to allow proper NAME="value" reception when + * value's length is too long */ + max_str_len = max_msg_len - val_name_len - start_delim_len; + + return max_str_len; +} +EXPORT_SYMBOL(kutf_helper_textbuf_max_str_len_for_kern); + +int kutf_helper_textbuf_send_named_str(struct kutf_context *context, + struct kutf_helper_textbuf *textbuf, char *val_name, + char *val_str) +{ + int val_str_len; + int str_buf_sz; + char *str_buf = NULL; + int ret = 1; + char *copy_ptr; + int val_name_len; + int start_delim_len = strlen(NAMED_STR_START_DELIM); + int end_delim_len = strlen(NAMED_STR_END_DELIM); + const char *errmsg = NULL; + + if (validate_val_name(val_name, KUTF_HELPER_MAX_VAL_NAME_LEN + 1)) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send u64 value named '%s': Invalid value name", val_name); + goto out_err; + } + val_name_len = strlen(val_name); + + val_str_len = find_quoted_string_valid_len(val_str); + + /* (name length) + ("=\"" length) + (val_str len) + ("\"" length) + terminator */ + str_buf_sz = val_name_len + start_delim_len + val_str_len + end_delim_len + 1; + + /* Using kmalloc() here instead of mempool since we know we need to free + * before we return */ + str_buf = kmalloc(str_buf_sz, GFP_KERNEL); + if (!str_buf) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send str value named '%s': kmalloc failed, str_buf_sz=%d", + val_name, str_buf_sz); + goto out_err; + } + copy_ptr = str_buf; + + /* Manually copy each string component instead of snprintf because + * val_str may need to end early, and less error path handling */ + + /* name */ + memcpy(copy_ptr, val_name, val_name_len); + copy_ptr += val_name_len; + + /* str start delimiter */ + memcpy(copy_ptr, NAMED_STR_START_DELIM, start_delim_len); + copy_ptr += start_delim_len; + + /* str value */ + memcpy(copy_ptr, val_str, val_str_len); + copy_ptr += val_str_len; + + /* str end delimiter */ + memcpy(copy_ptr, NAMED_STR_END_DELIM, end_delim_len); + copy_ptr += end_delim_len; + + /* Terminator */ + *copy_ptr = '\0'; + + ret = kutf_helper_textbuf_enqueue(textbuf, str_buf, str_buf_sz); + + if (ret) { + errmsg = kutf_dsprintf(&context->fixture_pool, + "Failed to send str value named '%s': send returned %d", + val_name, ret); + goto out_err; + } + + kfree(str_buf); + return ret; + +out_err: + kutf_test_fail(context, errmsg); + kfree(str_buf); + return ret; +} +EXPORT_SYMBOL(kutf_helper_textbuf_send_named_str); + +int kutf_helper_textbuf_receive_named_val(struct kutf_helper_named_val *named_val, + struct kutf_helper_textbuf *textbuf) +{ + int recv_sz; + char *recv_str; + char *search_ptr; + char *name_str = NULL; + int name_len; + int strval_len; + enum kutf_helper_valtype type = KUTF_HELPER_VALTYPE_INVALID; + char *strval = NULL; + u64 u64val = 0; + int orig_recv_sz; + int err = KUTF_HELPER_ERR_INVALID_VALUE; + + recv_str = kutf_helper_textbuf_dequeue(textbuf, &recv_sz); + if (!recv_str) + return -EBUSY; + else if (IS_ERR(recv_str)) + return PTR_ERR(recv_str); + orig_recv_sz = recv_sz; + + /* Find the '=', grab the name and validate it */ + search_ptr = strnchr(recv_str, recv_sz, NAMED_VALUE_SEP[0]); + if (search_ptr) { + name_len = search_ptr - recv_str; + if (!validate_val_name(recv_str, name_len)) { + /* no need to reallocate - just modify string in place */ + name_str = recv_str; + name_str[name_len] = '\0'; + + /* Move until after the '=' */ + recv_str += (name_len + 1); + recv_sz -= (name_len + 1); + } + } + if (!name_str) { + pr_err("Invalid name part for recevied string '%s'\n", recv_str); + return KUTF_HELPER_ERR_INVALID_NAME; + } + + /* detect value type */ + if (*recv_str == NAMED_STR_START_DELIM[1]) { + /* string delimiter start*/ + ++recv_str; + --recv_sz; + + /* Find end of string */ + search_ptr = strnchr(recv_str, recv_sz, NAMED_STR_END_DELIM[0]); + if (search_ptr) { + strval_len = search_ptr - recv_str; + /* Validate the string to ensure it contains no quotes */ + if (strval_len == find_quoted_string_valid_len(recv_str)) { + /* no need to reallocate - just modify string in place */ + strval = recv_str; + strval[strval_len] = '\0'; + + /* Move until after the end delimiter */ + recv_str += (strval_len + 1); + recv_sz -= (strval_len + 1); + type = KUTF_HELPER_VALTYPE_STR; + } else { + pr_err("String value contains invalid characters in rest of received string '%s'\n", recv_str); + err = KUTF_HELPER_ERR_CHARS_AFTER_VAL; + } + } else if (orig_recv_sz == textbuf->max_line_size) { + /* No end-delimiter found, but the line is at + * the max line size. Assume that before + * truncation the line had a closing delimiter + * anyway */ + strval_len = strlen(recv_str); + /* Validate the string to ensure it contains no quotes */ + if (strval_len == find_quoted_string_valid_len(recv_str)) { + strval = recv_str; + + /* Move to the end of the string */ + recv_str += strval_len; + recv_sz -= strval_len; + type = KUTF_HELPER_VALTYPE_STR; + } else { + pr_err("String value contains invalid characters in rest of received string '%s'\n", recv_str); + err = KUTF_HELPER_ERR_CHARS_AFTER_VAL; + } + } else { + pr_err("End of string delimiter not found in rest of received string '%s'\n", recv_str); + err = KUTF_HELPER_ERR_NO_END_DELIMITER; + } + } else { + /* possibly a number value - strtoull will parse it */ + err = kstrtoull(recv_str, 0, &u64val); + /* unlike userspace can't get an end ptr, but if kstrtoull() + * reads characters after the number it'll report -EINVAL */ + if (!err) { + int len_remain = strnlen(recv_str, recv_sz); + + type = KUTF_HELPER_VALTYPE_U64; + recv_str += len_remain; + recv_sz -= len_remain; + } else { + /* special case: not a number, report as such */ + pr_err("Rest of received string was not a numeric value or quoted string value: '%s'\n", recv_str); + } + } + + if (type == KUTF_HELPER_VALTYPE_INVALID) + return err; + + /* Any remaining characters - error */ + if (strnlen(recv_str, recv_sz) != 0) { + pr_err("Characters remain after value of type %s: '%s'\n", + get_val_type_name(type), recv_str); + return KUTF_HELPER_ERR_CHARS_AFTER_VAL; + } + + /* Success - write into the output structure */ + switch (type) { + case KUTF_HELPER_VALTYPE_U64: + named_val->u.val_u64 = u64val; + break; + case KUTF_HELPER_VALTYPE_STR: + named_val->u.val_str = strval; + break; + default: + pr_err("Unreachable, fix textbuf_receive_named_val\n"); + /* Coding error, report as though 'data' file failed */ + return -EINVAL; + } + + named_val->val_name = name_str; + named_val->type = type; + + return KUTF_HELPER_ERR_NONE; +} +EXPORT_SYMBOL(kutf_helper_textbuf_receive_named_val); + +#define DUMMY_MSG "" +int kutf_helper_textbuf_receive_check_val(struct kutf_helper_named_val *named_val, + struct kutf_context *context, struct kutf_helper_textbuf *textbuf, + char *expect_val_name, enum kutf_helper_valtype expect_val_type) +{ + int err; + + err = kutf_helper_textbuf_receive_named_val(named_val, textbuf); + if (err < 0) { + const char *msg = kutf_dsprintf(&context->fixture_pool, + "Failed to receive value named '%s'", + expect_val_name); + kutf_test_fail(context, msg); + return err; + } else if (err > 0) { + const char *msg = kutf_dsprintf(&context->fixture_pool, + "Named-value parse error when expecting value named '%s'", + expect_val_name); + kutf_test_fail(context, msg); + goto out_fail_and_fixup; + } + + if (strcmp(named_val->val_name, expect_val_name) != 0) { + const char *msg = kutf_dsprintf(&context->fixture_pool, + "Expecting to receive value named '%s' but got '%s'", + expect_val_name, named_val->val_name); + kutf_test_fail(context, msg); + goto out_fail_and_fixup; + } + + + if (named_val->type != expect_val_type) { + const char *msg = kutf_dsprintf(&context->fixture_pool, + "Expecting value named '%s' to be of type %s but got %s", + expect_val_name, get_val_type_name(expect_val_type), + get_val_type_name(named_val->type)); + kutf_test_fail(context, msg); + goto out_fail_and_fixup; + } + + return err; + +out_fail_and_fixup: + /* Produce a valid but incorrect value */ + switch (expect_val_type) { + case KUTF_HELPER_VALTYPE_U64: + named_val->u.val_u64 = 0ull; + break; + case KUTF_HELPER_VALTYPE_STR: + { + char *str = kutf_mempool_alloc(&context->fixture_pool, sizeof(DUMMY_MSG)); + + if (!str) + return -1; + + strcpy(str, DUMMY_MSG); + named_val->u.val_str = str; + break; + } + default: + break; + } + + /* Indicate that this is invalid */ + named_val->type = KUTF_HELPER_VALTYPE_INVALID; + + /* But at least allow the caller to continue in the test with failures */ + return 0; +} +EXPORT_SYMBOL(kutf_helper_textbuf_receive_check_val); + +void kutf_helper_output_named_val(struct kutf_helper_named_val *named_val) +{ + switch (named_val->type) { + case KUTF_HELPER_VALTYPE_U64: + pr_warn("%s=0x%llx\n", named_val->val_name, named_val->u.val_u64); + break; + case KUTF_HELPER_VALTYPE_STR: + pr_warn("%s=\"%s\"\n", named_val->val_name, named_val->u.val_str); + break; + case KUTF_HELPER_VALTYPE_INVALID: + pr_warn("%s is invalid\n", named_val->val_name); + break; + default: + pr_warn("%s has unknown type %d\n", named_val->val_name, named_val->type); + break; + } +} +EXPORT_SYMBOL(kutf_helper_output_named_val); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_mem.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_mem.c new file mode 100644 index 000000000000..a75e15fde05f --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_mem.c @@ -0,0 +1,102 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF memory management functions */ + +#include +#include + +#include + + +/** + * struct kutf_alloc_entry - Structure representing an allocation. + * @node: List node for use with kutf_mempool. + * @data: Data area of the allocation + */ +struct kutf_alloc_entry { + struct list_head node; + u8 data[0]; +}; + +int kutf_mempool_init(struct kutf_mempool *pool) +{ + if (!pool) { + pr_err("NULL pointer passed to %s\n", __func__); + return -1; + } + + INIT_LIST_HEAD(&pool->head); + mutex_init(&pool->lock); + + return 0; +} +EXPORT_SYMBOL(kutf_mempool_init); + +void kutf_mempool_destroy(struct kutf_mempool *pool) +{ + struct list_head *remove; + struct list_head *tmp; + + if (!pool) { + pr_err("NULL pointer passed to %s\n", __func__); + return; + } + + mutex_lock(&pool->lock); + list_for_each_safe(remove, tmp, &pool->head) { + struct kutf_alloc_entry *remove_alloc; + + remove_alloc = list_entry(remove, struct kutf_alloc_entry, node); + list_del(&remove_alloc->node); + kfree(remove_alloc); + } + mutex_unlock(&pool->lock); + +} +EXPORT_SYMBOL(kutf_mempool_destroy); + +void *kutf_mempool_alloc(struct kutf_mempool *pool, size_t size) +{ + struct kutf_alloc_entry *ret; + + if (!pool) { + pr_err("NULL pointer passed to %s\n", __func__); + goto fail_pool; + } + + mutex_lock(&pool->lock); + + ret = kmalloc(sizeof(*ret) + size, GFP_KERNEL); + if (!ret) { + pr_err("Failed to allocate memory\n"); + goto fail_alloc; + } + + INIT_LIST_HEAD(&ret->node); + list_add(&ret->node, &pool->head); + + mutex_unlock(&pool->lock); + + return &ret->data[0]; + +fail_alloc: + mutex_unlock(&pool->lock); +fail_pool: + return NULL; +} +EXPORT_SYMBOL(kutf_mempool_alloc); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_resultset.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_resultset.c new file mode 100644 index 000000000000..5bd04969fd55 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_resultset.c @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF result management functions */ + +#include +#include +#include + +#include + +/** + * struct kutf_result_set - Represents a set of results. + * @results: Pointer to the linked list where the results are stored. + */ +struct kutf_result_set { + struct list_head results; +}; + +struct kutf_result_set *kutf_create_result_set(void) +{ + struct kutf_result_set *set; + + set = kmalloc(sizeof(*set), GFP_KERNEL); + if (!set) { + pr_err("Failed to allocate resultset"); + goto fail_alloc; + } + + INIT_LIST_HEAD(&set->results); + + return set; + +fail_alloc: + return NULL; +} + +void kutf_add_result(struct kutf_mempool *mempool, + struct kutf_result_set *set, + enum kutf_result_status status, + const char *message) +{ + /* Create the new result */ + struct kutf_result *new_result; + + BUG_ON(set == NULL); + + new_result = kutf_mempool_alloc(mempool, sizeof(*new_result)); + if (!new_result) { + pr_err("Result allocation failed\n"); + return; + } + + INIT_LIST_HEAD(&new_result->node); + new_result->status = status; + new_result->message = message; + + list_add_tail(&new_result->node, &set->results); +} + +void kutf_destroy_result_set(struct kutf_result_set *set) +{ + if (!list_empty(&set->results)) + pr_err("kutf_destroy_result_set: Unread results from test\n"); + + kfree(set); +} + +struct kutf_result *kutf_remove_result(struct kutf_result_set *set) +{ + if (!list_empty(&set->results)) { + struct kutf_result *ret; + + ret = list_first_entry(&set->results, struct kutf_result, node); + list_del(&ret->node); + return ret; + } + + return NULL; +} + diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c new file mode 100644 index 000000000000..ad30cc86a3b0 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c @@ -0,0 +1,1398 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF suite, test and fixture management including user to kernel + * interaction */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#if defined(CONFIG_DEBUG_FS) + +/** + * struct kutf_application - Structure which represents kutf application + * @name: The name of this test application. + * @dir: The debugfs directory for this test + * @suite_list: List head to store all the suites which are part of this + * application + */ +struct kutf_application { + const char *name; + struct dentry *dir; + struct list_head suite_list; +}; + +/** + * struct kutf_test_function - Structure which represents kutf test function + * @suite: Back reference to the suite this test function + * belongs to + * @filters: Filters that apply to this test function + * @test_id: Test ID + * @execute: Function to run for this test + * @test_data: Static data for this test + * @node: List node for test_list + * @variant_list: List head to store all the variants which can run on + * this function + * @dir: debugfs directory for this test function + * @userdata_ops: Callbacks to use for sending and receiving data to + * userspace. + */ +struct kutf_test_function { + struct kutf_suite *suite; + unsigned int filters; + unsigned int test_id; + void (*execute)(struct kutf_context *context); + union kutf_callback_data test_data; + struct list_head node; + struct list_head variant_list; + struct dentry *dir; + struct kutf_userdata_ops userdata_ops; +}; + +/** + * struct kutf_test_fixture - Structure which holds information on the kutf + * test fixture + * @test_func: Test function this fixture belongs to + * @fixture_index: Index of this fixture + * @node: List node for variant_list + * @dir: debugfs directory for this test fixture + * @nr_running: Current count of user-clients running this fixture + */ +struct kutf_test_fixture { + struct kutf_test_function *test_func; + unsigned int fixture_index; + struct list_head node; + struct dentry *dir; + atomic_t nr_running; +}; + +struct dentry *base_dir; + +/** + * struct kutf_convert_table - Structure which keeps test results + * @result_name: Status of the test result + * @result: Status value for a single test + */ +struct kutf_convert_table { + char result_name[50]; + enum kutf_result_status result; +}; + +struct kutf_convert_table kutf_convert[] = { +#define ADD_UTF_RESULT(_name) \ +{ \ + #_name, \ + _name, \ +}, +ADD_UTF_RESULT(KUTF_RESULT_BENCHMARK) +ADD_UTF_RESULT(KUTF_RESULT_SKIP) +ADD_UTF_RESULT(KUTF_RESULT_UNKNOWN) +ADD_UTF_RESULT(KUTF_RESULT_PASS) +ADD_UTF_RESULT(KUTF_RESULT_DEBUG) +ADD_UTF_RESULT(KUTF_RESULT_INFO) +ADD_UTF_RESULT(KUTF_RESULT_WARN) +ADD_UTF_RESULT(KUTF_RESULT_FAIL) +ADD_UTF_RESULT(KUTF_RESULT_FATAL) +ADD_UTF_RESULT(KUTF_RESULT_ABORT) +}; + +#define UTF_CONVERT_SIZE (ARRAY_SIZE(kutf_convert)) + +/** + * kutf_create_context() - Create a test context in which a specific fixture + * of an application will be run and its results + * reported back to the user + * @test_fix: Test fixture to be run. + * + * The context's refcount will be initialized to 1. + * + * Return: Returns the created test context on success or NULL on failure + */ +static struct kutf_context *kutf_create_context( + struct kutf_test_fixture *test_fix); + +/** + * kutf_destroy_context() - Destroy a previously created test context, only + * once its refcount has become zero + * @kref: pointer to kref member within the context + * + * This should only be used via a kref_put() call on the context's kref member + */ +static void kutf_destroy_context(struct kref *kref); + +/** + * kutf_context_get() - increment refcount on a context + * @context: the kutf context + * + * This must be used when the lifetime of the context might exceed that of the + * thread creating @context + */ +static void kutf_context_get(struct kutf_context *context); + +/** + * kutf_context_put() - decrement refcount on a context, destroying it when it + * reached zero + * @context: the kutf context + * + * This must be used only after a corresponding kutf_context_get() call on + * @context, and the caller no longer needs access to @context. + */ +static void kutf_context_put(struct kutf_context *context); + +/** + * kutf_set_result() - Set the test result against the specified test context + * @context: Test context + * @status: Result status + */ +static void kutf_set_result(struct kutf_context *context, + enum kutf_result_status status); + +/** + * kutf_set_expected_result() - Set the expected test result for the specified + * test context + * @context: Test context + * @expected_status: Expected result status + */ +static void kutf_set_expected_result(struct kutf_context *context, + enum kutf_result_status expected_status); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +/* Pre 3.4.0 kernels don't have the simple_open helper */ + +/** + * simple_open() - Helper for file opening which stores the inode private data + * into the file private data + * @inode: File entry representation + * @file: A specific opening of the file + * + * Return: always 0; if inode private data do not exist, the file will not + * be assigned private data + */ +static int simple_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + return 0; +} +#endif + +/** + * kutf_result_to_string() - Converts a KUTF result into a string + * @result_str: Output result string + * @result: Result status to convert + * + * Return: 1 if test result was successfully converted to string, 0 otherwise + */ +static int kutf_result_to_string(char **result_str, + enum kutf_result_status result) +{ + int i; + int ret = 0; + + for (i = 0; i < UTF_CONVERT_SIZE; i++) { + if (result == kutf_convert[i].result) { + *result_str = kutf_convert[i].result_name; + ret = 1; + } + } + return ret; +} + +/** + * kutf_debugfs_const_string_read() - Simple debugfs read callback which + * returns a constant string + * @file: Opened file to read from + * @buf: User buffer to write the data into + * @len: Amount of data to read + * @ppos: Offset into file to read from + * + * Return: On success, the number of bytes read and offset @ppos advanced by + * this number; on error, negative value + */ +static ssize_t kutf_debugfs_const_string_read(struct file *file, + char __user *buf, size_t len, loff_t *ppos) +{ + char *str = file->private_data; + + return simple_read_from_buffer(buf, len, ppos, str, strlen(str)); +} + +static const struct file_operations kutf_debugfs_const_string_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = kutf_debugfs_const_string_read, + .llseek = default_llseek, +}; + +/** + * kutf_debugfs_data_open() Debugfs open callback for the "data" entry. + * @inode: inode of the opened file + * @file: Opened file to read from + * + * This function notifies the userdata callbacks that the userdata file has + * been opened, for tracking purposes. + * + * It is called on both the context's userdata_consumer_priv and + * userdata_producer_priv. + * + * This takes a refcount on the kutf_context + * + * Return: 0 on success + */ +static int kutf_debugfs_data_open(struct inode *inode, struct file *file) +{ + struct kutf_context *test_context = inode->i_private; + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + int err; + + simple_open(inode, file); + + /* This is not an error */ + if (!test_func->userdata_ops.open) + goto out_no_ops; + + /* This is safe here - the 'data' file is only openable whilst the + * initial refcount is still present, and the initial refcount is only + * dropped strictly after the 'data' file is removed */ + kutf_context_get(test_context); + + if (test_context->userdata_consumer_priv) { + err = test_func->userdata_ops.open(test_context->userdata_consumer_priv); + if (err) + goto out_consumer_fail; + } + + if (test_context->userdata_producer_priv) { + err = test_func->userdata_ops.open(test_context->userdata_producer_priv); + if (err) + goto out_producer_fail; + } + +out_no_ops: + return 0; + +out_producer_fail: + if (test_func->userdata_ops.release && test_context->userdata_consumer_priv) + test_func->userdata_ops.release(test_context->userdata_consumer_priv); +out_consumer_fail: + kutf_context_put(test_context); + + return err; +} + + +/** + * kutf_debugfs_data_read() Debugfs read callback for the "data" entry. + * @file: Opened file to read from + * @buf: User buffer to write the data into + * @len: Amount of data to read + * @ppos: Offset into file to read from + * + * This function allows user and kernel to exchange extra data necessary for + * the test fixture. + * + * The data is read from the first struct kutf_context running the fixture + * + * Return: Number of bytes read + */ +static ssize_t kutf_debugfs_data_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + struct kutf_context *test_context = file->private_data; + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + ssize_t (*producer)(void *private, char __user *userbuf, + size_t userbuf_len, loff_t *ppos); + ssize_t count; + + producer = test_func->userdata_ops.producer; + /* Can only read if there's a producer callback */ + if (!producer) + return -ENODEV; + + count = producer(test_context->userdata_producer_priv, buf, len, ppos); + + return count; +} + +/** + * kutf_debugfs_data_write() Debugfs write callback for the "data" entry. + * @file: Opened file to write to + * @buf: User buffer to read the data from + * @len: Amount of data to write + * @ppos: Offset into file to write to + * + * This function allows user and kernel to exchange extra data necessary for + * the test fixture. + * + * The data is added to the first struct kutf_context running the fixture + * + * Return: Number of bytes written + */ +static ssize_t kutf_debugfs_data_write(struct file *file, + const char __user *buf, size_t len, loff_t *ppos) +{ + struct kutf_context *test_context = file->private_data; + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + ssize_t (*consumer)(void *private, const char __user *userbuf, + size_t userbuf_len, loff_t *ppos); + ssize_t count; + + consumer = test_func->userdata_ops.consumer; + /* Can only write if there's a consumer callback */ + if (!consumer) + return -ENODEV; + + count = consumer(test_context->userdata_consumer_priv, buf, len, ppos); + + return count; +} + + +/** + * kutf_debugfs_data_release() - Debugfs release callback for the "data" entry. + * @inode: File entry representation + * @file: A specific opening of the file + * + * This function notifies the userdata callbacks that the userdata file has + * been closed, for tracking purposes. + * + * It is called on both the context's userdata_consumer_priv and + * userdata_producer_priv. + * + * It also drops the refcount on the kutf_context that was taken during + * kutf_debugfs_data_open() + */ +static int kutf_debugfs_data_release(struct inode *inode, struct file *file) +{ + struct kutf_context *test_context = file->private_data; + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + + if (!test_func->userdata_ops.release) + return 0; + + if (test_context->userdata_consumer_priv) + test_func->userdata_ops.release(test_context->userdata_consumer_priv); + if (test_context->userdata_producer_priv) + test_func->userdata_ops.release(test_context->userdata_producer_priv); + + kutf_context_put(test_context); + + return 0; +} + + +static const struct file_operations kutf_debugfs_data_ops = { + .owner = THIS_MODULE, + .open = kutf_debugfs_data_open, + .read = kutf_debugfs_data_read, + .write = kutf_debugfs_data_write, + .release = kutf_debugfs_data_release, + .llseek = default_llseek, +}; + +/** + * userdata_init() - Initialize userspace data exchange for a test, if + * specified by that test + * @test_context: Test context + * + * Note that this allows new refcounts to be made on test_context by userspace + * threads opening the 'data' file. + * + * Return: 0 on success, negative value corresponding to error code in failure + * and kutf result will be set appropriately to indicate the error + */ +static int userdata_init(struct kutf_context *test_context) +{ + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + int err = 0; + struct dentry *userdata_dentry; + + /* Valid to have neither a producer or consumer, which is the case for + * tests not requiring usersdata */ + if ((!test_func->userdata_ops.consumer) && (!test_func->userdata_ops.producer)) + return err; + + if (test_func->userdata_ops.consumer && !test_context->userdata_consumer_priv) { + kutf_test_fatal(test_context, + "incorrect test setup - userdata consumer provided without private data"); + return -EFAULT; + } + + if (test_func->userdata_ops.producer && !test_context->userdata_producer_priv) { + kutf_test_fatal(test_context, + "incorrect test setup - userdata producer provided without private data"); + return -EFAULT; + } + + userdata_dentry = debugfs_create_file("data", S_IROTH, test_fix->dir, + test_context, &kutf_debugfs_data_ops); + + if (!userdata_dentry) { + pr_err("Failed to create debugfs file \"data\" when running fixture\n"); + /* Not using Fatal (which stops other tests running), + * nor Abort (which indicates teardown should not be done) */ + kutf_test_fail(test_context, + "failed to create 'data' file for userside data exchange"); + + /* Error code is discarded by caller, but consistent with other + * debugfs_create_file failures */ + err = -EEXIST; + } else { + test_context->userdata_dentry = userdata_dentry; + } + + + return err; +} + +/** + * userdata_term() - Terminate userspace data exchange for a test, if specified + * by that test + * @test_context: Test context + * + * Note This also prevents new refcounts being made on @test_context by userspace + * threads opening the 'data' file for this test. Any existing open file descriptors + * to the 'data' file will still be safe to use by userspace. + */ +static void userdata_term(struct kutf_context *test_context) +{ + struct kutf_test_fixture *test_fix = test_context->test_fix; + struct kutf_test_function *test_func = test_fix->test_func; + void (*notify_ended)(void *priv) = test_func->userdata_ops.notify_ended; + + /* debugfs_remove() is safe when parameter is error or NULL */ + debugfs_remove(test_context->userdata_dentry); + + /* debugfs_remove() doesn't kill any currently open file descriptors on + * this file, and such fds are still safe to use providing test_context + * is properly refcounted */ + + if (notify_ended) { + if (test_context->userdata_consumer_priv) + notify_ended(test_context->userdata_consumer_priv); + if (test_context->userdata_producer_priv) + notify_ended(test_context->userdata_producer_priv); + } + +} + +/** + * kutf_add_explicit_result() - Check if an explicit result needs to be added + * @context: KUTF test context + */ +static void kutf_add_explicit_result(struct kutf_context *context) +{ + switch (context->expected_status) { + case KUTF_RESULT_UNKNOWN: + if (context->status == KUTF_RESULT_UNKNOWN) + kutf_test_pass(context, "(implicit pass)"); + break; + + case KUTF_RESULT_WARN: + if (context->status == KUTF_RESULT_WARN) + kutf_test_pass(context, + "Pass (expected warn occurred)"); + else if (context->status != KUTF_RESULT_SKIP) + kutf_test_fail(context, + "Fail (expected warn missing)"); + break; + + case KUTF_RESULT_FAIL: + if (context->status == KUTF_RESULT_FAIL) + kutf_test_pass(context, + "Pass (expected fail occurred)"); + else if (context->status != KUTF_RESULT_SKIP) { + /* Force the expected status so the fail gets logged */ + context->expected_status = KUTF_RESULT_PASS; + kutf_test_fail(context, + "Fail (expected fail missing)"); + } + break; + + case KUTF_RESULT_FATAL: + if (context->status == KUTF_RESULT_FATAL) + kutf_test_pass(context, + "Pass (expected fatal occurred)"); + else if (context->status != KUTF_RESULT_SKIP) + kutf_test_fail(context, + "Fail (expected fatal missing)"); + break; + + case KUTF_RESULT_ABORT: + if (context->status == KUTF_RESULT_ABORT) + kutf_test_pass(context, + "Pass (expected abort occurred)"); + else if (context->status != KUTF_RESULT_SKIP) + kutf_test_fail(context, + "Fail (expected abort missing)"); + break; + default: + break; + } +} + +/** + * kutf_debugfs_run_open() Debugfs open callback for the "run" entry. + * @inode: inode of the opened file + * @file: Opened file to read from + * + * This function retrieves the test fixture data that is associated with the + * opened file and works back to get the test, suite and application so + * it can then run the test that is associated with the file entry. + * + * Return: 0 on success + */ +static int kutf_debugfs_run_open(struct inode *inode, struct file *file) +{ + struct kutf_test_fixture *test_fix = inode->i_private; + struct kutf_test_function *test_func = test_fix->test_func; + struct kutf_suite *suite = test_func->suite; + struct kutf_context *test_context; + int err = 0; + + /* For the moment, only one user-client should be attempting to run + * this at a time. This simplifies how we lookup the kutf_context when + * using the 'data' file. + * Removing this restriction would require a rewrite of the mechanism + * of the 'data' file to pass data in, perhaps 'data' created here and + * based upon userspace thread's pid */ + if (atomic_inc_return(&test_fix->nr_running) != 1) { + err = -EBUSY; + goto finish; + } + + test_context = kutf_create_context(test_fix); + if (!test_context) { + err = -ENODEV; + goto finish; + } + + file->private_data = test_context; + + /* + * Call the create fixture function if required before the + * fixture is run + */ + if (suite->create_fixture) + test_context->fixture = suite->create_fixture(test_context); + + /* Only run the test if the fixture was created (if required) */ + if ((suite->create_fixture && test_context->fixture) || + (!suite->create_fixture)) { + int late_err; + /* Setup any userdata exchange */ + late_err = userdata_init(test_context); + + if (!late_err) + /* Run this fixture */ + test_func->execute(test_context); + + userdata_term(test_context); + + if (suite->remove_fixture) + suite->remove_fixture(test_context); + + kutf_add_explicit_result(test_context); + } + +finish: + atomic_dec(&test_fix->nr_running); + return err; +} + +/** + * kutf_debugfs_run_read() - Debugfs read callback for the "run" entry. + * @file: Opened file to read from + * @buf: User buffer to write the data into + * @len: Amount of data to read + * @ppos: Offset into file to read from + * + * This function emits the results which where logged during the opening of + * the file kutf_debugfs_run_open. + * Results will be emitted one at a time, once all the results have been read + * 0 will be returned to indicate there is no more data. + * + * Return: Number of bytes read. + */ +static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + struct kutf_context *test_context = file->private_data; + struct kutf_result *res; + unsigned long bytes_not_copied; + ssize_t bytes_copied = 0; + + /* Note: This code assumes a result is read completely */ + res = kutf_remove_result(test_context->result_set); + if (res) { + char *kutf_str_ptr = NULL; + unsigned int kutf_str_len = 0; + unsigned int message_len = 0; + char separator = ':'; + char terminator = '\n'; + + kutf_result_to_string(&kutf_str_ptr, res->status); + if (kutf_str_ptr) + kutf_str_len = strlen(kutf_str_ptr); + + if (res->message) + message_len = strlen(res->message); + + if ((kutf_str_len + 1 + message_len + 1) > len) { + pr_err("Not enough space in user buffer for a single result"); + return 0; + } + + /* First copy the result string */ + if (kutf_str_ptr) { + bytes_not_copied = copy_to_user(&buf[0], kutf_str_ptr, + kutf_str_len); + bytes_copied += kutf_str_len - bytes_not_copied; + if (bytes_not_copied) + goto exit; + } + + /* Then the separator */ + bytes_not_copied = copy_to_user(&buf[bytes_copied], + &separator, 1); + bytes_copied += 1 - bytes_not_copied; + if (bytes_not_copied) + goto exit; + + /* Finally Next copy the result string */ + if (res->message) { + bytes_not_copied = copy_to_user(&buf[bytes_copied], + res->message, message_len); + bytes_copied += message_len - bytes_not_copied; + if (bytes_not_copied) + goto exit; + } + + /* Finally the terminator */ + bytes_not_copied = copy_to_user(&buf[bytes_copied], + &terminator, 1); + bytes_copied += 1 - bytes_not_copied; + } +exit: + return bytes_copied; +} + +/** + * kutf_debugfs_run_release() - Debugfs release callback for the "run" entry. + * @inode: File entry representation + * @file: A specific opening of the file + * + * Release any resources that where created during the opening of the file + * + * Note that resources may not be released immediately, that might only happen + * later when other users of the kutf_context release their refcount. + * + * Return: 0 on success + */ +static int kutf_debugfs_run_release(struct inode *inode, struct file *file) +{ + struct kutf_context *test_context = file->private_data; + + kutf_context_put(test_context); + return 0; +} + +static const struct file_operations kutf_debugfs_run_ops = { + .owner = THIS_MODULE, + .open = kutf_debugfs_run_open, + .read = kutf_debugfs_run_read, + .release = kutf_debugfs_run_release, + .llseek = default_llseek, +}; + +/** + * create_fixture_variant() - Creates a fixture variant for the specified + * test function and index and the debugfs entries + * that represent it. + * @test_func: Test function + * @fixture_index: Fixture index + * + * Return: 0 on success, negative value corresponding to error code in failure + */ +static int create_fixture_variant(struct kutf_test_function *test_func, + unsigned int fixture_index) +{ + struct kutf_test_fixture *test_fix; + char name[11]; /* Enough to print the MAX_UINT32 + the null terminator */ + struct dentry *tmp; + int err; + + test_fix = kmalloc(sizeof(*test_fix), GFP_KERNEL); + if (!test_fix) { + pr_err("Failed to create debugfs directory when adding fixture\n"); + err = -ENOMEM; + goto fail_alloc; + } + + test_fix->test_func = test_func; + test_fix->fixture_index = fixture_index; + atomic_set(&test_fix->nr_running, 0); + + snprintf(name, sizeof(name), "%d", fixture_index); + test_fix->dir = debugfs_create_dir(name, test_func->dir); + if (!test_func->dir) { + pr_err("Failed to create debugfs directory when adding fixture\n"); + /* Might not be the right error, we don't get it passed back to us */ + err = -EEXIST; + goto fail_dir; + } + + tmp = debugfs_create_file("type", S_IROTH, test_fix->dir, "fixture\n", + &kutf_debugfs_const_string_ops); + if (!tmp) { + pr_err("Failed to create debugfs file \"type\" when adding fixture\n"); + /* Might not be the right error, we don't get it passed back to us */ + err = -EEXIST; + goto fail_file; + } + + tmp = debugfs_create_file("run", S_IROTH, test_fix->dir, test_fix, + &kutf_debugfs_run_ops); + if (!tmp) { + pr_err("Failed to create debugfs file \"run\" when adding fixture\n"); + /* Might not be the right error, we don't get it passed back to us */ + err = -EEXIST; + goto fail_file; + } + + list_add(&test_fix->node, &test_func->variant_list); + return 0; + +fail_file: + debugfs_remove_recursive(test_fix->dir); +fail_dir: + kfree(test_fix); +fail_alloc: + return err; +} + +/** + * kutf_remove_test_variant() - Destroy a previously created fixture variant. + * @test_fix: Test fixture + */ +static void kutf_remove_test_variant(struct kutf_test_fixture *test_fix) +{ + debugfs_remove_recursive(test_fix->dir); + kfree(test_fix); +} + +void kutf_add_test_with_filters_data_and_userdata( + struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data test_data, + struct kutf_userdata_ops *userdata_ops) +{ + struct kutf_test_function *test_func; + struct dentry *tmp; + unsigned int i; + + test_func = kmalloc(sizeof(*test_func), GFP_KERNEL); + if (!test_func) { + pr_err("Failed to allocate memory when adding test %s\n", name); + goto fail_alloc; + } + + INIT_LIST_HEAD(&test_func->variant_list); + + test_func->dir = debugfs_create_dir(name, suite->dir); + if (!test_func->dir) { + pr_err("Failed to create debugfs directory when adding test %s\n", name); + goto fail_dir; + } + + tmp = debugfs_create_file("type", S_IROTH, test_func->dir, "test\n", + &kutf_debugfs_const_string_ops); + if (!tmp) { + pr_err("Failed to create debugfs file \"type\" when adding test %s\n", name); + goto fail_file; + } + + test_func->filters = filters; + tmp = debugfs_create_x32("filters", S_IROTH, test_func->dir, + &test_func->filters); + if (!tmp) { + pr_err("Failed to create debugfs file \"filters\" when adding test %s\n", name); + goto fail_file; + } + + test_func->test_id = id; + tmp = debugfs_create_u32("test_id", S_IROTH, test_func->dir, + &test_func->test_id); + if (!tmp) { + pr_err("Failed to create debugfs file \"test_id\" when adding test %s\n", name); + goto fail_file; + } + + for (i = 0; i < suite->fixture_variants; i++) { + if (create_fixture_variant(test_func, i)) { + pr_err("Failed to create fixture %d when adding test %s\n", i, name); + goto fail_file; + } + } + + test_func->suite = suite; + test_func->execute = execute; + test_func->test_data = test_data; + memcpy(&test_func->userdata_ops, userdata_ops, sizeof(*userdata_ops)); + + list_add(&test_func->node, &suite->test_list); + return; + +fail_file: + debugfs_remove_recursive(test_func->dir); +fail_dir: + kfree(test_func); +fail_alloc: + return; +} +EXPORT_SYMBOL(kutf_add_test_with_filters_data_and_userdata); + +void kutf_add_test_with_filters_and_data( + struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data test_data) +{ + struct kutf_userdata_ops userdata_ops = { + .open = NULL, + .release = NULL, + .consumer = NULL, + .producer = NULL, + }; + + kutf_add_test_with_filters_data_and_userdata(suite, id, name, execute, + filters, test_data, &userdata_ops); +} + +EXPORT_SYMBOL(kutf_add_test_with_filters_and_data); + +void kutf_add_test_with_filters( + struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context), + unsigned int filters) +{ + union kutf_callback_data data; + + data.ptr_value = NULL; + + kutf_add_test_with_filters_and_data(suite, + id, + name, + execute, + suite->suite_default_flags, + data); +} +EXPORT_SYMBOL(kutf_add_test_with_filters); + +void kutf_add_test(struct kutf_suite *suite, + unsigned int id, + const char *name, + void (*execute)(struct kutf_context *context)) +{ + union kutf_callback_data data; + + data.ptr_value = NULL; + + kutf_add_test_with_filters_and_data(suite, + id, + name, + execute, + suite->suite_default_flags, + data); +} +EXPORT_SYMBOL(kutf_add_test); + +/** + * kutf_remove_test(): Remove a previously added test function. + * @test_func: Test function + */ +static void kutf_remove_test(struct kutf_test_function *test_func) +{ + struct list_head *pos; + struct list_head *tmp; + + list_for_each_safe(pos, tmp, &test_func->variant_list) { + struct kutf_test_fixture *test_fix; + + test_fix = list_entry(pos, struct kutf_test_fixture, node); + kutf_remove_test_variant(test_fix); + } + + list_del(&test_func->node); + debugfs_remove_recursive(test_func->dir); + kfree(test_func); +} + +struct kutf_suite *kutf_create_suite_with_filters_and_data( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context), + unsigned int filters, + union kutf_callback_data suite_data) +{ + struct kutf_suite *suite; + struct dentry *tmp; + + suite = kmalloc(sizeof(*suite), GFP_KERNEL); + if (!suite) { + pr_err("Failed to allocate memory when creating suite %s\n", name); + goto fail_kmalloc; + } + + suite->dir = debugfs_create_dir(name, app->dir); + if (!suite->dir) { + pr_err("Failed to create debugfs directory when adding test %s\n", name); + goto fail_debugfs; + } + + tmp = debugfs_create_file("type", S_IROTH, suite->dir, "suite\n", + &kutf_debugfs_const_string_ops); + if (!tmp) { + pr_err("Failed to create debugfs file \"type\" when adding test %s\n", name); + goto fail_file; + } + + INIT_LIST_HEAD(&suite->test_list); + suite->app = app; + suite->name = name; + suite->fixture_variants = fixture_count; + suite->create_fixture = create_fixture; + suite->remove_fixture = remove_fixture; + suite->suite_default_flags = filters; + suite->suite_data = suite_data; + + list_add(&suite->node, &app->suite_list); + + return suite; + +fail_file: + debugfs_remove_recursive(suite->dir); +fail_debugfs: + kfree(suite); +fail_kmalloc: + return NULL; +} +EXPORT_SYMBOL(kutf_create_suite_with_filters_and_data); + +struct kutf_suite *kutf_create_suite_with_filters( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context), + unsigned int filters) +{ + union kutf_callback_data data; + + data.ptr_value = NULL; + return kutf_create_suite_with_filters_and_data(app, + name, + fixture_count, + create_fixture, + remove_fixture, + filters, + data); +} +EXPORT_SYMBOL(kutf_create_suite_with_filters); + +struct kutf_suite *kutf_create_suite( + struct kutf_application *app, + const char *name, + unsigned int fixture_count, + void *(*create_fixture)(struct kutf_context *context), + void (*remove_fixture)(struct kutf_context *context)) +{ + union kutf_callback_data data; + + data.ptr_value = NULL; + return kutf_create_suite_with_filters_and_data(app, + name, + fixture_count, + create_fixture, + remove_fixture, + KUTF_F_TEST_GENERIC, + data); +} +EXPORT_SYMBOL(kutf_create_suite); + +/** + * kutf_destroy_suite() - Destroy a previously added test suite. + * @suite: Test suite + */ +static void kutf_destroy_suite(struct kutf_suite *suite) +{ + struct list_head *pos; + struct list_head *tmp; + + list_for_each_safe(pos, tmp, &suite->test_list) { + struct kutf_test_function *test_func; + + test_func = list_entry(pos, struct kutf_test_function, node); + kutf_remove_test(test_func); + } + + list_del(&suite->node); + debugfs_remove_recursive(suite->dir); + kfree(suite); +} + +struct kutf_application *kutf_create_application(const char *name) +{ + struct kutf_application *app; + struct dentry *tmp; + + app = kmalloc(sizeof(*app), GFP_KERNEL); + if (!app) { + pr_err("Failed to create allocate memory when creating application %s\n", name); + goto fail_kmalloc; + } + + app->dir = debugfs_create_dir(name, base_dir); + if (!app->dir) { + pr_err("Failed to create debugfs direcotry when creating application %s\n", name); + goto fail_debugfs; + } + + tmp = debugfs_create_file("type", S_IROTH, app->dir, "application\n", + &kutf_debugfs_const_string_ops); + if (!tmp) { + pr_err("Failed to create debugfs file \"type\" when creating application %s\n", name); + goto fail_file; + } + + INIT_LIST_HEAD(&app->suite_list); + app->name = name; + + return app; + +fail_file: + debugfs_remove_recursive(app->dir); +fail_debugfs: + kfree(app); +fail_kmalloc: + return NULL; +} +EXPORT_SYMBOL(kutf_create_application); + +void kutf_destroy_application(struct kutf_application *app) +{ + struct list_head *pos; + struct list_head *tmp; + + list_for_each_safe(pos, tmp, &app->suite_list) { + struct kutf_suite *suite; + + suite = list_entry(pos, struct kutf_suite, node); + kutf_destroy_suite(suite); + } + + debugfs_remove_recursive(app->dir); + kfree(app); +} +EXPORT_SYMBOL(kutf_destroy_application); + +static struct kutf_context *kutf_create_context( + struct kutf_test_fixture *test_fix) +{ + struct kutf_context *new_context; + + new_context = kmalloc(sizeof(*new_context), GFP_KERNEL); + if (!new_context) { + pr_err("Failed to allocate test context"); + goto fail_alloc; + } + + new_context->result_set = kutf_create_result_set(); + if (!new_context->result_set) { + pr_err("Failed to create resultset"); + goto fail_result_set; + } + + new_context->test_fix = test_fix; + /* Save the pointer to the suite as the callbacks will require it */ + new_context->suite = test_fix->test_func->suite; + new_context->status = KUTF_RESULT_UNKNOWN; + new_context->expected_status = KUTF_RESULT_UNKNOWN; + + kutf_mempool_init(&new_context->fixture_pool); + new_context->fixture = NULL; + new_context->fixture_index = test_fix->fixture_index; + new_context->fixture_name = NULL; + new_context->test_data = test_fix->test_func->test_data; + new_context->userdata_consumer_priv = NULL; + new_context->userdata_producer_priv = NULL; + new_context->userdata_dentry = NULL; + + kref_init(&new_context->kref); + + return new_context; + +fail_result_set: + kfree(new_context); +fail_alloc: + return NULL; +} + +static void kutf_destroy_context(struct kref *kref) +{ + struct kutf_context *context; + + context = container_of(kref, struct kutf_context, kref); + kutf_destroy_result_set(context->result_set); + kutf_mempool_destroy(&context->fixture_pool); + kfree(context); +} + +static void kutf_context_get(struct kutf_context *context) +{ + kref_get(&context->kref); +} + +static void kutf_context_put(struct kutf_context *context) +{ + kref_put(&context->kref, kutf_destroy_context); +} + + +static void kutf_set_result(struct kutf_context *context, + enum kutf_result_status status) +{ + context->status = status; +} + +static void kutf_set_expected_result(struct kutf_context *context, + enum kutf_result_status expected_status) +{ + context->expected_status = expected_status; +} + +/** + * kutf_test_log_result() - Log a result for the specified test context + * @context: Test context + * @message: Result string + * @new_status: Result status + */ +static void kutf_test_log_result( + struct kutf_context *context, + const char *message, + enum kutf_result_status new_status) +{ + if (context->status < new_status) + context->status = new_status; + + if (context->expected_status != new_status) + kutf_add_result(&context->fixture_pool, context->result_set, + new_status, message); +} + +void kutf_test_log_result_external( + struct kutf_context *context, + const char *message, + enum kutf_result_status new_status) +{ + kutf_test_log_result(context, message, new_status); +} +EXPORT_SYMBOL(kutf_test_log_result_external); + +void kutf_test_expect_abort(struct kutf_context *context) +{ + kutf_set_expected_result(context, KUTF_RESULT_ABORT); +} +EXPORT_SYMBOL(kutf_test_expect_abort); + +void kutf_test_expect_fatal(struct kutf_context *context) +{ + kutf_set_expected_result(context, KUTF_RESULT_FATAL); +} +EXPORT_SYMBOL(kutf_test_expect_fatal); + +void kutf_test_expect_fail(struct kutf_context *context) +{ + kutf_set_expected_result(context, KUTF_RESULT_FAIL); +} +EXPORT_SYMBOL(kutf_test_expect_fail); + +void kutf_test_expect_warn(struct kutf_context *context) +{ + kutf_set_expected_result(context, KUTF_RESULT_WARN); +} +EXPORT_SYMBOL(kutf_test_expect_warn); + +void kutf_test_expect_pass(struct kutf_context *context) +{ + kutf_set_expected_result(context, KUTF_RESULT_PASS); +} +EXPORT_SYMBOL(kutf_test_expect_pass); + +void kutf_test_skip(struct kutf_context *context) +{ + kutf_set_result(context, KUTF_RESULT_SKIP); + kutf_set_expected_result(context, KUTF_RESULT_UNKNOWN); + + kutf_test_log_result(context, "Test skipped", KUTF_RESULT_SKIP); +} +EXPORT_SYMBOL(kutf_test_skip); + +void kutf_test_skip_msg(struct kutf_context *context, const char *message) +{ + kutf_set_result(context, KUTF_RESULT_SKIP); + kutf_set_expected_result(context, KUTF_RESULT_UNKNOWN); + + kutf_test_log_result(context, kutf_dsprintf(&context->fixture_pool, + "Test skipped: %s", message), KUTF_RESULT_SKIP); + kutf_test_log_result(context, "!!!Test skipped!!!", KUTF_RESULT_SKIP); +} +EXPORT_SYMBOL(kutf_test_skip_msg); + +void kutf_test_debug(struct kutf_context *context, char const *message) +{ + kutf_test_log_result(context, message, KUTF_RESULT_DEBUG); +} +EXPORT_SYMBOL(kutf_test_debug); + +void kutf_test_pass(struct kutf_context *context, char const *message) +{ + static const char explicit_message[] = "(explicit pass)"; + + if (!message) + message = explicit_message; + + kutf_test_log_result(context, message, KUTF_RESULT_PASS); +} +EXPORT_SYMBOL(kutf_test_pass); + +void kutf_test_info(struct kutf_context *context, char const *message) +{ + kutf_test_log_result(context, message, KUTF_RESULT_INFO); +} +EXPORT_SYMBOL(kutf_test_info); + +void kutf_test_warn(struct kutf_context *context, char const *message) +{ + kutf_test_log_result(context, message, KUTF_RESULT_WARN); +} +EXPORT_SYMBOL(kutf_test_warn); + +void kutf_test_fail(struct kutf_context *context, char const *message) +{ + kutf_test_log_result(context, message, KUTF_RESULT_FAIL); +} +EXPORT_SYMBOL(kutf_test_fail); + +void kutf_test_fatal(struct kutf_context *context, char const *message) +{ + kutf_test_log_result(context, message, KUTF_RESULT_FATAL); +} +EXPORT_SYMBOL(kutf_test_fatal); + +void kutf_test_abort(struct kutf_context *context) +{ + kutf_test_log_result(context, "", KUTF_RESULT_ABORT); +} +EXPORT_SYMBOL(kutf_test_abort); + +/** + * init_kutf_core() - Module entry point. + * + * Create the base entry point in debugfs. + */ +static int __init init_kutf_core(void) +{ + int ret; + + base_dir = debugfs_create_dir("kutf_tests", NULL); + if (!base_dir) { + ret = -ENODEV; + goto exit_dir; + } + + return 0; + +exit_dir: + return ret; +} + +/** + * exit_kutf_core() - Module exit point. + * + * Remove the base entry point in debugfs. + */ +static void __exit exit_kutf_core(void) +{ + debugfs_remove_recursive(base_dir); +} + +#else /* defined(CONFIG_DEBUG_FS) */ + +/** + * init_kutf_core() - Module entry point. + * + * Stub for when build against a kernel without debugfs support + */ +static int __init init_kutf_core(void) +{ + pr_debug("KUTF requires a kernel with debug fs support"); + + return -ENODEV; +} + +/** + * exit_kutf_core() - Module exit point. + * + * Stub for when build against a kernel without debugfs support + */ +static void __exit exit_kutf_core(void) +{ +} +#endif /* defined(CONFIG_DEBUG_FS) */ + +MODULE_LICENSE("GPL"); + +module_init(init_kutf_core); +module_exit(exit_kutf_core); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c new file mode 100644 index 000000000000..a429a2dbf788 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* Kernel UTF utility functions */ + +#include +#include +#include +#include + +#include +#include + +static char tmp_buffer[KUTF_MAX_DSPRINTF_LEN]; + +DEFINE_MUTEX(buffer_lock); + +const char *kutf_dsprintf(struct kutf_mempool *pool, + const char *fmt, ...) +{ + va_list args; + int len; + int size; + void *buffer; + + mutex_lock(&buffer_lock); + va_start(args, fmt); + len = vsnprintf(tmp_buffer, sizeof(tmp_buffer), fmt, args); + va_end(args); + + if (len < 0) { + pr_err("kutf_dsprintf: Bad format dsprintf format %s\n", fmt); + goto fail_format; + } + + if (len >= sizeof(tmp_buffer)) { + pr_warn("kutf_dsprintf: Truncated dsprintf message %s\n", fmt); + size = sizeof(tmp_buffer); + } else { + size = len + 1; + } + + buffer = kutf_mempool_alloc(pool, size); + if (!buffer) + goto fail_alloc; + + memcpy(buffer, tmp_buffer, size); + mutex_unlock(&buffer_lock); + + return buffer; + +fail_alloc: +fail_format: + mutex_unlock(&buffer_lock); + return NULL; +} +EXPORT_SYMBOL(kutf_dsprintf); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/sconscript b/drivers/gpu/arm/bifrost/tests/kutf/sconscript new file mode 100644 index 000000000000..d7f112448e42 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/kutf/sconscript @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2014-2016, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import('kutf_env') + +make_args = kutf_env.kernel_get_config_defines(ret_list = True) + +mod = kutf_env.BuildKernelModule('$STATIC_LIB_PATH/kutf.ko', Glob('*.c'), make_args = make_args) +kutf_env.KernelObjTarget('kutf', mod) diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kbuild b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kbuild new file mode 100644 index 000000000000..0cd9cebe9d8b --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kbuild @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ccflags-y += -I$(src)/../include -I$(src)/../../../ -I$(src)/../../ -I$(src)/../../backend/gpu -I$(srctree)/drivers/staging/android + +obj-$(CONFIG_MALI_IRQ_LATENCY) += mali_kutf_irq_test.o + +mali_kutf_irq_test-y := mali_kutf_irq_test_main.o diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig new file mode 100644 index 000000000000..f4553d3aa08a --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +config MALI_IRQ_LATENCY + tristate "Mali GPU IRQ latency measurement" + depends on MALI_MIDGARD && MALI_DEBUG && MALI_KUTF + default m + help + This option will build a test module mali_kutf_irq_test that + can determine the latency of the Mali GPU IRQ on your system. + Choosing M here will generate a single module called mali_kutf_irq_test. diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile new file mode 100644 index 000000000000..2ac4f97aa397 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile @@ -0,0 +1,47 @@ +# +# (C) COPYRIGHT 2015, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +TEST_CCFLAGS := \ + -DMALI_DEBUG=$(MALI_DEBUG) \ + -DMALI_BACKEND_KERNEL=$(MALI_BACKEND_KERNEL) \ + -DMALI_NO_MALI=$(MALI_NO_MALI) \ + -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ + -DMALI_USE_UMP=$(MALI_USE_UMP) \ + -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \ + -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \ + $(SCONS_CFLAGS) \ + -I$(CURDIR)/../include \ + -I$(CURDIR)/../../../../../../include \ + -I$(CURDIR)/../../../ \ + -I$(CURDIR)/../../ \ + -I$(CURDIR)/../../backend/gpu \ + -I$(CURDIR)/ \ + -I$(srctree)/drivers/staging/android \ + -I$(srctree)/include/linux + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) $(SCONS_CONFIGS) EXTRA_CFLAGS="$(TEST_CCFLAGS)" KBUILD_EXTRA_SYMBOLS="$(CURDIR)/../kutf/Module.symvers $(CURDIR)/../../Module.symvers" modules + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c new file mode 100644 index 000000000000..c9cc4447cf37 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c @@ -0,0 +1,269 @@ +/* + * + * (C) COPYRIGHT 2016, 2017 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include + +#include "mali_kbase.h" +#include + +#include +#include + +/* + * This file contains the code which is used for measuring interrupt latency + * of the Mali GPU IRQ. In particular, function mali_kutf_irq_latency() is + * used with this purpose and it is called within KUTF framework - a kernel + * unit test framework. The measured latency provided by this test should + * be representative for the latency of the Mali JOB/MMU IRQs as well. + */ + +/* KUTF test application pointer for this test */ +struct kutf_application *irq_app; + +/** + * struct kutf_irq_fixture data - test fixture used by the test functions. + * @kbdev: kbase device for the GPU. + * + */ +struct kutf_irq_fixture_data { + struct kbase_device *kbdev; +}; + +#define SEC_TO_NANO(s) ((s)*1000000000LL) + +/* ID for the GPU IRQ */ +#define GPU_IRQ_HANDLER 2 + +#define NR_TEST_IRQS 1000000 + +/* IRQ for the test to trigger. Currently MULTIPLE_GPU_FAULTS as we would not + * expect to see this in normal use (e.g., when Android is running). */ +#define TEST_IRQ MULTIPLE_GPU_FAULTS + +#define IRQ_TIMEOUT HZ + +/* Kernel API for setting irq throttle hook callback and irq time in us*/ +extern int kbase_set_custom_irq_handler(struct kbase_device *kbdev, + irq_handler_t custom_handler, + int irq_type); +extern irqreturn_t kbase_gpu_irq_handler(int irq, void *data); + +static DECLARE_WAIT_QUEUE_HEAD(wait); +static bool triggered; +static u64 irq_time; + +static void *kbase_untag(void *ptr) +{ + return (void *)(((uintptr_t) ptr) & ~3); +} + +/** + * kbase_gpu_irq_custom_handler - Custom IRQ throttle handler + * @irq: IRQ number + * @data: Data associated with this IRQ + * + * Return: state of the IRQ + */ +static irqreturn_t kbase_gpu_irq_custom_handler(int irq, void *data) +{ + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS), NULL); + if (val & TEST_IRQ) { + struct timespec tval; + + getnstimeofday(&tval); + irq_time = SEC_TO_NANO(tval.tv_sec) + (tval.tv_nsec); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val, + NULL); + + triggered = true; + wake_up(&wait); + + return IRQ_HANDLED; + } + + /* Trigger main irq handler */ + return kbase_gpu_irq_handler(irq, data); +} + +/** + * mali_kutf_irq_default_create_fixture() - Creates the fixture data required + * for all the tests in the irq suite. + * @context: KUTF context. + * + * Return: Fixture data created on success or NULL on failure + */ +static void *mali_kutf_irq_default_create_fixture( + struct kutf_context *context) +{ + struct kutf_irq_fixture_data *data; + + data = kutf_mempool_alloc(&context->fixture_pool, + sizeof(struct kutf_irq_fixture_data)); + + if (!data) + goto fail; + + /* Acquire the kbase device */ + data->kbdev = kbase_find_device(-1); + if (data->kbdev == NULL) { + kutf_test_fail(context, "Failed to find kbase device"); + goto fail; + } + + return data; + +fail: + return NULL; +} + +/** + * mali_kutf_irq_default_remove_fixture() - Destroy fixture data previously + * created by mali_kutf_irq_default_create_fixture. + * + * @context: KUTF context. + */ +static void mali_kutf_irq_default_remove_fixture( + struct kutf_context *context) +{ + struct kutf_irq_fixture_data *data = context->fixture; + struct kbase_device *kbdev = data->kbdev; + + kbase_release_device(kbdev); +} + +/** + * mali_kutf_irq_latency() - measure GPU IRQ latency + * @context: kutf context within which to perform the test + * + * The test triggers IRQs manually, and measures the + * time between triggering the IRQ and the IRQ handler being executed. + * + * This is not a traditional test, in that the pass/fail status has little + * meaning (other than indicating that the IRQ handler executed at all). Instead + * the results are in the latencies provided with the test result. There is no + * meaningful pass/fail result that can be obtained here, instead the latencies + * are provided for manual analysis only. + */ +static void mali_kutf_irq_latency(struct kutf_context *context) +{ + struct kutf_irq_fixture_data *data = context->fixture; + struct kbase_device *kbdev = data->kbdev; + u64 min_time = U64_MAX, max_time = 0, average_time = 0; + int i; + bool test_failed = false; + + /* Force GPU to be powered */ + kbase_pm_context_active(kbdev); + + kbase_set_custom_irq_handler(kbdev, kbase_gpu_irq_custom_handler, + GPU_IRQ_HANDLER); + + for (i = 0; i < NR_TEST_IRQS; i++) { + struct timespec tval; + u64 start_time; + int ret; + + triggered = false; + getnstimeofday(&tval); + start_time = SEC_TO_NANO(tval.tv_sec) + (tval.tv_nsec); + + /* Trigger fake IRQ */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), + TEST_IRQ, NULL); + + ret = wait_event_timeout(wait, triggered != false, IRQ_TIMEOUT); + + if (ret == 0) { + kutf_test_fail(context, "Timed out waiting for IRQ\n"); + test_failed = true; + break; + } + + if ((irq_time - start_time) < min_time) + min_time = irq_time - start_time; + if ((irq_time - start_time) > max_time) + max_time = irq_time - start_time; + average_time += irq_time - start_time; + + udelay(10); + } + + /* Go back to default handler */ + kbase_set_custom_irq_handler(kbdev, NULL, GPU_IRQ_HANDLER); + + kbase_pm_context_idle(kbdev); + + if (!test_failed) { + const char *results; + + do_div(average_time, NR_TEST_IRQS); + results = kutf_dsprintf(&context->fixture_pool, + "Min latency = %lldns, Max latency = %lldns, Average latency = %lldns\n", + min_time, max_time, average_time); + kutf_test_pass(context, results); + } +} + +/** + * Module entry point for this test. + */ +int mali_kutf_irq_test_main_init(void) +{ + struct kutf_suite *suite; + + irq_app = kutf_create_application("irq"); + + if (NULL == irq_app) { + pr_warn("Creation of test application failed!\n"); + return -ENOMEM; + } + + suite = kutf_create_suite(irq_app, "irq_default", + 1, mali_kutf_irq_default_create_fixture, + mali_kutf_irq_default_remove_fixture); + + if (NULL == suite) { + pr_warn("Creation of test suite failed!\n"); + kutf_destroy_application(irq_app); + return -ENOMEM; + } + + kutf_add_test(suite, 0x0, "irq_latency", + mali_kutf_irq_latency); + return 0; +} + +/** + * Module exit point for this test. + */ +void mali_kutf_irq_test_main_exit(void) +{ + kutf_destroy_application(irq_app); +} + +module_init(mali_kutf_irq_test_main_init); +module_exit(mali_kutf_irq_test_main_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript new file mode 100644 index 000000000000..280fa9866957 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript @@ -0,0 +1,30 @@ +# +# (C) COPYRIGHT 2015, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +Import('env') + +src = [Glob('#kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/*.c'), Glob('#kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Makefile')] + +if env.GetOption('clean') : + env.Execute(Action("make clean", '[CLEAN] mali_kutf_irq_test')) + cmd = env.Command('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', src, []) + env.KernelObjTarget('mali_kutf_irq_test', cmd) +else: + makeAction=Action("cd ${SOURCE.dir} && make MALI_DEBUG=${debug} MALI_BACKEND_KERNEL=1 MALI_ERROR_INJECT_ON=${error_inject} MALI_NO_MALI=${no_mali} MALI_UNIT_TEST=${unit} MALI_USE_UMP=${ump} MALI_CUSTOMER_RELEASE=${release} %s && ( ( [ -f mali_kutf_irq_test.ko ] && cp mali_kutf_irq_test.ko $STATIC_LIB_PATH/ ) || touch $STATIC_LIB_PATH/mali_kutf_irq_test.ko)" % env.kernel_get_config_defines(), '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', src, [makeAction]) + env.Depends('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', '$STATIC_LIB_PATH/kutf.ko') + env.Depends('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', '$STATIC_LIB_PATH/mali_kbase.ko') + env.KernelObjTarget('mali_kutf_irq_test', cmd) diff --git a/drivers/gpu/arm/bifrost/tests/sconscript b/drivers/gpu/arm/bifrost/tests/sconscript new file mode 100644 index 000000000000..04584117ccef --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/sconscript @@ -0,0 +1,38 @@ +# +# (C) COPYRIGHT 2010-2011, 2013, 2017 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import ('env') + +kutf_env = env.Clone() +kutf_env.Append(CPPPATH = '#kernel/drivers/gpu/arm/midgard/tests/include') +Export('kutf_env') + +if Glob('internal/sconscript'): + SConscript('internal/sconscript') + +if kutf_env['debug'] == '1': + SConscript('kutf/sconscript') + SConscript('mali_kutf_irq_test/sconscript') + + if Glob('kutf_test/sconscript'): + SConscript('kutf_test/sconscript') + + if Glob('kutf_test_runner/sconscript'): + SConscript('kutf_test_runner/sconscript') + +if env['unit'] == '1': + SConscript('mali_kutf_ipa_test/sconscript') + SConscript('mali_kutf_ipa_unit_test/sconscript') + SConscript('mali_kutf_vinstr_test/sconscript') From f6ee06ee9c1c8a354e4cfc5a3fd0b322b34be3c9 Mon Sep 17 00:00:00 2001 From: Tony Xie Date: Thu, 1 Feb 2018 21:31:29 +0800 Subject: [PATCH 194/427] arm64: dts: rockchip: add rk809 config for px30 Change-Id: I800930de092077f96873304b17aa218fa791813a Signed-off-by: Tony Xie --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 256 +++++++++++++++++ .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 257 ++++++++++++++++++ 2 files changed, 513 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 505b66d6de85..966884522314 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -263,6 +263,255 @@ status = "okay"; }; +&i2c0 { + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + + vcc5v0_sys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcc3v3_sys: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v3_lcd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_lcd"; + }; + + vcc5v0_host: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_host"; + }; + }; + }; +}; + &i2c1 { status = "okay"; @@ -307,6 +556,13 @@ }; &pinctrl { + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index bd7bb55ab3d6..fb7335473d7e 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -235,6 +235,256 @@ }; }; +&i2c0 { + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + + vcc5v0_sys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcc3v3_sys: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v3_lcd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_lcd"; + }; + + vcc5v0_host: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_host"; + }; + }; + }; +}; + &i2c1 { status = "okay"; @@ -322,6 +572,13 @@ }; &pinctrl { + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; From bffbb0ee12b420dc1846b792dc82fd2066373450 Mon Sep 17 00:00:00 2001 From: "tony.xie" Date: Mon, 29 Jan 2018 19:23:07 +0800 Subject: [PATCH 195/427] arm64: dts: rockchip: add rk817 config for rk3326 Change-Id: Ia7c18fddccb02148c997659f4684b25d3d1ce5c8 Signed-off-by: Tony Xie --- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 246 ++++++++++++++++++ .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 246 ++++++++++++++++++ 2 files changed, 492 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 622a488ac2b4..a43a53d7352c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -199,6 +199,245 @@ status = "okay"; }; +&i2c0 { + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&dcdc_boost>; + + vccsys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + dcdc_boost: BOOST { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4700000>; + regulator-max-microvolt = <5400000>; + regulator-name = "boost"; + }; + + otg_switch: OTG_SWITCH { + regulator-always-on; + regulator-boot-on; + regulator-name = "otg_switch"; + }; + }; + }; +}; + &i2c1 { status = "okay"; @@ -236,6 +475,13 @@ }; &pinctrl { + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index a67a415a93a6..779f2f59000e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -296,6 +296,245 @@ status = "okay"; }; +&i2c0 { + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&dcdc_boost>; + + vccsys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + dcdc_boost: BOOST { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4700000>; + regulator-max-microvolt = <5400000>; + regulator-name = "boost"; + }; + + otg_switch: OTG_SWITCH { + regulator-always-on; + regulator-boot-on; + regulator-name = "otg_switch"; + }; + }; + }; +}; + &i2c1 { status = "okay"; @@ -365,6 +604,13 @@ }; &pinctrl { + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; From 64ef3da37214379c02471ef94292bf3902746762 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Fri, 2 Feb 2018 17:14:55 +0800 Subject: [PATCH 196/427] arm64: dts: rockchip: add io-domain config for px30/rk3326 Change-Id: I8b0c76dfc388068782f613285f3b0c5e5314cd32 Signed-off-by: Weixin Zhou --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 17 +++++++++++++ .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 17 +++++++++++++ .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 25 ++++++++++++++++--- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 25 ++++++++++++++++--- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 966884522314..86d831e73f97 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -547,6 +547,16 @@ }; }; +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc3v0_pmu>; + vccio5-supply = <&vcc_3v0>; +}; + &mipi_dphy { status = "okay"; }; @@ -570,6 +580,13 @@ }; }; +&pmu_io_domains { + status = "okay"; + + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; +}; + &pwm1 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index fb7335473d7e..f156d5b0c86c 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -511,6 +511,16 @@ }; }; +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc3v0_pmu>; + vccio5-supply = <&vcc_3v0>; +}; + &dsi_in_vopl { status = "disabled"; }; @@ -586,6 +596,13 @@ }; }; +&pmu_io_domains { + status = "okay"; + + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; +}; + &pwm1 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index a43a53d7352c..879ae083ce96 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -462,6 +462,16 @@ }; }; +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc_3v0>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc2v8_dvp>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; +}; + &mipi_dphy { status = "okay"; }; @@ -470,10 +480,6 @@ status = "okay"; }; -&pwm1 { - status = "okay"; -}; - &pinctrl { pmic { pmic_int: pmic_int { @@ -489,6 +495,17 @@ }; }; +&pmu_io_domains { + status = "okay"; + + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; +}; + +&pwm1 { + status = "okay"; +}; + &rk_rga { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 779f2f59000e..583dfe71ffba 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -570,6 +570,16 @@ }; }; +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc1v8_dvp>; + vccio4-supply = <&vcc_3v0>; + vccio5-supply = <&vcc_3v0>; +}; + &lvds { //pinctrl-names = "lcdc"; //pinctrl-0 = <&lcdc_rgb_dclk_pin &lcdc_rgb_m0_den_pin &lcdc_rgb_m0_hsync_pin &lcdc_rgb_m0_vsync_pin &lcdc_rgb666_m0_data_pins>; @@ -599,10 +609,6 @@ status = "okay"; }; -&pwm1 { - status = "okay"; -}; - &pinctrl { pmic { pmic_int: pmic_int { @@ -618,6 +624,17 @@ }; }; +&pmu_io_domains { + status = "okay"; + + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; +}; + +&pwm1 { + status = "okay"; +}; + &saradc { status = "okay"; }; From ac4076851c5c59d23415338ba958085724fbbfc8 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 30 Jan 2018 16:50:17 +0800 Subject: [PATCH 197/427] drm/rockchip: vop: fix wait frame start timeout In the following case will lead to wait frame start timeout: uboot(HDMI output 4K(DCLK: 594HZ)) -> kernel start(unplug HDMI) ->drm driver probe(plug HDMI)enable crtc(set dclk to 27Mhz) ->VOP timing register is frame effect ->VOP working at 4k output but dclk is 27M -> VOP frame time 16.6ms * 574 / 27 = 354ms Change-Id: Ic98af0029a15fbeef78e4f3abe4e739e760ab471 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 45 +++++++++++++-------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2426c0f7d6ac..6290aec7f100 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -201,6 +201,7 @@ struct vop { bool is_iommu_enabled; bool is_iommu_needed; bool is_enabled; + bool mode_update; u32 version; @@ -860,6 +861,20 @@ static int to_vop_csc_mode(int csc_mode) } } +static void vop_disable_all_planes(struct vop *vop) +{ + bool active; + int ret; + + vop_disable_allwin(vop); + vop_cfg_done(vop); + ret = readx_poll_timeout_atomic(vop_is_allwin_disabled, + vop, active, active, + 0, 500 * 1000); + if (ret) + dev_err(vop->dev, "wait win close timeout\n"); +} + /* * rk3399 colorspace path: * Input Win csc Output @@ -2401,8 +2416,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc) int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0; uint32_t val; - bool active; - int ret, act_end; + int act_end; rockchip_set_system_status(sys_status); mutex_lock(&vop->vop_lock); @@ -2523,7 +2537,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, win_csc_mode_sel, 1); if (vop_crtc_mode_update(crtc)) { - vop_disable_allwin(vop); + vop_disable_all_planes(vop); + vop->mode_update = true; DRM_DEV_INFO(vop->dev, "Update mode to %d*%d, close all win\n", hdisplay, vdisplay); } @@ -2538,20 +2553,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc) enable_irq(vop->irq); drm_crtc_vblank_on(crtc); - drm_crtc_vblank_get(crtc); mutex_unlock(&vop->vop_lock); - /* make sure timing config take effect */ - ret = readx_poll_timeout_atomic(vop_fs_irq_is_active, - vop, active, !active, - 0, 100 * 1000); - if (ret) - dev_err(vop->dev, "wait exit fs irq timeout\n"); - ret = readx_poll_timeout_atomic(vop_fs_irq_is_active, - vop, active, active, - 0, 100 * 1000); - if (ret) - dev_err(vop->dev, "wait get fs irq timeout\n"); - drm_crtc_vblank_put(crtc); } static int vop_zpos_cmp(const void *a, const void *b) @@ -3142,9 +3144,17 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, vop_cfg_update(crtc, old_crtc_state); if (!vop->is_iommu_enabled && vop->is_iommu_needed) { - bool need_wait_vblank = !vop_is_allwin_disabled(vop); + bool need_wait_vblank; int ret; + if (vop->mode_update) + vop_disable_all_planes(vop); + + need_wait_vblank = !vop_is_allwin_disabled(vop); + if (vop->mode_update && need_wait_vblank) + dev_warn(vop->dev, "mode_update:%d, need wait blk:%d\n", + vop->mode_update, need_wait_vblank); + if (need_wait_vblank) { bool active; @@ -3188,6 +3198,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock_irqsave(&vop->irq_lock, flags); vop->pre_overlay = s->hdr.pre_overlay; vop_cfg_done(vop); + vop->mode_update = false; spin_unlock_irqrestore(&vop->irq_lock, flags); /* From 1cb8aa091d13dc06b3843dee582414400dcdbf4e Mon Sep 17 00:00:00 2001 From: Huicong Xu Date: Tue, 30 Jan 2018 16:01:56 +0800 Subject: [PATCH 198/427] drm/bridge/synopsys: restore bus_width as 8 when disable hdmi encoder to modify bus width error sometime plug out hdmi and switch cvbs output Change-Id: Iaa7914fbccc99991fbfbc5495ba647f97997c8ba Signed-off-by: Huicong Xu --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 0cb40e2008d6..9f2ee9dab8f3 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -101,6 +101,7 @@ struct rockchip_hdmi { unsigned int colordepth; unsigned int colorimetry; + unsigned int phy_bus_width; enum drm_hdmi_output_type hdmi_output; }; @@ -542,6 +543,12 @@ static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + /* + * when plug out hdmi it will be switch cvbs and then phy bus width + * must be set as 8 + */ + if (hdmi->phy) + phy_set_bus_width(hdmi->phy, 8); clk_disable_unprepare(hdmi->dclk); } @@ -557,6 +564,9 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) if (WARN_ON(!crtc || !crtc->state)) return; + if (hdmi->phy) + phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); + clk_set_rate(hdmi->vpll_clk, crtc->state->adjusted_mode.crtc_clock * 1000); @@ -800,6 +810,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, bus_width = colordepth; } + hdmi->phy_bus_width = bus_width; if (hdmi->phy) phy_set_bus_width(hdmi->phy, bus_width); From 4a56c8edc7ce00c92dbcaa5638bf9358b4329ca1 Mon Sep 17 00:00:00 2001 From: "tony.xie" Date: Mon, 29 Jan 2018 15:32:32 +0800 Subject: [PATCH 199/427] mfd: RK817 & RK809: Add new mfd driver for RK817 & RK809 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RK817 & RK809 chip is a power management IC for multimedia and handheld devices. It contains the following components: - Regulators - RTC - Clkout - Pinctrl - Powerkey The RK817 & RK809 core driver is registered as a platform driver and provides communication through I2C with the host device for the different components. The following is the different between the RK817 and the RK809. 1ã€The dcdc-buck5 is a boost dcdc for RK817 and is a buck for RK809. 2ã€The RK817 have one switch but The Rk809 have two. 3ã€The RK817 have a charger and powerpatch function but RK809 not. Change-Id: I132029c5b28978db7ae06e13c327a1edf70f5b69 Signed-off-by: Tony Xie --- .../devicetree/bindings/mfd/rk809.txt | 293 +++++++++ .../devicetree/bindings/mfd/rk817.txt | 288 +++++++++ drivers/clk/clk-rk808.c | 63 +- drivers/mfd/rk808.c | 185 +++++- drivers/regulator/rk808-regulator.c | 577 +++++++++++++++++- drivers/rtc/rtc-rk808.c | 75 ++- include/linux/mfd/rk808.h | 158 +++++ 7 files changed, 1611 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/rk809.txt create mode 100644 Documentation/devicetree/bindings/mfd/rk817.txt diff --git a/Documentation/devicetree/bindings/mfd/rk809.txt b/Documentation/devicetree/bindings/mfd/rk809.txt new file mode 100644 index 000000000000..17c23275e892 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rk809.txt @@ -0,0 +1,293 @@ +RK809 Power Management Integrated Circuit + +Required properties: +- compatible: "rockchip,rk809" +- reg: I2C slave address +- interrupt-parent: The parent interrupt controller. +- interrupts: the interrupt outputs of the controller. +- #clock-cells: from common clock binding; shall be set to 1 (multiple clock + outputs). See for clock IDs. + +Optional properties: +- clock-output-names: From common clock binding to override the + default output clock name +- rockchip,system-power-controller: Telling whether or not this pmic is controlling + the system power. +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3 +- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6 +- vcc7-supply: The input supply for LDO_REG7, LDO_REG8, LDO_REG9 +- vcc8-supply: The input supply for SWITCH_REG1 +- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2 + +Regulators: All the regulators of RK809 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the RK809 PMIC block are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK808 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 5. + - LDO_REGn + - valid values for n are 1 to 9. + - SWITCH_REGn + - valid values for n are 1 to 2. +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details + +Example: + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + + vcc5v0_sys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcc3v3_sys: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v3_lcd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_lcd"; + }; + + vcc5v0_host: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_host"; + }; + }; + }; + + + diff --git a/Documentation/devicetree/bindings/mfd/rk817.txt b/Documentation/devicetree/bindings/mfd/rk817.txt new file mode 100644 index 000000000000..062b9f7d957a --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rk817.txt @@ -0,0 +1,288 @@ +RK817 Power Management Integrated Circuit + +Required properties: +- compatible: "rockchip,rk817" +- reg: I2C slave address +- interrupt-parent: The parent interrupt controller. +- interrupts: the interrupt outputs of the controller. +- #clock-cells: from common clock binding; shall be set to 1 (multiple clock + outputs). See for clock IDs. + +Optional properties: +- clock-output-names: From common clock binding to override the + default output clock name +- rockchip,system-power-controller: Telling whether or not this pmic is controlling + the system power. +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3 +- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6 +- vcc7-supply: The input supply for LDO_REG7, LDO_REG8, LDO_REG9 +- vcc8-supply: The input supply for BOOST +- vcc9-supply: The input supply for OTG_SWITCH + +Regulators: All the regulators of RK817 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the RK817 PMIC block are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK808 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 4. + - LDO_REGn + - valid values for n are 1 to 9. + +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details + +Example: + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + vcc8-supply = <&vccsys>; + vcc9-supply = <&vccsys>; + vcc10-supply = <&vccsys>; + vcc11-supply = <&vcc_3v0>; + vcc12-supply = <&vcc_3v0>; + vcc13-supply = <&vcc_3v0>; + vcc14-supply = <&vccsys>; + vcc15-supply = <&rk817_boost>; + + vccsys: vccsys{ + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + + rk817_pin0_ts: rk817_pin0_ts { + pins = "gpio0"; + function = "pin_fun0"; + }; + + rk817_pin0_gpio: rk817_pin0_gpio { + pins = "gpio0"; + function = "gpio"; + }; + + rk817_pin1_gt: rk817_pin1_gt { + pins = "gpio1"; + function = "pin_fun0"; + }; + + rk817_pin1_gpio: rk817_pin1_gpio { + pins = "gpio1"; + function = "gpio"; + }; + + regulators { + vdd_arm: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_logic: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <800000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; //?? + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_cif: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_cif"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_cif: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_cif"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vcc1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + boost: BOOST { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4700000>; + regulator-max-microvolt = <5400000>; + regulator-name = "boost"; + }; + + otg_switch: OTG_SWITCH { + regulator-always-on; + regulator-boot-on; + regulator-name = "otg_switch"; + }; + }; + }; + + + diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c index 0fee2f4ca258..73c508eddcd1 100644 --- a/drivers/clk/clk-rk808.c +++ b/drivers/clk/clk-rk808.c @@ -85,6 +85,67 @@ static const struct clk_ops rk808_clkout2_ops = { .recalc_rate = rk808_clkout_recalc_rate, }; +static int rk817_clkout2_enable(struct clk_hw *hw, bool enable) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + + return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1), + RK817_CLK32KOUT2_EN, + enable ? RK817_CLK32KOUT2_EN : 0); +} + +static int rk817_clkout2_prepare(struct clk_hw *hw) +{ + return rk817_clkout2_enable(hw, true); +} + +static void rk817_clkout2_unprepare(struct clk_hw *hw) +{ + rk817_clkout2_enable(hw, false); +} + +static int rk817_clkout2_is_prepared(struct clk_hw *hw) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + unsigned int val; + + int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val); + + if (ret < 0) + return ret; + + return (val & RK817_CLK32KOUT2_EN) ? 1 : 0; +} + +static const struct clk_ops rk817_clkout2_ops = { + .prepare = rk817_clkout2_prepare, + .unprepare = rk817_clkout2_unprepare, + .is_prepared = rk817_clkout2_is_prepared, + .recalc_rate = rk808_clkout_recalc_rate, +}; + +static const struct clk_ops *rkpmic_get_ops(long variant) +{ + switch (variant) { + case RK809_ID: + case RK817_ID: + return &rk817_clkout2_ops; + case RK805_ID: + case RK808_ID: + case RK816_ID: + case RK818_ID: + return &rk808_clkout2_ops; + } + + return &rk808_clkout2_ops; +} + static int rk808_clkout_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); @@ -123,7 +184,7 @@ static int rk808_clkout_probe(struct platform_device *pdev) return PTR_ERR(clk_table[0]); init.name = "rk808-clkout2"; - init.ops = &rk808_clkout2_ops; + init.ops = rkpmic_get_ops(rk808->variant); rk808_clkout->clkout2_hw.init = &init; /* optional override of the clockname */ diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 51ad22c1092a..f6a062d30565 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -61,6 +61,29 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) return false; } +static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK817_SECONDS_REG ... RK817_WEEKS_REG: + case RK817_RTC_STATUS_REG: + case RK817_INT_STS_REG0: + case RK817_INT_STS_REG1: + case RK817_INT_STS_REG2: + case RK817_SYS_STS: + return true; + } + + return true; +} + static int rk808_shutdown(struct regmap *regmap) { int ret; @@ -110,6 +133,25 @@ static int rk805_shutdown_prepare(struct regmap *regmap) return ret; } +static int rk817_shutdown_prepare(struct regmap *regmap) +{ + int ret; + + /* close rtc int when power off */ + regmap_update_bits(regmap, + RK817_INT_STS_MSK_REG1, + (0x3 << 5), (0x3 << 5)); + regmap_update_bits(regmap, + RK817_RTC_INT_REG, + (0x3 << 2), (0x0 << 2)); + + /* pmic sleep shutdown function */ + ret = regmap_update_bits(regmap, + RK817_SYS_CFG(3), + RK817_SLPPIN_FUNC_MSK, SHUTDOWN_FUN); + return ret; +} + static bool rk818_is_volatile_reg(struct device *dev, unsigned int reg) { /* @@ -176,6 +218,14 @@ static const struct regmap_config rk818_regmap_config = { .volatile_reg = rk818_is_volatile_reg, }; +static const struct regmap_config rk817_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK817_GPIO_INT_CFG, + .cache_type = REGCACHE_NONE, + .volatile_reg = rk817_is_volatile_reg, +}; + static struct resource rtc_resources[] = { { .start = RK808_IRQ_RTC_ALARM, @@ -184,6 +234,14 @@ static struct resource rtc_resources[] = { } }; +static struct resource rk817_rtc_resources[] = { + { + .start = RK817_IRQ_RTC_ALARM, + .end = RK817_IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, + } +}; + static struct resource rk816_rtc_resources[] = { { .start = RK816_IRQ_RTC_ALARM, @@ -192,7 +250,7 @@ static struct resource rk816_rtc_resources[] = { } }; -static struct resource pwrkey_resources[] = { +static struct resource rk805_pwrkey_resources[] = { { .start = RK805_IRQ_PWRON_RISE, .end = RK805_IRQ_PWRON_RISE, @@ -205,6 +263,19 @@ static struct resource pwrkey_resources[] = { }, }; +static struct resource rk817_pwrkey_resources[] = { + { + .start = RK817_IRQ_PWRON_RISE, + .end = RK817_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK817_IRQ_PWRON_FALL, + .end = RK817_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource rk816_pwrkey_resources[] = { { .start = RK816_IRQ_PWRON_RISE, @@ -609,8 +680,8 @@ static const struct mfd_cell rk805s[] = { { .name = "rk8xx-gpio", }, { .name = "rk8xx-pwrkey", - .num_resources = ARRAY_SIZE(pwrkey_resources), - .resources = &pwrkey_resources[0], + .num_resources = ARRAY_SIZE(rk805_pwrkey_resources), + .resources = &rk805_pwrkey_resources[0], }, { .name = "rk808-rtc", @@ -635,6 +706,83 @@ static struct rk808_reg_data rk805_resume_reg[] = { {RK805_BUCK3_CONFIG_REG, PWM_MODE_MSK, FPWM_MODE}, }; +#define REGMAP_IRQ_M(_id) \ + [_id] = { \ + .mask = BIT(((_id) % 8)), \ + .reg_offset = ((_id) / 8), \ + } + +static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = { + REGMAP_IRQ_M(0), + REGMAP_IRQ_M(1), + REGMAP_IRQ_M(2), + REGMAP_IRQ_M(3), + REGMAP_IRQ_M(4), + REGMAP_IRQ_M(5), + REGMAP_IRQ_M(6), + REGMAP_IRQ_M(7), + REGMAP_IRQ_M(8), + REGMAP_IRQ_M(9), + REGMAP_IRQ_M(10), + REGMAP_IRQ_M(11), + REGMAP_IRQ_M(12), + REGMAP_IRQ_M(13), + REGMAP_IRQ_M(14), + REGMAP_IRQ_M(15), + REGMAP_IRQ_M(16), + REGMAP_IRQ_M(17), + REGMAP_IRQ_M(18), + REGMAP_IRQ_M(19), + REGMAP_IRQ_M(20), + REGMAP_IRQ_M(21), + REGMAP_IRQ_M(22), + REGMAP_IRQ_M(23) +}; + +static struct regmap_irq_chip rk817_irq_chip = { + .name = "rk817", + .irqs = rk817_irqs, + .num_irqs = ARRAY_SIZE(rk817_irqs), + .num_regs = 3, + .irq_reg_stride = 2, + .status_base = RK817_INT_STS_REG0, + .mask_base = RK817_INT_STS_MSK_REG0, + .ack_base = RK817_INT_STS_REG0, + .init_ack_masked = true, +}; + +static const struct mfd_cell rk817s[] = { + { .name = "rk808-clkout",}, + { .name = "rk808-regulator",}, + { .name = "rk805-pinctrl", }, + { + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), + .resources = &rk817_pwrkey_resources[0], + }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rk817_rtc_resources), + .resources = &rk817_rtc_resources[0], + }, +}; + +static const struct rk808_reg_data rk817_pre_init_reg[] = { + {RK817_SYS_CFG(3), RK817_SLPPIN_FUNC_MSK, SLPPIN_SLP_FUN}, + {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, + {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, + {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, + RK817_HOTDIE_105 | RK817_TSD_140}, +}; + +static struct rk808_reg_data rk817_suspend_reg[] = { + {RK817_BUCK3_ON_VSEL_REG, PWM_MODE_MSK, AUTO_PWM_MODE}, +}; + +static struct rk808_reg_data rk817_resume_reg[] = { + {RK817_BUCK3_ON_VSEL_REG, PWM_MODE_MSK, FPWM_MODE}, +}; + static int (*pm_shutdown)(struct regmap *regmap); static int (*pm_shutdown_prepare)(struct regmap *regmap); static struct i2c_client *rk808_i2c_client; @@ -758,7 +906,9 @@ static struct device_attribute rk8xx_attrs = static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk809" }, { .compatible = "rockchip,rk816" }, + { .compatible = "rockchip,rk817" }, { .compatible = "rockchip,rk818" }, { }, }; @@ -780,6 +930,7 @@ static int rk808_probe(struct i2c_client *client, int msb, lsb, reg_num, cell_num; int ret, i, pm_off = 0; unsigned int on, off; + u8 pmic_id_msb = RK808_ID_MSB, pmic_id_lsb = RK808_ID_LSB; if (!client->irq) { dev_err(&client->dev, "No interrupt support, no core IRQ\n"); @@ -790,15 +941,19 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; + if (of_device_is_compatible(np, "rockchip,rk817")) { + pmic_id_msb = RK817_ID_MSB; + pmic_id_lsb = RK817_ID_LSB; + } /* read Chip variant */ - msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + msb = i2c_smbus_read_byte_data(client, pmic_id_msb); if (msb < 0) { dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); return msb; } - lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb); if (lsb < 0) { dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_LSB); @@ -865,6 +1020,22 @@ static int rk808_probe(struct i2c_client *client, resume_reg = rk805_resume_reg; resume_reg_num = ARRAY_SIZE(rk805_resume_reg); break; + case RK809_ID: + case RK817_ID: + cell = rk817s; + cell_num = ARRAY_SIZE(rk817s); + pre_init_reg = rk817_pre_init_reg; + reg_num = ARRAY_SIZE(rk817_pre_init_reg); + regmap_config = &rk817_regmap_config; + irq_chip = &rk817_irq_chip; + pm_shutdown_prepare_fn = rk817_shutdown_prepare; + on_source = RK817_ON_SOURCE_REG; + off_source = RK817_OFF_SOURCE_REG; + suspend_reg = rk817_suspend_reg; + suspend_reg_num = ARRAY_SIZE(rk817_suspend_reg); + resume_reg = rk817_resume_reg; + resume_reg_num = ARRAY_SIZE(rk817_resume_reg); + break; default: dev_err(&client->dev, "unsupported RK8XX ID 0x%lx\n", rk808->variant); @@ -942,7 +1113,7 @@ static int rk808_probe(struct i2c_client *client, } pm_off = of_property_read_bool(np, - "rockchip,system-power-controller"); + "rockchip,system-power-controller"); if (pm_off) { if (pm_shutdown_prepare_fn) { pm_shutdown_prepare = pm_shutdown_prepare_fn; @@ -1033,7 +1204,9 @@ static const struct dev_pm_ops rk808_pm_ops = { static const struct i2c_device_id rk808_ids[] = { { "rk805" }, { "rk808" }, + { "rk809" }, { "rk816" }, + { "rk817" }, { "rk818" }, { }, }; diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 7c59fb1ea657..f1bbb6c1bc9e 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -114,6 +114,53 @@ .ops = &rk808_reg_ops, \ } +#define RK817_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _enval, _disval, _etime) \ + [_id] = { \ + .name = (_match), \ + .supply_name = (_supply), \ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = (_id), \ + .n_voltages = (((_max) - (_min)) / (_step) + 1), \ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000, \ + .uV_step = (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask = (_emask), \ + .enable_val = (_enval), \ + .disable_val = (_disval), \ + .enable_time = (_etime), \ + .ops = &rk817_reg_ops, \ + } + +#define RK817_BOOST_DESC(_id, _match, _supply, _min, _max, _step, _vreg,\ + _vmask, _ereg, _emask, _enval, _disval, _etime, m_drop) \ + [_id] = { \ + .name = (_match), \ + .supply_name = (_supply), \ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = (_id), \ + .n_voltages = (((_max) - (_min)) / (_step) + 1), \ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000, \ + .uV_step = (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask = (_emask), \ + .enable_val = (_enval), \ + .disable_val = (_disval), \ + .enable_time = (_etime), \ + .min_dropout_uV = (m_drop) * 1000, \ + .ops = &rk817_boost_ops, \ + } + #define RK8XX_DESC_SWITCH(_id, _match, _supply, _ereg, _emask) \ [_id] = { \ .name = (_match), \ @@ -128,6 +175,22 @@ .ops = &rk808_switch_ops \ } +#define RK817_DESC_SWITCH(_id, _match, _supply, _ereg, _emask,\ + _enval, _disval) \ + [_id] = { \ + .name = (_match), \ + .supply_name = (_supply), \ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = (_id), \ + .enable_reg = (_ereg), \ + .enable_mask = (_emask), \ + .enable_val = (_enval), \ + .disable_val = (_disval), \ + .owner = THIS_MODULE, \ + .ops = &rk817_switch_ops \ + } struct rk808_regulator_data { struct gpio_desc *dvs_gpio[2]; @@ -156,6 +219,51 @@ static const struct regulator_linear_range rk816_buck4_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0), /* 3.5v */ }; +#define RK817_BUCK1_MIN0 500000 +#define RK817_BUCK1_MAX0 1500000 + +#define RK817_BUCK1_MIN1 1600000 +#define RK817_BUCK1_MAX1 2400000 + +#define RK817_BUCK3_MAX1 3400000 + +#define RK817_BUCK1_STP0 12500 +#define RK817_BUCK1_STP1 100000 + +#define RK817_BUCK1_SEL0 ((RK817_BUCK1_MAX0 - RK817_BUCK1_MIN0) /\ + RK817_BUCK1_STP0) +#define RK817_BUCK1_SEL1 ((RK817_BUCK1_MAX1 - RK817_BUCK1_MIN1) /\ + RK817_BUCK1_STP1) + +#define RK817_BUCK3_SEL1 ((RK817_BUCK3_MAX1 - RK817_BUCK1_MIN1) /\ + RK817_BUCK1_STP1) + +#define RK817_BUCK1_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK1_SEL1 + 1) +#define RK817_BUCK3_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK3_SEL1 + 1) + +static const struct regulator_linear_range rk817_buck1_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0, + RK817_BUCK1_SEL0, RK817_BUCK1_STP0), + REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1, + RK817_BUCK1_SEL_CNT, RK817_BUCK1_STP1), +}; + +static const struct regulator_linear_range rk817_buck3_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0, + RK817_BUCK1_SEL0, RK817_BUCK1_STP0), + REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1, + RK817_BUCK3_SEL_CNT, RK817_BUCK1_STP1), +}; + +#define RK809_BUCK5_SEL_CNT (8) + +static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1500000, 0, 0, 0), + REGULATOR_LINEAR_RANGE(1800000, 1, 3, 200000), + REGULATOR_LINEAR_RANGE(2800000, 4, 5, 200000), + REGULATOR_LINEAR_RANGE(3300000, 6, 7, 300000), +}; + static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode) { if (mode == 1) @@ -309,8 +417,8 @@ static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev, } static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, - unsigned int new_selector) + unsigned int old_selector, + unsigned int new_selector) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); @@ -349,6 +457,35 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) RK808_RAMP_RATE_MASK, ramp_value); } +/* + * RK817 RK809 + */ +static int rk817_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RK817_RAMP_RATE_25MV_PER_US; + unsigned int reg = RK817_BUCK_CONFIG_REG(rdev_get_id(rdev)); + + switch (ramp_delay) { + case 0 ... 3000: + ramp_value = RK817_RAMP_RATE_3MV_PER_US; + break; + case 3001 ... 6300: + ramp_value = RK817_RAMP_RATE_6_3MV_PER_US; + break; + case 6301 ... 12500: + ramp_value = RK817_RAMP_RATE_12_5MV_PER_US; + break; + case 12501 ... 25000: + break; + default: + pr_warn("%s ramp_delay: %d not supported, setting 10000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, reg, + RK817_RAMP_RATE_MASK, ramp_value); +} + static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv) { unsigned int reg; @@ -364,6 +501,29 @@ static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv) sel); } +static int rk817_check_suspend_voltage(int id) +{ + if (id >= RK817_ID_DCDC1 && id <= RK817_ID_LDO9) + return 0; + return -1; +} + +static int rk817_set_suspend_voltage(struct regulator_dev *rdev, int uv) +{ + unsigned int reg; + int id = rdev_get_id(rdev); + int sel = regulator_map_voltage_linear(rdev, uv, uv); + /* only ldo1~ldo9 */ + if (sel < 0 || rk817_check_suspend_voltage(id)) + return -EINVAL; + + reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->vsel_mask, + sel); +} + static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) { unsigned int reg; @@ -457,6 +617,43 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } +static int rk817_set_suspend_enable_ctrl(struct regulator_dev *rdev, + unsigned int en) +{ + unsigned int reg; + int id = rdev_get_id(rdev); + unsigned int id_slp, msk, val; + + if (id >= RK817_ID_DCDC1 && id <= RK817_ID_DCDC4) + id_slp = id; + else if (id >= RK817_ID_LDO1 && id <= RK817_ID_LDO8) + id_slp = 8 + (id - RK817_ID_LDO1); + else if (id >= RK817_ID_LDO9 && id <= RK809_ID_SW2) + id_slp = 4 + (id - RK817_ID_LDO9); + else + return -EINVAL; + + reg = RK817_POWER_SLP_EN_REG(id_slp / 8); + + msk = BIT(id_slp % 8); + if (en) + val = msk; + else + val = 0; + + return regmap_update_bits(rdev->regmap, reg, msk, val); +} + +static int rk817_set_suspend_enable(struct regulator_dev *rdev) +{ + return rk817_set_suspend_enable_ctrl(rdev, 1); +} + +static int rk817_set_suspend_disable(struct regulator_dev *rdev) +{ + return rk817_set_suspend_enable_ctrl(rdev, 0); +} + static int rk8xx_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) { unsigned int reg; @@ -510,6 +707,29 @@ static unsigned int rk8xx_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } +int rk8xx_is_enabled_wmsk_regmap(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret != 0) + return ret; + + /* add write mask bit */ + val |= (rdev->desc->enable_mask & 0xf0); + val &= rdev->desc->enable_mask; + + if (rdev->desc->enable_is_inverted) { + if (rdev->desc->enable_val) + return val != rdev->desc->enable_val; + return (val == 0); + } + if (rdev->desc->enable_val) + return val == rdev->desc->enable_val; + return val != 0; +} + static struct regulator_ops rk808_buck1_2_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -546,6 +766,38 @@ static struct regulator_ops rk8xx_buck_ops_range = { .set_suspend_disable = rk808_set_suspend_disable, }; +static struct regulator_ops rk817_buck_ops_range = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + .set_mode = rk8xx_set_mode, + .get_mode = rk8xx_get_mode, + .set_suspend_mode = rk8xx_set_suspend_mode, + .set_ramp_delay = rk817_set_ramp_delay, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk817_set_suspend_enable, + .set_suspend_disable = rk817_set_suspend_disable, +}; + +static struct regulator_ops rk809_buck5_ops_range = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk817_set_suspend_enable, + .set_suspend_disable = rk817_set_suspend_disable, +}; + static struct regulator_ops rk808_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -562,6 +814,31 @@ static struct regulator_ops rk808_reg_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static struct regulator_ops rk817_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + .set_suspend_voltage = rk817_set_suspend_voltage, + .set_suspend_enable = rk817_set_suspend_enable, + .set_suspend_disable = rk817_set_suspend_disable, +}; + +static struct regulator_ops rk817_boost_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + .set_suspend_enable = rk817_set_suspend_enable, + .set_suspend_disable = rk817_set_suspend_disable, +}; + static struct regulator_ops rk808_reg_ops_ranges = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, @@ -589,6 +866,14 @@ static struct regulator_ops rk808_switch_ops = { .set_suspend_mode = rk8xx_set_suspend_mode, }; +static struct regulator_ops rk817_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = rk817_set_suspend_enable, + .set_suspend_disable = rk817_set_suspend_disable, +}; + static struct regulator_ops rk816_buck_ops_range = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, @@ -903,10 +1188,284 @@ static const struct regulator_desc rk818_reg[] = { RK818_DCDC_EN_REG, BIT(7)), }; +#define RK817_LDO_VSEL_MASK 0x7f +#define RK817_BOOST_VSEL_MASK 0x7 +#define RK817_BUCK_VSEL_MASK 0x7f +#define RK809_BUCK5_VSEL_MASK 0x7 + +#define ENABLE_MASK(id) (BIT(id) | BIT(4 + (id))) +#define DISABLE_VAL(id) (BIT(4 + (id))) + +static const struct regulator_desc rk817_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .of_match = of_match_ptr("DCDC_REG1"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC1, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK1_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC1), + .enable_val = ENABLE_MASK(RK817_ID_DCDC1), + .disable_val = DISABLE_VAL(RK817_ID_DCDC1), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .of_match = of_match_ptr("DCDC_REG2"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC2, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK2_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC2), + .enable_val = ENABLE_MASK(RK817_ID_DCDC2), + .disable_val = DISABLE_VAL(RK817_ID_DCDC2), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .of_match = of_match_ptr("DCDC_REG3"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC3, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK3_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC3), + .enable_val = ENABLE_MASK(RK817_ID_DCDC3), + .disable_val = DISABLE_VAL(RK817_ID_DCDC3), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .of_match = of_match_ptr("DCDC_REG4"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC4, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK3_SEL_CNT + 1, + .linear_ranges = rk817_buck3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges), + .vsel_reg = RK817_BUCK4_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC4), + .enable_val = ENABLE_MASK(RK817_ID_DCDC4), + .disable_val = DISABLE_VAL(RK817_ID_DCDC4), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, + RK817_DESC(RK817_ID_LDO1, "LDO_REG1", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + RK817_DESC(RK817_ID_LDO2, "LDO_REG2", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(1), ENABLE_MASK(1), + DISABLE_VAL(1), 400), + RK817_DESC(RK817_ID_LDO3, "LDO_REG3", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(2), ENABLE_MASK(2), + DISABLE_VAL(2), 400), + RK817_DESC(RK817_ID_LDO4, "LDO_REG4", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(3), ENABLE_MASK(3), + DISABLE_VAL(3), 400), + RK817_DESC(RK817_ID_LDO5, "LDO_REG5", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + RK817_DESC(RK817_ID_LDO6, "LDO_REG6", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(1), ENABLE_MASK(1), + DISABLE_VAL(1), 400), + RK817_DESC(RK817_ID_LDO7, "LDO_REG7", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(2), ENABLE_MASK(2), + DISABLE_VAL(2), 400), + RK817_DESC(RK817_ID_LDO8, "LDO_REG8", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(3), ENABLE_MASK(3), + DISABLE_VAL(3), 400), + RK817_DESC(RK817_ID_LDO9, "LDO_REG9", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(3), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + RK817_BOOST_DESC(RK817_ID_BOOST, "BOOST", "vcc8", 4700, 5400, 100, + RK817_BOOST_OTG_CFG, RK817_BOOST_VSEL_MASK, + RK817_POWER_EN_REG(3), ENABLE_MASK(1), ENABLE_MASK(1), + DISABLE_VAL(1), 400, 3500 - 5400), + RK817_DESC_SWITCH(RK817_ID_BOOST_OTG_SW, "OTG_SWITCH", "vcc9", + RK817_POWER_EN_REG(3), ENABLE_MASK(2), + ENABLE_MASK(2), DISABLE_VAL(2)), +}; + +static const struct regulator_desc rk809_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .of_match = of_match_ptr("DCDC_REG1"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC1, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK1_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC1), + .enable_val = ENABLE_MASK(RK817_ID_DCDC1), + .disable_val = DISABLE_VAL(RK817_ID_DCDC1), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .of_match = of_match_ptr("DCDC_REG2"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC2, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK2_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC2), + .enable_val = ENABLE_MASK(RK817_ID_DCDC2), + .disable_val = DISABLE_VAL(RK817_ID_DCDC2), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .of_match = of_match_ptr("DCDC_REG3"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC3, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK1_SEL_CNT + 1, + .linear_ranges = rk817_buck1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges), + .vsel_reg = RK817_BUCK3_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC3), + .enable_val = ENABLE_MASK(RK817_ID_DCDC3), + .disable_val = DISABLE_VAL(RK817_ID_DCDC3), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .of_match = of_match_ptr("DCDC_REG4"), + .regulators_node = of_match_ptr("regulators"), + .id = RK817_ID_DCDC4, + .ops = &rk817_buck_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK817_BUCK3_SEL_CNT + 1, + .linear_ranges = rk817_buck3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges), + .vsel_reg = RK817_BUCK4_ON_VSEL_REG, + .vsel_mask = RK817_BUCK_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(0), + .enable_mask = ENABLE_MASK(RK817_ID_DCDC4), + .enable_val = ENABLE_MASK(RK817_ID_DCDC4), + .disable_val = DISABLE_VAL(RK817_ID_DCDC4), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, + + RK817_DESC(RK817_ID_LDO1, "LDO_REG1", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + RK817_DESC(RK817_ID_LDO2, "LDO_REG2", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(1), ENABLE_MASK(1), + DISABLE_VAL(1), 400), + RK817_DESC(RK817_ID_LDO3, "LDO_REG3", "vcc5", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(2), ENABLE_MASK(2), + DISABLE_VAL(2), 400), + RK817_DESC(RK817_ID_LDO4, "LDO_REG4", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(1), ENABLE_MASK(3), ENABLE_MASK(3), + DISABLE_VAL(3), 400), + RK817_DESC(RK817_ID_LDO5, "LDO_REG5", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + RK817_DESC(RK817_ID_LDO6, "LDO_REG6", "vcc6", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(1), ENABLE_MASK(1), + DISABLE_VAL(1), 400), + RK817_DESC(RK817_ID_LDO7, "LDO_REG7", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(2), ENABLE_MASK(2), + DISABLE_VAL(2), 400), + RK817_DESC(RK817_ID_LDO8, "LDO_REG8", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(2), ENABLE_MASK(3), ENABLE_MASK(3), + DISABLE_VAL(3), 400), + RK817_DESC(RK817_ID_LDO9, "LDO_REG9", "vcc7", 600, 3400, 25, + RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK, + RK817_POWER_EN_REG(3), ENABLE_MASK(0), ENABLE_MASK(0), + DISABLE_VAL(0), 400), + { + .name = "DCDC_REG5", + .supply_name = "vcc9", + .of_match = of_match_ptr("DCDC_REG5"), + .regulators_node = of_match_ptr("regulators"), + .id = RK809_ID_DCDC5, + .ops = &rk809_buck5_ops_range, + .type = REGULATOR_VOLTAGE, + .n_voltages = RK809_BUCK5_SEL_CNT, + .linear_ranges = rk809_buck5_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk809_buck5_voltage_ranges), + .vsel_reg = RK809_BUCK5_CONFIG(0), + .vsel_mask = RK809_BUCK5_VSEL_MASK, + .enable_reg = RK817_POWER_EN_REG(3), + .enable_mask = ENABLE_MASK(1), + .enable_val = ENABLE_MASK(1), + .disable_val = DISABLE_VAL(1), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, + RK817_DESC_SWITCH(RK809_ID_SW1, "SWITCH_REG1", "vcc8", + RK817_POWER_EN_REG(3), ENABLE_MASK(2), + ENABLE_MASK(2), DISABLE_VAL(2)), + RK817_DESC_SWITCH(RK809_ID_SW2, "SWITCH_REG2", "vcc9", + RK817_POWER_EN_REG(3), ENABLE_MASK(3), + ENABLE_MASK(3), DISABLE_VAL(3)), +}; + static int rk808_regulator_dt_parse_pdata(struct device *dev, - struct device *client_dev, - struct regmap *map, - struct rk808_regulator_data *pdata) + struct device *client_dev, + struct regmap *map, + struct rk808_regulator_data *pdata) { struct device_node *np; int tmp, ret = 0, i; @@ -967,6 +1526,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk808_reg; nregulators = RK808_NUM_REGULATORS; break; + case RK809_ID: + regulators = rk809_reg; + nregulators = RK809_NUM_REGULATORS; + break; case RK818_ID: regulators = rk818_reg; nregulators = RK818_NUM_REGULATORS; @@ -975,6 +1538,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk816_reg; nregulators = RK816_NUM_REGULATORS; break; + case RK817_ID: + regulators = rk817_reg; + nregulators = RK817_NUM_REGULATORS; + break; default: dev_err(&client->dev, "unsupported RK8XX ID %lu\n", rk808->variant); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 4279e1a144fd..46df77414aeb 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -50,9 +50,18 @@ #define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1) #define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1) +struct rk_rtc_compat_reg { + unsigned int ctrl_reg; + unsigned int status_reg; + unsigned int alarm_seconds_reg; + unsigned int int_reg; + unsigned int seconds_reg; +}; + struct rk808_rtc { struct rk808 *rk808; struct rtc_device *rtc; + struct rk_rtc_compat_reg *creg; int irq; }; @@ -81,6 +90,7 @@ static void gregorian_to_rockchip(struct rtc_time *tm) { time64_t extra_days = nov2dec_transitions(tm); time64_t time = rtc_tm_to_time64(tm); + rtc_time64_to_tm(time - extra_days * 86400, tm); /* Compensate if we went back over Nov 31st (will work up to 2381) */ @@ -101,7 +111,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) int ret; /* Force an update of the shadowed registers right now */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_RTC_GET_TIME, BIT_RTC_CTRL_REG_RTC_GET_TIME); if (ret) { @@ -115,7 +125,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) * 32khz. If we clear the GET_TIME bit here, the time of i2c transfer * certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency. */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_RTC_GET_TIME, 0); if (ret) { @@ -123,7 +133,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG, + ret = regmap_bulk_read(rk808->regmap, rk808_rtc->creg->seconds_reg, rtc_data, NUM_TIME_REGS); if (ret) { dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret); @@ -166,7 +176,7 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_data[6] = bin2bcd(tm->tm_wday); /* Stop RTC while updating the RTC registers */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M, BIT_RTC_CTRL_REG_STOP_RTC_M); if (ret) { @@ -174,14 +184,14 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG, + ret = regmap_bulk_write(rk808->regmap, rk808_rtc->creg->seconds_reg, rtc_data, NUM_TIME_REGS); if (ret) { dev_err(dev, "Failed to bull write rtc_data: %d\n", ret); return ret; } /* Start RTC again */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M, 0); if (ret) { dev_err(dev, "Failed to update RTC control: %d\n", ret); @@ -199,8 +209,13 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) uint32_t int_reg; int ret; - ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG, + ret = regmap_bulk_read(rk808->regmap, + rk808_rtc->creg->alarm_seconds_reg, alrm_data, NUM_ALARM_REGS); + if (ret) { + dev_err(dev, "Failed to read RTC alarm date REG: %d\n", ret); + return ret; + } alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK); alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK); @@ -210,7 +225,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; rockchip_to_gregorian(&alrm->time); - ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); + ret = regmap_read(rk808->regmap, rk808_rtc->creg->int_reg, &int_reg); if (ret) { dev_err(dev, "Failed to read RTC INT REG: %d\n", ret); return ret; @@ -231,7 +246,7 @@ static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) struct rk808 *rk808 = rk808_rtc->rk808; int ret; - ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0); return ret; @@ -242,7 +257,7 @@ static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) struct rk808 *rk808 = rk808_rtc->rk808; int ret; - ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); @@ -274,7 +289,8 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); - ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG, + ret = regmap_bulk_write(rk808->regmap, + rk808_rtc->creg->alarm_seconds_reg, alrm_data, NUM_ALARM_REGS); if (ret) { dev_err(dev, "Failed to bulk write: %d\n", ret); @@ -318,7 +334,7 @@ static irqreturn_t rk808_alarm_irq(int irq, void *data) struct i2c_client *client = rk808->i2c; int ret; - ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg, RTC_STATUS_MASK); if (ret) { dev_err(&client->dev, @@ -328,7 +344,7 @@ static irqreturn_t rk808_alarm_irq(int irq, void *data) rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF); dev_dbg(&client->dev, - "%s:irq=%d\n", __func__, irq); + "%s:irq=%d\n", __func__, irq); return IRQ_HANDLED; } @@ -371,6 +387,22 @@ static int rk808_rtc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops, rk808_rtc_suspend, rk808_rtc_resume); +static struct rk_rtc_compat_reg rk808_creg = { + .ctrl_reg = RK808_RTC_CTRL_REG, + .status_reg = RK808_RTC_STATUS_REG, + .alarm_seconds_reg = RK808_ALARM_SECONDS_REG, + .int_reg = RK808_RTC_INT_REG, + .seconds_reg = RK808_SECONDS_REG, +}; + +static struct rk_rtc_compat_reg rk817_creg = { + .ctrl_reg = RK817_RTC_CTRL_REG, + .status_reg = RK817_RTC_STATUS_REG, + .alarm_seconds_reg = RK817_ALARM_SECONDS_REG, + .int_reg = RK817_RTC_INT_REG, + .seconds_reg = RK817_SECONDS_REG, +}; + static int rk808_rtc_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); @@ -382,8 +414,10 @@ static int rk808_rtc_probe(struct platform_device *pdev) switch (rk808->variant) { case RK805_ID: case RK808_ID: + case RK809_ID: case RK816_ID: case RK818_ID: + case RK817_ID: np = of_get_child_by_name(pdev->dev.parent->of_node, "rtc"); if (np && !of_device_is_available(np)) { dev_info(&pdev->dev, "device is disabled\n"); @@ -395,14 +429,23 @@ static int rk808_rtc_probe(struct platform_device *pdev) } rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL); - if (rk808_rtc == NULL) + if (!rk808_rtc) return -ENOMEM; + switch (rk808->variant) { + case RK809_ID: + case RK817_ID: + rk808_rtc->creg = &rk817_creg; + break; + default: + rk808_rtc->creg = &rk808_creg; + break; + } platform_set_drvdata(pdev, rk808_rtc); rk808_rtc->rk808 = rk808; /* start rtc running by default, and use shadowed timer. */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M | BIT_RTC_CTRL_REG_RTC_READSEL_M, BIT_RTC_CTRL_REG_RTC_READSEL_M); @@ -412,7 +455,7 @@ static int rk808_rtc_probe(struct platform_device *pdev) return ret; } - ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg, RTC_STATUS_MASK); if (ret) { dev_err(&pdev->dev, diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 9ce2cf36363f..fd37ab08beb2 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -766,6 +766,162 @@ enum rk805_reg { #define FPWM_MODE BIT(7) #define AUTO_PWM_MODE 0 +enum rk817_reg_id { + RK817_ID_DCDC1 = 0, + RK817_ID_DCDC2, + RK817_ID_DCDC3, + RK817_ID_DCDC4, + RK817_ID_LDO1, + RK817_ID_LDO2, + RK817_ID_LDO3, + RK817_ID_LDO4, + RK817_ID_LDO5, + RK817_ID_LDO6, + RK817_ID_LDO7, + RK817_ID_LDO8, + RK817_ID_LDO9, + RK817_ID_BOOST, + RK817_ID_BOOST_OTG_SW, + RK817_NUM_REGULATORS +}; + +enum rk809_reg_id { + RK809_ID_DCDC5 = RK817_ID_BOOST, + RK809_ID_SW1, + RK809_ID_SW2, + RK809_NUM_REGULATORS +}; + +#define RK817_SECONDS_REG 0x00 +#define RK817_MINUTES_REG 0x01 +#define RK817_HOURS_REG 0x02 +#define RK817_DAYS_REG 0x03 +#define RK817_MONTHS_REG 0x04 +#define RK817_YEARS_REG 0x05 +#define RK817_WEEKS_REG 0x06 +#define RK817_ALARM_SECONDS_REG 0x07 +#define RK817_ALARM_MINUTES_REG 0x08 +#define RK817_ALARM_HOURS_REG 0x09 +#define RK817_ALARM_DAYS_REG 0x0a +#define RK817_ALARM_MONTHS_REG 0x0b +#define RK817_ALARM_YEARS_REG 0x0c +#define RK817_RTC_CTRL_REG 0xd +#define RK817_RTC_STATUS_REG 0xe +#define RK817_RTC_INT_REG 0xf +#define RK817_RTC_COMP_LSB_REG 0x10 +#define RK817_RTC_COMP_MSB_REG 0x11 + +#define RK817_POWER_EN_REG(i) (0xb1 + (i)) +#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) + +#define RK817_BUCK_CONFIG_REG(i) (0xba + (i) * 3) + +#define RK817_BUCK1_ON_VSEL_REG 0xBB +#define RK817_BUCK1_SLP_VSEL_REG 0xBC + +#define RK817_BUCK2_CONFIG_REG 0xBD +#define RK817_BUCK2_ON_VSEL_REG 0xBE +#define RK817_BUCK2_SLP_VSEL_REG 0xBF + +#define RK817_BUCK3_CONFIG_REG 0xC0 +#define RK817_BUCK3_ON_VSEL_REG 0xC1 +#define RK817_BUCK3_SLP_VSEL_REG 0xC2 + +#define RK817_BUCK4_CONFIG_REG 0xC3 +#define RK817_BUCK4_ON_VSEL_REG 0xC4 +#define RK817_BUCK4_SLP_VSEL_REG 0xC5 + +#define RK817_LDO_ON_VSEL_REG(idx) (0xcc + (idx) * 2) +#define RK817_BOOST_OTG_CFG (0xde) + +#define RK817_ID_MSB 0xed +#define RK817_ID_LSB 0xee + +#define RK817_SYS_STS 0xf0 +#define RK817_SYS_CFG(i) (0xf1 + (i)) + +#define RK817_ON_SOURCE_REG 0xf5 +#define RK817_OFF_SOURCE_REG 0xf6 + +/* INTERRUPT REGISTER */ +#define RK817_INT_STS_REG0 0xf8 +#define RK817_INT_STS_MSK_REG0 0xf9 +#define RK817_INT_STS_REG1 0xfa +#define RK817_INT_STS_MSK_REG1 0xfb +#define RK817_INT_STS_REG2 0xfc +#define RK817_INT_STS_MSK_REG2 0xfd +#define RK817_GPIO_INT_CFG 0xfe + +/* IRQ Definitions */ +#define RK817_IRQ_PWRON_FALL 0 +#define RK817_IRQ_PWRON_RISE 1 +#define RK817_IRQ_PWRON 2 +#define RK817_IRQ_PWMON_LP 3 +#define RK817_IRQ_HOTDIE 4 +#define RK817_IRQ_RTC_ALARM 5 +#define RK817_IRQ_RTC_PERIOD 6 +#define RK817_IRQ_VB_LO 7 +#define RK817_IRQ_PLUG_IN (8 + 0) +#define RK817_IRQ_PLUG_OUT (8 + 1) +#define RK817_IRQ_CHRG_TERM (8 + 2) +#define RK817_IRQ_CHRG_TIME (8 + 3) +#define RK817_IRQ_CHRG_TS (8 + 4) +#define RK817_IRQ_USB_OV (8 + 5) +#define RK817_IRQ_CHRG_IN_CLMP (8 + 6) +#define RK817_IRQ_BAT_DIS_ILIM (8 + 7) +#define RK817_IRQ_GATE_GPIO (16 + 0) +#define RK817_IRQ_TS_GPIO (16 + 1) +#define RK817_IRQ_CODEC_PD (16 + 2) +#define RK817_IRQ_CODEC_PO (16 + 3) +#define RK817_IRQ_CLASSD_MUTE_DONE (16 + 4) +#define RK817_IRQ_CLASSD_OCP (16 + 5) +#define RK817_IRQ_BAT_OVP (16 + 6) +#define RK817_IRQ_CHRG_BAT_HI (16 + 7) +#define RK817_IRQ_END (RK817_IRQ_CHRG_BAT_HI + 1) + +/* + * rtc_ctrl 0xd + * same as 808, except bit4 + */ +#define RK817_RTC_CTRL_RSV4 BIT(4) + +/* buck config 0xba */ +#define RK817_RAMP_RATE_OFFSET 6 +#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET) + +/* sys_cfg1 0xf2 */ +#define RK817_HOTDIE_TEMP_MSK (0x3 << 4) +#define RK817_HOTDIE_85 (0x0 << 4) +#define RK817_HOTDIE_95 (0x1 << 4) +#define RK817_HOTDIE_105 (0x2 << 4) +#define RK817_HOTDIE_115 (0x3 << 4) + +#define RK817_TSD_TEMP_MSK BIT(6) +#define RK817_TSD_140 0 +#define RK817_TSD_160 BIT(6) + +#define RK817_CLK32KOUT2_EN BIT(7) + +/* sys_cfg3 0xf4 */ +#define RK817_SLPPIN_FUNC_MSK (0x3 << 3) +#define SLPPIN_NULL_FUN (0x0 << 3) +#define SLPPIN_SLP_FUN (0x1 << 3) +#define SLPPIN_DN_FUN (0x2 << 3) +#define SLPPIN_RST_FUN (0x3 << 3) + +#define RK817_SLPPOL_MSK BIT(5) +#define RK817_SLPPOL_H BIT(5) + +/* gpio&int 0xfe */ +#define RK817_INT_POL_MSK BIT(1) +#define RK817_INT_POL_H BIT(1) +#define RK817_INT_POL_L 0 +#define RK809_BUCK5_CONFIG(i) (RK817_BOOST_OTG_CFG + (i) * 1) + enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, @@ -799,7 +955,9 @@ struct rk808 { enum { RK805_ID = 0x8050, RK808_ID = 0x0000, + RK809_ID = 0x8090, RK816_ID = 0x8160, + RK817_ID = 0x8170, RK818_ID = 0x8180, }; From 90aca5321d3df0cf093a5097ec0a9e5a3f95fa8b Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Thu, 1 Feb 2018 21:42:37 +0800 Subject: [PATCH 200/427] power: rk817: support rk817 charger driver Change-Id: I2c1aca9706ee43f0b119cf775140a11fdb837e47 Signed-off-by: shengfei Xu --- .../bindings/power/rk817-charger.txt | 37 + drivers/mfd/rk808.c | 1 + drivers/power/Kconfig | 7 + drivers/power/Makefile | 3 +- drivers/power/rk817_charger.c | 1730 +++++++++++++++++ 5 files changed, 1777 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/power/rk817-charger.txt create mode 100644 drivers/power/rk817_charger.c diff --git a/Documentation/devicetree/bindings/power/rk817-charger.txt b/Documentation/devicetree/bindings/power/rk817-charger.txt new file mode 100644 index 000000000000..f45b855cb431 --- /dev/null +++ b/Documentation/devicetree/bindings/power/rk817-charger.txt @@ -0,0 +1,37 @@ +rk817-charger +~~~~~~~~~~ + +Required properties : + - compatible: "rk817,charger" + - min_input_voltage: minimum voltage from adapter + - max_input_current: maximum current from adapter + - max_chrg_current: maximum current for battery charge + - max_chrg_voltage: maximum charge voltage for battery + - chrg_finish_cur: charging termination current + +Optional properties : + - virtual_power: test mode for none battery + - power_dc2otg: dc can provide supply for otg 5v + - dc_det_adc: dc detect by saradc + +Example: + +rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + + ...... + + charger { + compatible = "rk817,charger"; + min_input_voltage = <4500>; + max_input_current = <1500>; + max_chrg_current = <1300>; + max_chrg_voltage = <4200>; + chrg_finish_cur = <300>; + virtual_power = <0>; + dc_det_adc = <0>; + }; + + ...... +}; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index f6a062d30565..c0f79e17e3df 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -755,6 +755,7 @@ static const struct mfd_cell rk817s[] = { { .name = "rk808-clkout",}, { .name = "rk808-regulator",}, { .name = "rk805-pinctrl", }, + { .name = "rk817-charger", .of_compatible = "rk817,charger", }, { .name = "rk8xx-pwrkey", .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 324e18b9bfa2..f73fbc1a9625 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -526,6 +526,13 @@ config BATTERY_RK816 If you say yes here you will get support for the battery of RK816 PMIC. This driver can give support for Rk816 Battery Charge Interface. +config CHARGER_RK817 + bool "RK817 Charger driver" + depends on MFD_RK808 + help + If you say yes here you will get support for the charger of RK817 PMIC. + This driver can give support for Rk817 Charger Interface. + config BATTERY_RK818 bool "RK818 Battery driver" depends on MFD_RK808 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 2d0971161f5b..0ba1d0673509 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_BATTERY_RK816) += rk816_battery.o +obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o obj-$(CONFIG_BATTERY_RK818) += rk818_battery.o obj-$(CONFIG_CHARGER_RK818) += rk818_charger.o obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o @@ -78,4 +79,4 @@ obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o obj-$(CONFIG_POWER_RESET) += reset/ obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o -obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o \ No newline at end of file +obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o diff --git a/drivers/power/rk817_charger.c b/drivers/power/rk817_charger.c new file mode 100644 index 000000000000..01fda7531a4c --- /dev/null +++ b/drivers/power/rk817_charger.c @@ -0,0 +1,1730 @@ +/* + * rk817 charger driver + * + * Copyright (C) 2018 Rockchip Electronics Co., Ltd + * xsf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int dbg_enable; +module_param_named(dbg_level, dbg_enable, int, 0644); + +#define DBG(args...) \ + do { \ + if (dbg_enable) { \ + pr_info(args); \ + } \ + } while (0) + +#define CHARGE_DRIVER_VERSION "1.0" + +#define DISABLE 0x00 +#define ENABLE 0x01 +#define OTG_SLP_ENABLE 0x03 +#define OTG_SLP_DISABLE 0x00 +#define OTG_ENABLE 0x33 +#define OTG_DISABLE 0x30 +#define DEFAULT_INPUT_VOLTAGE 4500 +#define DEFAULT_INPUT_CURRENT 2000 +#define DEFAULT_CHRG_VOLTAGE 4200 +#define DEFAULT_CHRG_CURRENT 1400 +#define DEFAULT_CHRG_TERM_MODE 1 +#define DEFAULT_CHRG_TERM_CUR 150 +#define SAMPLE_RES_10MR 10 +#define SAMPLE_RES_20MR 20 +#define SAMPLE_RES_DIV1 1 +#define SAMPLE_RES_DIV2 2 + +#define INPUT_450MA 450 +#define INPUT_1500MA 1500 + +#define CURRENT_TO_ADC(current, samp_res) \ + (current * 1000 * samp_res / 172) + +enum charge_current { + CHRG_CUR_1000MA, + CHRG_CUR_1500MA, + CHRG_CUR_2000MA, + CHRG_CUR_2500MA, + CHRG_CUR_2750MA, + CHRG_CUR_3000MA, + CHRG_CUR_3500MA, + CHRG_CUR_500MA, +}; + +enum charge_voltage { + CHRG_VOL_4100MV, + CHRG_VOL_4150MV, + CHRG_VOL_4200MV, + CHRG_VOL_4250MV, + CHRG_VOL_4300MV, + CHRG_VOL_4350MV, + CHRG_VOL_4400MV, + CHRG_VOL_4450MV, +}; + +enum input_voltage { + INPUT_VOL_4000MV, + INPUT_VOL_4100MV, + INPUT_VOL_4200MV, + INPUT_VOL_4300MV, + INPUT_VOL_4400MV, + INPUT_VOL_4500MV, + INPUT_VOL_4600MV, + INPUT_VOL_4700MV, +}; + +enum input_current { + INPUT_CUR_450MA, + INPUT_CUR_80MA, + INPUT_CUR_850MA, + INPUT_CUR_1500MA, + INPUT_CUR_1750MA, + INPUT_CUR_2000MA, + INPUT_CUR_2500MA, + INPUT_CUR_3000MA, +}; + +enum charge_clk { + CHRG_CLK_1M, + CHRG_CLK_2M, +}; + +enum charge_term_sel { + CHRG_TERM_150MA, + CHRG_TERM_200MA, + CHRG_TERM_300MA, + CHRG_TERM_400MA, +}; + +enum charge_timer_trickle { + CHRG_TIMER_TRIKL_30MIN, + CHRG_TIMER_TRIKL_45MIN, + CHRG_TIMER_TRIKL_60MIN, + CHRG_TIMER_TRIKL_90MIN, + CHRG_TIMER_TRIKL_120MIN, + CHRG_TIMER_TRIKL_150MIN, + CHRG_TIMER_TRIKL_180MIN, + CHRG_TIMER_TRIKL_210MIN, +}; + +enum charge_timer_cccv { + CHRG_TIMER_CCCV_4H, + CHRG_TIMER_CCCV_5H, + CHRG_TIMER_CCCV_6H, + CHRG_TIMER_CCCV_8H, + CHRG_TIMER_CCCV_10H, + CHRG_TIMER_CCCV_12H, + CHRG_TIMER_CCCV_14H, + CHRG_TIMER_CCCV_16H, +}; + +enum charge_status { + CHRG_OFF, + DEAD_CHRG, + TRICKLE_CHRG, + CC_OR_CV_CHRG, + CHRG_TERM, + USB_OVER_VOL, + BAT_TMP_ERR, + BAT_TIM_ERR, +}; + +enum discharge_ilimit { + DISCHRG_2000MA, + DISCHRG_2500MA, + DISCHRG_3000MA, + DISCHRG_3500MA, + DISCHRG_4000MA, +}; + +enum bat_system_comp_time { + DLY_20US, + DLY_10US, + DLY_40US, + DLY_20US_AGAIN, +}; + +enum charge_term_mode { + CHRG_ANALOG, + CHRG_DIGITAL, +}; + +enum charger_t { + USB_TYPE_UNKNOWN_CHARGER, + USB_TYPE_NONE_CHARGER, + USB_TYPE_USB_CHARGER, + USB_TYPE_AC_CHARGER, + USB_TYPE_CDP_CHARGER, + DC_TYPE_DC_CHARGER, + DC_TYPE_NONE_CHARGER, +}; + +enum rk817_charge_fields { + OTG_EN, OTG_SLP_EN, CHRG_CLK_SEL, + CHRG_EN, CHRG_VOL_SEL, CHRG_CT_EN, CHRG_CUR_SEL, + USB_VLIM_EN, USB_VLIM_SEL, USB_ILIM_EN, USB_ILIM_SEL, + SYS_CAN_SD, USB_SYS_EN, BAT_OVP_EN, CHRG_TERM_ANA_DIG, + CHRG_TERM_ANA_SEL, + CHRG_TERM_DIG, + BAT_HTS_TS, BAT_LTS_TS, + CHRG_TIMER_TRIKL_EN, CHRG_TIMER_TRIKL, + CHRG_TIMER_CCCV_EN, CHRG_TIMER_CCCV, + BAT_EXS, CHG_STS, BAT_OVP_STS, CHRG_IN_CLAMP, + USB_EXS, USB_EFF, + BAT_DIS_ILIM_STS, BAT_SYS_CMP_DLY, BAT_DIS_ILIM_EN, + BAT_DISCHRG_ILIM, + PLUG_IN_STS, SOC_REG, + F_MAX_FIELDS +}; + +static const struct reg_field rk817_charge_reg_fields[] = { + [SOC_REG] = REG_FIELD(0xA5, 0, 6), + [OTG_EN] = REG_FIELD(0xB4, 1, 6), + [OTG_SLP_EN] = REG_FIELD(0xB5, 5, 6), + [CHRG_EN] = REG_FIELD(0xE4, 7, 7), + [CHRG_VOL_SEL] = REG_FIELD(0xE4, 4, 6), + [CHRG_CT_EN] = REG_FIELD(0xE4, 3, 3), + [CHRG_CUR_SEL] = REG_FIELD(0xE4, 0, 2), + + [USB_VLIM_EN] = REG_FIELD(0xE5, 7, 7), + [USB_VLIM_SEL] = REG_FIELD(0xE5, 4, 6), + [USB_ILIM_EN] = REG_FIELD(0xE5, 3, 3), + [USB_ILIM_SEL] = REG_FIELD(0xE5, 0, 2), + + [SYS_CAN_SD] = REG_FIELD(0xE6, 7, 7), + [USB_SYS_EN] = REG_FIELD(0xE6, 6, 6), + [BAT_OVP_EN] = REG_FIELD(0xE6, 3, 3), + [CHRG_TERM_ANA_DIG] = REG_FIELD(0xE6, 2, 2), + [CHRG_TERM_ANA_SEL] = REG_FIELD(0xE6, 0, 1), + + [CHRG_TERM_DIG] = REG_FIELD(0xE7, 0, 7), + + [BAT_HTS_TS] = REG_FIELD(0xE8, 0, 7), + + [BAT_LTS_TS] = REG_FIELD(0xE9, 0, 7), + + [CHRG_TIMER_TRIKL_EN] = REG_FIELD(0xEA, 7, 7), + [CHRG_TIMER_TRIKL] = REG_FIELD(0xEA, 4, 6), + [CHRG_TIMER_CCCV_EN] = REG_FIELD(0xEA, 3, 3), + [CHRG_TIMER_CCCV] = REG_FIELD(0xEA, 0, 2), + + [BAT_EXS] = REG_FIELD(0xEB, 7, 7), + [CHG_STS] = REG_FIELD(0xEB, 4, 6), + [BAT_OVP_STS] = REG_FIELD(0xEB, 3, 3), + [CHRG_IN_CLAMP] = REG_FIELD(0xEB, 2, 2), + [USB_EXS] = REG_FIELD(0xEB, 1, 1), + [USB_EFF] = REG_FIELD(0xEB, 0, 0), + + [BAT_DIS_ILIM_STS] = REG_FIELD(0xEC, 6, 6), + [BAT_SYS_CMP_DLY] = REG_FIELD(0xEC, 4, 5), + [BAT_DIS_ILIM_EN] = REG_FIELD(0xEC, 3, 3), + [BAT_DISCHRG_ILIM] = REG_FIELD(0xEC, 0, 2), + [CHRG_CLK_SEL] = REG_FIELD(0xF3, 6, 6), +}; + +struct charger_platform_data { + u32 max_input_current; + u32 min_input_voltage; + + u32 max_chrg_current; + u32 max_chrg_voltage; + + u32 chrg_finish_cur; + u32 chrg_term_mode; + + u32 power_dc2otg; + u32 dc_det_level; + int dc_det_pin; + bool support_dc_det; + int virtual_power; + int sample_res; + int otg5v_suspend_enable; + bool extcon; +}; + +struct rk817_charger { + struct i2c_client *client; + struct platform_device *pdev; + struct device *dev; + struct rk808 *rk817; + struct regmap *regmap; + struct regmap_field *rmap_fields[F_MAX_FIELDS]; + + struct power_supply *ac_psy; + struct power_supply *usb_psy; + struct extcon_dev *cable_edev; + struct charger_platform_data *pdata; + struct workqueue_struct *usb_charger_wq; + struct workqueue_struct *dc_charger_wq; + struct delayed_work dc_work; + struct delayed_work usb_work; + struct delayed_work host_work; + struct delayed_work discnt_work; + struct delayed_work irq_work; + struct notifier_block bc_nb; + struct notifier_block cable_cg_nb; + struct notifier_block cable_host_nb; + struct notifier_block cable_discnt_nb; + unsigned int bc_event; + enum charger_t usb_charger; + enum charger_t dc_charger; + u8 ac_in; + u8 usb_in; + u8 otg_in; + u8 dc_in; + u8 prop_status; + + u32 max_input_current; + u32 min_input_voltage; + + u32 max_chrg_current; + u32 max_chrg_voltage; + + u32 chrg_finish_cur; + u32 chrg_term_mode; + + u8 res_div; + u8 otg_slp_state; + u8 plugin_trigger; + u8 plugout_trigger; + int plugin_irq; + int plugout_irq; +}; + +static const struct regmap_range rk817_charge_readonly_reg_ranges[] = { + regmap_reg_range(0xEB, 0xEB), +}; + +static const struct regmap_access_table rk817_charge_writeable_regs = { + .no_ranges = rk817_charge_readonly_reg_ranges, + .n_no_ranges = ARRAY_SIZE(rk817_charge_readonly_reg_ranges), +}; + +static const struct regmap_range rk817_charge_volatile_reg_ranges[] = { + regmap_reg_range(0xB4, 0xB4), + regmap_reg_range(0xE4, 0xEA), + regmap_reg_range(0xEC, 0xEC), +}; + +static const struct regmap_access_table rk817_charge_volatile_regs = { + .yes_ranges = rk817_charge_volatile_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(rk817_charge_volatile_reg_ranges), +}; + +static const struct regmap_config rk817_charge_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = 0xFF, + .cache_type = REGCACHE_RBTREE, + .wr_table = &rk817_charge_writeable_regs, + .volatile_table = &rk817_charge_volatile_regs, +}; + +static enum power_supply_property rk817_ac_props[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CURRENT_MAX, +}; + +static enum power_supply_property rk817_usb_props[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CURRENT_MAX, +}; + +static int rk817_charge_ac_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct rk817_charger *charge = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + if (charge->pdata->virtual_power) + val->intval = 1; + else + val->intval = (charge->ac_in | charge->dc_in); + + DBG("report online: %d\n", val->intval); + break; + case POWER_SUPPLY_PROP_STATUS: + if (charge->pdata->virtual_power) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = charge->prop_status; + + DBG("report prop: %d\n", val->intval); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = charge->max_chrg_voltage; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = charge->max_chrg_current; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int rk817_charge_usb_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct rk817_charger *charge = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + if (charge->pdata->virtual_power) + val->intval = 1; + else + val->intval = charge->usb_in; + + DBG("report online: %d\n", val->intval); + break; + case POWER_SUPPLY_PROP_STATUS: + if (charge->pdata->virtual_power) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = charge->prop_status; + + DBG("report prop: %d\n", val->intval); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = charge->max_chrg_voltage; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = charge->max_chrg_current; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct power_supply_desc rk817_ac_desc = { + .name = "ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = rk817_ac_props, + .num_properties = ARRAY_SIZE(rk817_ac_props), + .get_property = rk817_charge_ac_get_property, +}; + +static const struct power_supply_desc rk817_usb_desc = { + .name = "usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = rk817_usb_props, + .num_properties = ARRAY_SIZE(rk817_usb_props), + .get_property = rk817_charge_usb_get_property, +}; + +static int rk817_charge_init_power_supply(struct rk817_charger *charge) +{ + struct power_supply_config psy_cfg = { .drv_data = charge, }; + + charge->usb_psy = devm_power_supply_register(charge->dev, + &rk817_usb_desc, + &psy_cfg); + if (IS_ERR(charge->usb_psy)) { + dev_err(charge->dev, "register usb power supply fail\n"); + return PTR_ERR(charge->usb_psy); + } + + charge->ac_psy = devm_power_supply_register(charge->dev, &rk817_ac_desc, + &psy_cfg); + if (IS_ERR(charge->ac_psy)) { + dev_err(charge->dev, "register ac power supply fail\n"); + return PTR_ERR(charge->ac_psy); + } + + return 0; +} + +static int rk817_charge_field_read(struct rk817_charger *charge, + enum rk817_charge_fields field_id) +{ + int ret; + int val; + + ret = regmap_field_read(charge->rmap_fields[field_id], &val); + if (ret < 0) + return ret; + + return val; +} + +static int rk817_charge_field_write(struct rk817_charger *charge, + enum rk817_charge_fields field_id, + unsigned int val) +{ + return regmap_field_write(charge->rmap_fields[field_id], val); +} + +static int rk817_charge_get_otg_state(struct rk817_charger *charge) +{ + return (rk817_charge_field_read(charge, OTG_EN) & 0x03); +} + +static void rk817_charge_otg_disable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, OTG_EN, OTG_DISABLE); +} + +static void rk817_charge_otg_enable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, OTG_EN, OTG_ENABLE); +} + +static int rk817_charge_get_otg_slp_state(struct rk817_charger *charge) +{ + return (rk817_charge_field_read(charge, OTG_SLP_EN) & OTG_SLP_ENABLE); +} + +static void rk817_charge_otg_slp_disable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, OTG_SLP_EN, OTG_SLP_DISABLE); +} + +static void rk817_charge_otg_slp_enable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, OTG_SLP_EN, OTG_SLP_ENABLE); +} + +static int rk817_charge_get_charge_state(struct rk817_charger *charge) +{ + return rk817_charge_field_read(charge, CHRG_EN); +} + +static void rk817_charge_enable_charge(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, CHRG_EN, ENABLE); +} + +static void rk817_charge_usb_to_sys_enable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, USB_SYS_EN, ENABLE); +} + +static int rk817_charge_get_charge_status(struct rk817_charger *charge) +{ + int status; + + status = rk817_charge_field_read(charge, CHG_STS); + + switch (status) { + case CHRG_OFF: + DBG("charge off...\n"); + break; + case DEAD_CHRG: + DBG("dead charge...\n"); + break; + case TRICKLE_CHRG: + DBG("trickle charge...\n"); + break; + case CC_OR_CV_CHRG: + DBG("CC or CV charge...\n"); + break; + case CHRG_TERM: + DBG("charge TERM...\n"); + break; + case USB_OVER_VOL: + DBG("USB over voltage...\n"); + break; + case BAT_TMP_ERR: + DBG("battery temperature error...\n"); + break; + case BAT_TIM_ERR: + DBG("battery timer error..\n"); + break; + default: + break; + } + + return status; +} + +static int rk817_charge_get_plug_in_status(struct rk817_charger *charge) +{ + return rk817_charge_field_read(charge, PLUG_IN_STS); +} + +static void rk817_charge_set_charge_clock(struct rk817_charger *charge, + enum charge_clk clock) +{ + rk817_charge_field_write(charge, CHRG_CLK_SEL, clock); +} + +static int is_battery_exist(struct rk817_charger *charge) +{ + return rk817_charge_field_read(charge, BAT_EXS); +} + +static void rk817_charge_set_chrg_voltage(struct rk817_charger *charge, + int chrg_vol) +{ + int voltage; + + if (chrg_vol < 4100 || chrg_vol > 4500) { + dev_err(charge->dev, "the charge voltage is error!\n"); + } else { + voltage = (chrg_vol - 4100) / 50; + rk817_charge_field_write(charge, + CHRG_VOL_SEL, + CHRG_VOL_4100MV + voltage); + } +} + +static void rk817_charge_set_chrg_current(struct rk817_charger *charge, + int chrg_current) +{ + if (chrg_current < 500 || chrg_current > 3500) + dev_err(charge->dev, "the charge current is error!\n"); + + if (chrg_current < 1000) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_500MA); + else if (chrg_current < 1500) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_1000MA); + else if (chrg_current < 2000) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_1500MA); + else if (chrg_current < 2500) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_2000MA); + else if (chrg_current < 3000) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_2500MA); + else if (chrg_current < 3500) + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_3000MA); + else + rk817_charge_field_write(charge, CHRG_CUR_SEL, CHRG_CUR_3500MA); +} + +static void rk817_charge_vlimit_enable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, USB_VLIM_EN, ENABLE); +} + +static void rk817_charge_set_input_voltage(struct rk817_charger *charge, + int input_voltage) +{ + int voltage; + + if (input_voltage < 4000) + dev_err(charge->dev, "the input voltage is error.\n"); + + voltage = INPUT_VOL_4000MV + (input_voltage - 4000) / 100; + + rk817_charge_field_write(charge, USB_VLIM_SEL, voltage); + rk817_charge_vlimit_enable(charge); +} + +static void rk817_charge_ilimit_enable(struct rk817_charger *charge) +{ + rk817_charge_field_write(charge, USB_ILIM_EN, ENABLE); +} + +static void rk817_charge_set_input_current(struct rk817_charger *charge, + int input_current) +{ + if (input_current < 80 || input_current > 3000) + dev_err(charge->dev, "the input current is error.\n"); + + if (input_current < 450) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_80MA); + else if (input_current < 850) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_450MA); + else if (input_current < 1500) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_850MA); + else if (input_current < 1750) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_1500MA); + else if (input_current < 2000) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_1750MA); + else if (input_current < 2500) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_2000MA); + else if (input_current < 3000) + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_2500MA); + else + rk817_charge_field_write(charge, USB_ILIM_SEL, + INPUT_CUR_3000MA); + + rk817_charge_ilimit_enable(charge); +} + +static void rk817_charge_set_chrg_term_mod(struct rk817_charger *charge, + int mode) +{ + rk817_charge_field_write(charge, CHRG_TERM_ANA_DIG, mode); +} + +static void rk817_charge_set_term_current_analog(struct rk817_charger *charge, + int chrg_current) +{ + int value; + + if (chrg_current < 150) + chrg_current = 150; + if (chrg_current > 400) + chrg_current = 400; + + value = (chrg_current - 150) / 50; + rk817_charge_field_write(charge, + CHRG_TERM_ANA_SEL, + CHRG_TERM_150MA + value); +} + +static void rk817_charge_set_term_current_digital(struct rk817_charger *charge, + int chrg_current) +{ + int value; + u8 current_adc; + + value = CURRENT_TO_ADC(chrg_current, charge->res_div); + + value &= (0xff << 5); + current_adc = value >> 5; + rk817_charge_field_write(charge, CHRG_TERM_DIG, current_adc); +} + +static void rk817_charge_set_chrg_finish_condition(struct rk817_charger *charge) +{ + if (charge->chrg_term_mode == CHRG_ANALOG) + rk817_charge_set_term_current_analog(charge, + charge->chrg_finish_cur); + else + rk817_charge_set_term_current_digital(charge, + charge->chrg_finish_cur); + + rk817_charge_set_chrg_term_mod(charge, charge->chrg_term_mode); +} + +static int rk817_charge_online(struct rk817_charger *charge) +{ + return (charge->ac_in | charge->usb_in | charge->dc_in); +} + +static int rk817_charge_get_dsoc(struct rk817_charger *charge) +{ + return rk817_charge_field_read(charge, SOC_REG); +} + +static void rk817_charge_set_chrg_param(struct rk817_charger *charge, + enum charger_t charger) +{ + switch (charger) { + case USB_TYPE_NONE_CHARGER: + charge->usb_in = 0; + charge->ac_in = 0; + if (charge->dc_in == 0) { + charge->prop_status = POWER_SUPPLY_STATUS_DISCHARGING; + rk817_charge_set_input_current(charge, INPUT_450MA); + } + power_supply_changed(charge->usb_psy); + power_supply_changed(charge->ac_psy); + break; + case USB_TYPE_USB_CHARGER: + charge->usb_in = 1; + charge->ac_in = 0; + charge->prop_status = POWER_SUPPLY_STATUS_CHARGING; + if (charge->dc_in == 0) + rk817_charge_set_input_current(charge, INPUT_450MA); + power_supply_changed(charge->usb_psy); + power_supply_changed(charge->ac_psy); + break; + case USB_TYPE_AC_CHARGER: + case USB_TYPE_CDP_CHARGER: + charge->ac_in = 1; + charge->usb_in = 0; + charge->prop_status = POWER_SUPPLY_STATUS_CHARGING; + if (charger == USB_TYPE_AC_CHARGER) + rk817_charge_set_input_current(charge, + charge->max_input_current); + else + rk817_charge_set_input_current(charge, + INPUT_1500MA); + power_supply_changed(charge->usb_psy); + power_supply_changed(charge->ac_psy); + break; + case DC_TYPE_DC_CHARGER: + charge->dc_in = 1; + charge->prop_status = POWER_SUPPLY_STATUS_CHARGING; + rk817_charge_set_input_current(charge, + charge->max_input_current); + power_supply_changed(charge->usb_psy); + power_supply_changed(charge->ac_psy); + break; + case DC_TYPE_NONE_CHARGER: + charge->dc_in = 0; + if (!rk817_charge_get_plug_in_status(charge)) { + charge->ac_in = 0; + charge->usb_in = 0; + charge->prop_status = POWER_SUPPLY_STATUS_DISCHARGING; + rk817_charge_set_input_current(charge, INPUT_450MA); + } else if (charge->usb_in) { + rk817_charge_set_input_current(charge, INPUT_450MA); + charge->prop_status = POWER_SUPPLY_STATUS_CHARGING; + } + power_supply_changed(charge->usb_psy); + power_supply_changed(charge->ac_psy); + break; + default: + charge->prop_status = POWER_SUPPLY_STATUS_DISCHARGING; + rk817_charge_set_input_current(charge, INPUT_450MA); + break; + } + + if (rk817_charge_online(charge) && rk817_charge_get_dsoc(charge) == 100) + charge->prop_status = POWER_SUPPLY_STATUS_FULL; +} + +static void rk817_charge_set_otg_state(struct rk817_charger *charge, int state) +{ + switch (state) { + case USB_OTG_POWER_ON: + if (charge->otg_in) { + DBG("otg5v is on yet, ignore..\n"); + } else { + charge->otg_in = 1; + + if (!rk817_charge_get_otg_state(charge)) { + rk817_charge_otg_enable(charge); + if (!rk817_charge_get_otg_state(charge)) { + DBG("enable otg5v failed\n"); + return; + } + } + disable_irq(charge->plugin_irq); + disable_irq(charge->plugout_irq); + DBG("enable otg5v\n"); + } + break; + + case USB_OTG_POWER_OFF: + if (!charge->otg_in) { + DBG("otg5v is off yet, ignore..\n"); + } else { + charge->otg_in = 0; + + if (rk817_charge_get_otg_state(charge)) { + rk817_charge_otg_disable(charge); + if (rk817_charge_get_otg_state(charge)) { + DBG("disable otg5v failed\n"); + return; + } + } + enable_irq(charge->plugin_irq); + enable_irq(charge->plugout_irq); + DBG("disable otg5v\n"); + } + break; + default: + dev_err(charge->dev, "error otg type\n"); + break; + } +} + +static irqreturn_t rk817_charge_dc_det_isr(int irq, void *charger) +{ + struct rk817_charger *charge = (struct rk817_charger *)charger; + + if (gpio_get_value(charge->pdata->dc_det_pin)) + irq_set_irq_type(irq, IRQF_TRIGGER_LOW); + else + irq_set_irq_type(irq, IRQF_TRIGGER_HIGH); + + queue_delayed_work(charge->dc_charger_wq, &charge->dc_work, + msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static enum charger_t rk817_charge_get_dc_state(struct rk817_charger *charge) +{ + int level; + + if (!gpio_is_valid(charge->pdata->dc_det_pin)) + return DC_TYPE_NONE_CHARGER; + + level = gpio_get_value(charge->pdata->dc_det_pin); + + return (level == charge->pdata->dc_det_level) ? + DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER; +} + +static void rk817_charge_dc_det_worker(struct work_struct *work) +{ + enum charger_t charger; + struct rk817_charger *charge = container_of(work, + struct rk817_charger, dc_work.work); + + charger = rk817_charge_get_dc_state(charge); + if (charger == DC_TYPE_DC_CHARGER) { + DBG("detect dc charger in..\n"); + rk817_charge_set_chrg_param(charge, DC_TYPE_DC_CHARGER); + /* check otg supply */ + if (charge->otg_in && charge->pdata->power_dc2otg) { + DBG("otg power from dc adapter\n"); + rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF); + } + } else { + DBG("detect dc charger out..\n"); + rk817_charge_set_chrg_param(charge, DC_TYPE_NONE_CHARGER); + /* check otg supply, power on anyway */ + if (charge->otg_in) + rk817_charge_set_otg_state(charge, USB_OTG_POWER_ON); + } +} + +static int rk817_charge_init_dc(struct rk817_charger *charge) +{ + int ret, level; + unsigned long irq_flags; + unsigned int dc_det_irq; + + charge->dc_charger_wq = alloc_ordered_workqueue("%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, + "rk817-dc-wq"); + INIT_DELAYED_WORK(&charge->dc_work, rk817_charge_dc_det_worker); + charge->dc_charger = DC_TYPE_NONE_CHARGER; + + if (!charge->pdata->support_dc_det) + return 0; + + ret = devm_gpio_request(charge->dev, + charge->pdata->dc_det_pin, + "rk817_dc_det"); + if (ret < 0) { + dev_err(charge->dev, "failed to request gpio %d\n", + charge->pdata->dc_det_pin); + return ret; + } + + ret = gpio_direction_input(charge->pdata->dc_det_pin); + if (ret) { + dev_err(charge->dev, "failed to set gpio input\n"); + return ret; + } + + level = gpio_get_value(charge->pdata->dc_det_pin); + if (level == charge->pdata->dc_det_level) + charge->dc_charger = DC_TYPE_DC_CHARGER; + else + charge->dc_charger = DC_TYPE_NONE_CHARGER; + + if (level) + irq_flags = IRQF_TRIGGER_LOW; + else + irq_flags = IRQF_TRIGGER_HIGH; + + dc_det_irq = gpio_to_irq(charge->pdata->dc_det_pin); + ret = devm_request_irq(charge->dev, dc_det_irq, rk817_charge_dc_det_isr, + irq_flags, "rk817_dc_det", charge); + if (ret != 0) { + dev_err(charge->dev, "rk817_dc_det_irq request failed!\n"); + return ret; + } + + enable_irq_wake(dc_det_irq); + + if (charge->dc_charger != DC_TYPE_NONE_CHARGER) + rk817_charge_set_chrg_param(charge, charge->dc_charger); + + return 0; +} + +static void rk817_charge_host_evt_worker(struct work_struct *work) +{ + struct rk817_charger *charge = container_of(work, + struct rk817_charger, host_work.work); + struct extcon_dev *edev = charge->cable_edev; + + /* Determine cable/charger type */ + if (extcon_get_cable_state_(edev, EXTCON_USB_VBUS_EN) > 0) { + DBG("receive type-c notifier event: OTG ON...\n"); + if (charge->dc_in && charge->pdata->power_dc2otg) + DBG("otg power from dc adapter\n"); + else + rk817_charge_set_otg_state(charge, USB_OTG_POWER_ON); + } else if (extcon_get_cable_state_(edev, EXTCON_USB_VBUS_EN) == 0) { + DBG("receive type-c notifier event: OTG OFF...\n"); + rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF); + } +} + +static void rk817_charger_evt_worker(struct work_struct *work) +{ + struct rk817_charger *charge = container_of(work, + struct rk817_charger, usb_work.work); + struct extcon_dev *edev = charge->cable_edev; + enum charger_t charger = USB_TYPE_UNKNOWN_CHARGER; + static const char * const event[] = {"UN", "NONE", "USB", + "AC", "CDP1.5A"}; + + /* Determine cable/charger type */ + if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) + charger = USB_TYPE_USB_CHARGER; + else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) + charger = USB_TYPE_AC_CHARGER; + else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) + charger = USB_TYPE_CDP_CHARGER; + + if (charger != USB_TYPE_UNKNOWN_CHARGER) { + DBG("receive type-c notifier event: %s...\n", + event[charger]); + charge->usb_charger = charger; + rk817_charge_set_chrg_param(charge, charger); + } +} + +static void rk817_charge_discnt_evt_worker(struct work_struct *work) +{ + struct rk817_charger *charge = container_of(work, + struct rk817_charger, discnt_work.work); + + if (extcon_get_cable_state_(charge->cable_edev, EXTCON_USB) == 0) { + DBG("receive type-c notifier event: DISCNT...\n"); + + rk817_charge_set_chrg_param(charge, USB_TYPE_NONE_CHARGER); + } +} + +static void rk817_charge_bc_evt_worker(struct work_struct *work) +{ + struct rk817_charger *charge = container_of(work, + struct rk817_charger, + usb_work.work); + static const char * const event_name[] = {"DISCNT", "USB", "AC", + "CDP1.5A", "UNKNOWN", + "OTG ON", "OTG OFF"}; + + switch (charge->bc_event) { + case USB_BC_TYPE_DISCNT: + rk817_charge_set_chrg_param(charge, USB_TYPE_NONE_CHARGER); + break; + case USB_BC_TYPE_SDP: + rk817_charge_set_chrg_param(charge, USB_TYPE_USB_CHARGER); + break; + case USB_BC_TYPE_DCP: + rk817_charge_set_chrg_param(charge, USB_TYPE_AC_CHARGER); + break; + case USB_BC_TYPE_CDP: + rk817_charge_set_chrg_param(charge, USB_TYPE_CDP_CHARGER); + break; + case USB_OTG_POWER_ON: + if (charge->pdata->power_dc2otg && charge->dc_in) + DBG("otg power from dc adapter\n"); + else + rk817_charge_set_otg_state(charge, USB_OTG_POWER_ON); + break; + case USB_OTG_POWER_OFF: + rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF); + break; + default: + break; + } + + DBG("receive bc notifier event: %s..\n", event_name[charge->bc_event]); +} + +static int rk817_charger_evt_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct rk817_charger *charge = + container_of(nb, struct rk817_charger, cable_cg_nb); + + queue_delayed_work(charge->usb_charger_wq, &charge->usb_work, + msecs_to_jiffies(10)); + + return NOTIFY_DONE; +} + +static int rk817_charge_host_evt_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct rk817_charger *charge = + container_of(nb, struct rk817_charger, cable_discnt_nb); + + queue_delayed_work(charge->usb_charger_wq, &charge->discnt_work, + msecs_to_jiffies(10)); + + return NOTIFY_DONE; +} + +static int rk817_charge_discnt_evt_notfier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct rk817_charger *charge = + container_of(nb, struct rk817_charger, cable_discnt_nb); + + queue_delayed_work(charge->usb_charger_wq, &charge->discnt_work, + msecs_to_jiffies(10)); + + return NOTIFY_DONE; +} + +static int rk817_charge_bc_evt_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct rk817_charger *charge = + container_of(nb, struct rk817_charger, bc_nb); + + charge->bc_event = event; + queue_delayed_work(charge->usb_charger_wq, &charge->usb_work, + msecs_to_jiffies(10)); + + return NOTIFY_DONE; +} + +static int rk817_charge_usb_init(struct rk817_charger *charge) +{ + enum charger_t charger; + enum bc_port_type bc_type; + struct extcon_dev *edev; + struct device *dev = charge->dev; + int ret; + + charge->usb_charger_wq = alloc_ordered_workqueue("%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, + "rk817-usb-wq"); + + /* type-C */ + if (charge->pdata->extcon) { + edev = extcon_get_edev_by_phandle(dev, 0); + if (IS_ERR(edev)) { + if (PTR_ERR(edev) != -EPROBE_DEFER) + dev_err(dev, "Invalid or missing extcon\n"); + return PTR_ERR(edev); + } + + /* Register chargers */ + INIT_DELAYED_WORK(&charge->usb_work, rk817_charger_evt_worker); + charge->cable_cg_nb.notifier_call = rk817_charger_evt_notifier; + ret = extcon_register_notifier(edev, EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + if (ret < 0) { + dev_err(dev, "failed to register notifier for SDP\n"); + return ret; + } + + ret = extcon_register_notifier(edev, EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + if (ret < 0) { + dev_err(dev, "failed to register notifier for DCP\n"); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + return ret; + } + + ret = extcon_register_notifier(edev, EXTCON_CHG_USB_CDP, + &charge->cable_cg_nb); + if (ret < 0) { + dev_err(dev, "failed to register notifier for CDP\n"); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + return ret; + } + + /* Register host */ + INIT_DELAYED_WORK(&charge->host_work, + rk817_charge_host_evt_worker); + charge->cable_host_nb.notifier_call = + rk817_charge_host_evt_notifier; + ret = extcon_register_notifier(edev, EXTCON_USB_VBUS_EN, + &charge->cable_host_nb); + if (ret < 0) { + dev_err(dev, "failed to register notifier for HOST\n"); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_CDP, + &charge->cable_cg_nb); + + return ret; + } + + /* Register discnt usb */ + INIT_DELAYED_WORK(&charge->discnt_work, + rk817_charge_discnt_evt_worker); + charge->cable_discnt_nb.notifier_call = + rk817_charge_discnt_evt_notfier; + ret = extcon_register_notifier(edev, EXTCON_USB, + &charge->cable_discnt_nb); + if (ret < 0) { + dev_err(dev, "failed to register notifier for HOST\n"); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_CHG_USB_CDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(edev, EXTCON_USB_VBUS_EN, + &charge->cable_host_nb); + return ret; + } + + charge->cable_edev = edev; + + schedule_delayed_work(&charge->host_work, 0); + schedule_delayed_work(&charge->usb_work, 0); + DBG("register typec extcon evt notifier\n"); + } else { + INIT_DELAYED_WORK(&charge->usb_work, + rk817_charge_bc_evt_worker); + charge->bc_nb.notifier_call = rk817_charge_bc_evt_notifier; + ret = rk_bc_detect_notifier_register(&charge->bc_nb, &bc_type); + if (ret) { + dev_err(dev, "failed to register notifier for bc\n"); + return -EINVAL; + } + + switch (bc_type) { + case USB_BC_TYPE_DISCNT: + charger = USB_TYPE_NONE_CHARGER; + break; + case USB_BC_TYPE_SDP: + case USB_BC_TYPE_CDP: + charger = USB_TYPE_USB_CHARGER; + break; + case USB_BC_TYPE_DCP: + charger = USB_TYPE_AC_CHARGER; + break; + default: + charger = USB_TYPE_NONE_CHARGER; + break; + } + + charge->usb_charger = charger; + if (charge->dc_charger != DC_TYPE_NONE_CHARGER) + rk817_charge_set_chrg_param(charge, + charge->usb_charger); + + DBG("register bc evt notifier\n"); + } + + return 0; +} + +static void rk817_charge_pre_init(struct rk817_charger *charge) +{ + charge->max_chrg_current = charge->pdata->max_chrg_current; + charge->max_input_current = charge->pdata->max_input_current; + charge->max_chrg_voltage = charge->pdata->max_chrg_voltage; + charge->min_input_voltage = charge->pdata->min_input_voltage; + charge->chrg_finish_cur = charge->pdata->chrg_finish_cur; + charge->chrg_term_mode = charge->pdata->chrg_term_mode; + + rk817_charge_set_input_voltage(charge, charge->min_input_voltage); + + rk817_charge_set_chrg_voltage(charge, charge->max_chrg_voltage); + rk817_charge_set_chrg_current(charge, charge->max_chrg_current); + + rk817_charge_set_chrg_finish_condition(charge); + + rk817_charge_otg_disable(charge); + + rk817_charge_usb_to_sys_enable(charge); + rk817_charge_enable_charge(charge); + + rk817_charge_set_charge_clock(charge, CHRG_CLK_2M); +} + +static void rk817_chage_debug(struct rk817_charger *charge) +{ + rk817_charge_get_charge_status(charge); + DBG("OTG state : %d\n", rk817_charge_get_otg_state(charge)); + DBG("charge state: %d\n", rk817_charge_get_charge_state(charge)); + DBG("max_chrg_current: %d\n" + "max_input_current: %d\n" + "min_input_voltage: %d\n" + "max_chrg_voltage: %d\n" + "max_chrg_finish_cur: %d\n" + "chrg_term_mode: %d\n", + charge->max_chrg_current, + charge->max_input_current, + charge->min_input_voltage, + charge->max_chrg_voltage, + charge->chrg_finish_cur, + charge->chrg_term_mode); +} + +#ifdef CONFIG_OF +static int rk817_charge_parse_dt(struct rk817_charger *charge) +{ + struct charger_platform_data *pdata; + enum of_gpio_flags flags; + struct device *dev = charge->dev; + struct device_node *np = charge->dev->of_node; + int ret; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + charge->pdata = pdata; + pdata->max_chrg_current = DEFAULT_CHRG_CURRENT; + pdata->max_input_current = DEFAULT_INPUT_CURRENT; + pdata->max_chrg_voltage = DEFAULT_CHRG_VOLTAGE; + pdata->min_input_voltage = DEFAULT_INPUT_VOLTAGE; + pdata->chrg_finish_cur = DEFAULT_CHRG_TERM_CUR; + pdata->chrg_term_mode = DEFAULT_CHRG_TERM_MODE; + + pdata->extcon = of_property_read_bool(np, "extcon"); + + ret = of_property_read_u32(np, "max_chrg_current", + &pdata->max_chrg_current); + if (ret < 0) + dev_err(dev, "max_chrg_current missing!\n"); + + ret = of_property_read_u32(np, "max_input_current", + &pdata->max_input_current); + if (ret < 0) + dev_err(dev, "max_input_current missing!\n"); + + ret = of_property_read_u32(np, "max_chrg_voltage", + &pdata->max_chrg_voltage); + if (ret < 0) + dev_err(dev, "max_chrg_voltage missing!\n"); + + ret = of_property_read_u32(np, "min_input_voltage", + &pdata->min_input_voltage); + if (ret < 0) + dev_WARN(dev, "min_input_voltage missing!\n"); + + ret = of_property_read_u32(np, "chrg_finish_cur", + &pdata->chrg_finish_cur); + + if (ret < 0) + dev_WARN(dev, "chrg_term_mode missing!\n"); + + ret = of_property_read_u32(np, "chrg_term_mode", + &pdata->chrg_term_mode); + if (ret < 0) + dev_WARN(dev, "chrg_term_mode missing!\n"); + + ret = of_property_read_u32(np, "virtual_power", &pdata->virtual_power); + if (ret < 0) + dev_err(dev, "virtual_power missing!\n"); + + ret = of_property_read_u32(np, "power_dc2otg", &pdata->power_dc2otg); + if (ret < 0) + dev_err(dev, "power_dc2otg missing!\n"); + + ret = of_property_read_u32(np, "sample_res", &pdata->sample_res); + if (ret < 0) { + pdata->sample_res = SAMPLE_RES_10MR; + dev_err(dev, "sample_res missing!\n"); + } + + ret = of_property_read_u32(np, "otg5v_suspend_enable", + &pdata->otg5v_suspend_enable); + if (ret < 0) { + pdata->otg5v_suspend_enable = 1; + dev_err(dev, "otg5v_suspend_enable missing!\n"); + } + + if (!is_battery_exist(charge)) + pdata->virtual_power = 1; + + charge->res_div = (charge->pdata->sample_res == SAMPLE_RES_10MR) ? + SAMPLE_RES_DIV1 : SAMPLE_RES_DIV2; + + if (!of_find_property(np, "dc_det_gpio", &ret)) { + pdata->support_dc_det = false; + DBG("not support dc\n"); + } else { + pdata->support_dc_det = true; + pdata->dc_det_pin = of_get_named_gpio_flags(np, "dc_det_gpio", + 0, &flags); + if (gpio_is_valid(pdata->dc_det_pin)) { + DBG("support dc\n"); + pdata->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW) ? + 0 : 1; + } else { + dev_err(dev, "invalid dc det gpio!\n"); + return -EINVAL; + } + } + + DBG("input_current:%d\n" + "input_min_voltage: %d\n" + "chrg_current:%d\n" + "chrg_voltage:%d\n" + "sample_res:%d\n" + "extcon:%d\n" + "virtual_power:%d\n" + "power_dc2otg:%d\n", + pdata->max_input_current, pdata->min_input_voltage, + pdata->max_chrg_current, pdata->max_chrg_voltage, + pdata->sample_res, pdata->extcon, + pdata->virtual_power, pdata->power_dc2otg); + + return 0; +} +#else +static int rk817_charge_parse_dt(struct rk817_charger *charge) +{ + return -ENODEV; +} +#endif + +static void rk817_charge_irq_delay_work(struct work_struct *work) +{ + struct rk817_charger *charge = container_of(work, + struct rk817_charger, irq_work.work); + + if (charge->plugin_trigger) { + DBG("pmic: plug in\n"); + charge->plugin_trigger = 0; + if (charge->pdata->extcon) + queue_delayed_work(charge->usb_charger_wq, &charge->usb_work, + msecs_to_jiffies(10)); + } else if (charge->plugout_trigger) { + DBG("pmic: plug out\n"); + charge->plugout_trigger = 0; + rk817_charge_set_chrg_param(charge, USB_TYPE_NONE_CHARGER); + rk817_charge_set_chrg_param(charge, DC_TYPE_NONE_CHARGER); + } else { + DBG("pmic: unknown irq\n"); + } +} + +static irqreturn_t rk817_plug_in_isr(int irq, void *cg) +{ + struct rk817_charger *charge; + + charge = (struct rk817_charger *)cg; + charge->plugin_trigger = 1; + queue_delayed_work(charge->usb_charger_wq, &charge->irq_work, + msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static irqreturn_t rk817_plug_out_isr(int irq, void *cg) +{ + struct rk817_charger *charge; + + charge = (struct rk817_charger *)cg; + charge->plugout_trigger = 1; + queue_delayed_work(charge->usb_charger_wq, &charge->irq_work, + msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static int rk817_charge_init_irqs(struct rk817_charger *charge) +{ + struct rk808 *rk817 = charge->rk817; + struct platform_device *pdev = charge->pdev; + int ret, plug_in_irq, plug_out_irq; + + plug_in_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_IN); + if (plug_in_irq < 0) { + dev_err(charge->dev, "plug_in_irq request failed!\n"); + return plug_in_irq; + } + + plug_out_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_OUT); + if (plug_out_irq < 0) { + dev_err(charge->dev, "plug_out_irq request failed!\n"); + return plug_out_irq; + } + + ret = devm_request_threaded_irq(charge->dev, plug_in_irq, NULL, + rk817_plug_in_isr, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rk817_plug_in", charge); + if (ret) { + dev_err(&pdev->dev, "plug_in_irq request failed!\n"); + return ret; + } + + ret = devm_request_threaded_irq(charge->dev, plug_out_irq, NULL, + rk817_plug_out_isr, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rk817_plug_out", charge); + if (ret) { + dev_err(&pdev->dev, "plug_out_irq request failed!\n"); + return ret; + } + + charge->plugin_irq = plug_in_irq; + charge->plugout_irq = plug_out_irq; + + INIT_DELAYED_WORK(&charge->irq_work, rk817_charge_irq_delay_work); + + return 0; +} + +static const struct of_device_id rk817_charge_of_match[] = { + { .compatible = "rk817,charger", }, + { }, +}; + +static int rk817_charge_probe(struct platform_device *pdev) +{ + struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent); + const struct of_device_id *of_id = + of_match_device(rk817_charge_of_match, &pdev->dev); + struct i2c_client *client = rk817->i2c; + struct rk817_charger *charge; + int i; + int ret; + + if (!of_id) { + dev_err(&pdev->dev, "Failed to find matching dt id\n"); + return -ENODEV; + } + + charge = devm_kzalloc(&pdev->dev, sizeof(*charge), GFP_KERNEL); + if (!charge) + return -EINVAL; + + charge->rk817 = rk817; + charge->pdev = pdev; + charge->dev = &pdev->dev; + charge->client = client; + platform_set_drvdata(pdev, charge); + + charge->regmap = devm_regmap_init_i2c(client, + &rk817_charge_regmap_config); + if (IS_ERR(charge->regmap)) { + dev_err(charge->dev, "Failed to initialize regmap\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(rk817_charge_reg_fields); i++) { + const struct reg_field *reg_fields = rk817_charge_reg_fields; + + charge->rmap_fields[i] = + devm_regmap_field_alloc(charge->dev, + charge->regmap, + reg_fields[i]); + if (IS_ERR(charge->rmap_fields[i])) { + dev_err(charge->dev, "cannot allocate regmap field\n"); + return PTR_ERR(charge->rmap_fields[i]); + } + } + + ret = rk817_charge_parse_dt(charge); + if (ret < 0) { + dev_err(charge->dev, "charge parse dt failed!\n"); + return ret; + } + + rk817_charge_pre_init(charge); + + ret = rk817_charge_init_dc(charge); + if (ret) { + dev_err(charge->dev, "init dc failed!\n"); + return ret; + } + + ret = rk817_charge_usb_init(charge); + if (ret) { + dev_err(charge->dev, "init usb failed!\n"); + return ret; + } + ret = rk817_charge_init_power_supply(charge); + if (ret) { + dev_err(charge->dev, "init power supply fail!\n"); + return ret; + } + + ret = rk817_charge_init_irqs(charge); + if (ret) { + dev_err(charge->dev, "init irqs failed!\n"); + goto irq_fail; + } + + rk817_chage_debug(charge); + DBG("driver version: %s\n", CHARGE_DRIVER_VERSION); + + return 0; +irq_fail: + if (charge->pdata->extcon) { + cancel_delayed_work_sync(&charge->host_work); + cancel_delayed_work_sync(&charge->discnt_work); + } + + cancel_delayed_work_sync(&charge->usb_work); + cancel_delayed_work_sync(&charge->dc_work); + cancel_delayed_work_sync(&charge->irq_work); + destroy_workqueue(charge->usb_charger_wq); + destroy_workqueue(charge->dc_charger_wq); + + if (charge->pdata->extcon) { + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_CDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_USB_VBUS_EN, + &charge->cable_host_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_USB, + &charge->cable_discnt_nb); + } else { + rk_bc_detect_notifier_unregister(&charge->bc_nb); + } + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int rk817_charge_pm_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk817_charger *charge = dev_get_drvdata(&pdev->dev); + + charge->otg_slp_state = rk817_charge_get_otg_slp_state(charge); + + /* enable sleep boost5v and otg5v */ + if (charge->pdata->otg5v_suspend_enable) { + if ((charge->otg_in && !charge->dc_in) || + (charge->otg_in && charge->dc_in && + !charge->pdata->power_dc2otg)) { + rk817_charge_otg_slp_enable(charge); + DBG("suspend: otg 5v on\n"); + return 0; + } + } + + /* disable sleep otg5v */ + rk817_charge_otg_slp_disable(charge); + DBG("suspend: otg 5v off\n"); + return 0; +} + +static int rk817_charge_pm_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk817_charger *charge = dev_get_drvdata(&pdev->dev); + + /* resume sleep boost5v and otg5v */ + if (charge->otg_slp_state) + rk817_charge_otg_slp_enable(charge); + + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(rk817_charge_pm_ops, + rk817_charge_pm_suspend, rk817_charge_pm_resume); + +static void rk817_charger_shutdown(struct platform_device *dev) +{ + struct rk817_charger *charge = platform_get_drvdata(dev); + + /* type-c only */ + if (charge->pdata->extcon) { + cancel_delayed_work_sync(&charge->host_work); + cancel_delayed_work_sync(&charge->discnt_work); + } + + rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF); + disable_irq(charge->plugin_irq); + disable_irq(charge->plugout_irq); + + cancel_delayed_work_sync(&charge->usb_work); + cancel_delayed_work_sync(&charge->dc_work); + cancel_delayed_work_sync(&charge->irq_work); + flush_workqueue(charge->usb_charger_wq); + flush_workqueue(charge->dc_charger_wq); + + if (charge->pdata->extcon) { + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_SDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_DCP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_CHG_USB_CDP, + &charge->cable_cg_nb); + extcon_unregister_notifier(charge->cable_edev, + EXTCON_USB_VBUS_EN, + &charge->cable_host_nb); + extcon_unregister_notifier(charge->cable_edev, EXTCON_USB, + &charge->cable_discnt_nb); + } else { + rk_bc_detect_notifier_unregister(&charge->bc_nb); + } + + DBG("shutdown: ac=%d usb=%d dc=%d otg=%d\n", + charge->ac_in, charge->usb_in, charge->dc_in, charge->otg_in); +} + +static struct platform_driver rk817_charge_driver = { + .probe = rk817_charge_probe, + .shutdown = rk817_charger_shutdown, + .driver = { + .name = "rk817-charger", + .pm = &rk817_charge_pm_ops, + .of_match_table = of_match_ptr(rk817_charge_of_match), + }, +}; + +static int __init rk817_charge_init(void) +{ + return platform_driver_register(&rk817_charge_driver); +} +fs_initcall_sync(rk817_charge_init); + +static void __exit rk817_charge_exit(void) +{ + platform_driver_unregister(&rk817_charge_driver); +} +module_exit(rk817_charge_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("shengfeixu "); +MODULE_DESCRIPTION("rk817 charge driver"); From 828352f6ebd595359ac37fb6c2229e2b80814cc7 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Thu, 1 Feb 2018 21:53:27 +0800 Subject: [PATCH 201/427] arm64: rockchip_defconfig: enable CONFIG_CHARGER_RK817 Change-Id: I49ad5dcddb06e17e9e9eaa03992851cdf159732d Signed-off-by: shengfei Xu --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 24bdcfb18ee4..0ac303b9548e 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -425,6 +425,7 @@ CONFIG_TEST_POWER=y CONFIG_CHARGER_BQ25700=y CONFIG_BATTERY_EC=y CONFIG_BATTERY_CW2015=y +CONFIG_CHARGER_RK817=y CONFIG_BATTERY_RK818=y CONFIG_CHARGER_RK818=y CONFIG_POWER_RESET_GPIO=y From 92e570a84f96e97904abb95fa7c62c812d13b34f Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Mon, 5 Feb 2018 14:31:48 +0800 Subject: [PATCH 202/427] power: rk817: support rk817 battery driver Change-Id: Ie0e2f4baab33949506ef835e068a10610863ab73 Signed-off-by: shengfei Xu --- .../bindings/power_supply/rk817-battery.txt | 49 + drivers/mfd/rk808.c | 1 + drivers/power/Kconfig | 7 + drivers/power/Makefile | 1 + drivers/power/rk817_battery.c | 2383 +++++++++++++++++ 5 files changed, 2441 insertions(+) create mode 100644 Documentation/devicetree/bindings/power_supply/rk817-battery.txt create mode 100644 drivers/power/rk817_battery.c diff --git a/Documentation/devicetree/bindings/power_supply/rk817-battery.txt b/Documentation/devicetree/bindings/power_supply/rk817-battery.txt new file mode 100644 index 000000000000..68b98ccabfb9 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/rk817-battery.txt @@ -0,0 +1,49 @@ +rk817-battery +~~~~~~~~~~ + +Required properties : + - compatible: "rk817,battery" + - ocv_table: ocv voltage and soc relation table + - design_capacity: real capacity tested by tool + - design_qmax: nominal capacity * 1.1 + +Optional properties : + - sleep_enter_current: current threshold of enter relax mode + - sleep_exit_current: current threshold of exit relax mode + - sleep_filter_current: current threshold of valid relax mode + - power_off_thresd: vsys voltage threshold of power off + - zero_algorithm_vol: voltage threshold of discharge zero algorithm + - max_soc_offset: soc threshold of correct dsoc as rsoc + - monitor_sec: poll seconds for battery delay work + - virtual_power: test mode for none battery + - energy_mode: try to use all power of battery + +Example: + +rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + + ...... + + battery { + compatible = "rk817,battery"; + ocv_table = <3400 3654 3686 3710 3744 3775 3803 + 3825 3843 3858 3870 3886 3955 3988 + 4010 4023 4032 4049 4080 4151>; + design_capacity = <2000>; + design_qmax = <2200>; + bat_res = <120>; + sleep_enter_current = <300>; + sleep_exit_current = <300>; + sleep_filter_current = <100>; + power_off_thresd = <3500>; + zero_algorithm_vol = <3800>; + max_soc_offset = <60>; + monitor_sec = <5>; + virtual_power = <0>; + energy_mode = <0>; + }; + + ...... +}; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index c0f79e17e3df..fd9adae77a42 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -755,6 +755,7 @@ static const struct mfd_cell rk817s[] = { { .name = "rk808-clkout",}, { .name = "rk808-regulator",}, { .name = "rk805-pinctrl", }, + { .name = "rk817-battery", .of_compatible = "rk817,battery", }, { .name = "rk817-charger", .of_compatible = "rk817,charger", }, { .name = "rk8xx-pwrkey", diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f73fbc1a9625..93db0e67be60 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -526,6 +526,13 @@ config BATTERY_RK816 If you say yes here you will get support for the battery of RK816 PMIC. This driver can give support for Rk816 Battery Charge Interface. +config BATTERY_RK817 + bool "RK817 Battery driver" + depends on MFD_RK808 + help + If you say yes here you will get support for the battery of RK817 PMIC. + This driver can give support for Rk817 Battery Interface. + config CHARGER_RK817 bool "RK817 Charger driver" depends on MFD_RK808 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 0ba1d0673509..4c922bb80110 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_BATTERY_RK816) += rk816_battery.o +obj-$(CONFIG_BATTERY_RK817) += rk817_battery.o obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o obj-$(CONFIG_BATTERY_RK818) += rk818_battery.o obj-$(CONFIG_CHARGER_RK818) += rk818_charger.o diff --git a/drivers/power/rk817_battery.c b/drivers/power/rk817_battery.c new file mode 100644 index 000000000000..aa9163d62c40 --- /dev/null +++ b/drivers/power/rk817_battery.c @@ -0,0 +1,2383 @@ +/* + * rk817 battery driver + * + * Copyright (C) 2018 Rockchip Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int dbg_enable; + +module_param_named(dbg_level, dbg_enable, int, 0644); + +#define DBG(args...) \ + do { \ + if (dbg_enable) { \ + pr_info(args); \ + } \ + } while (0) + +#define BAT_INFO(fmt, args...) pr_info("rk817-bat: "fmt, ##args) + +#define DRIVER_VERSION "1.00" +#define SFT_SET_KB 1 + +#define DIV(x) ((x) ? (x) : 1) +#define ENABLE 0x01 +#define DISABLE 0x00 +#define MAX_INTERPOLATE 1000 +#define MAX_PERCENTAGE 100 +#define MAX_INT 0x7FFF + +/* RK818_GGCON */ +#define OCV_SAMP_MIN_MSK 0x0c +#define OCV_SAMP_8MIN (0x00 << 2) + +#define ADC_CAL_8MIN 0x00 +#define RELAX_VOL12_UPD_MSK (RELAX_VOL1_UPD | RELAX_VOL2_UPD) +#define MINUTE(x) \ + ((x) * 60) + +#define ADC_TO_CURRENT(adc_value, samp_res) \ + (adc_value * 172 / 1000 / samp_res) +#define CURRENT_TO_ADC(current, samp_res) \ + (current * 1000 * samp_res / 172) + +#define ADC_TO_CAPACITY(adc_value, samp_res) \ + (adc_value / 1000 * 172 / 3600 / samp_res) +#define CAPACITY_TO_ADC(capacity, samp_res) \ + (capacity * samp_res * 3600 / 172 * 1000) + +#define ADC_TO_CAPACITY_UAH(adc_value, samp_res) \ + (adc_value / 3600 * 172 / samp_res) +#define ADC_TO_CAPACITY_MAH(adc_value, samp_res) \ + (adc_value / 1000 * 172 / 3600 / samp_res) + +/* THREAML_REG */ +#define TEMP_85C (0x00 << 2) +#define TEMP_95C (0x01 << 2) +#define TEMP_105C (0x02 << 2) +#define TEMP_115C (0x03 << 2) + +#define ZERO_LOAD_LVL1 1400 +#define ZERO_LOAD_LVL2 600 + +/* zero algorithm */ +#define PWROFF_THRESD 3400 +#define MIN_ZERO_DSOC_ACCURACY 10 /*0.01%*/ +#define MIN_ZERO_OVERCNT 100 +#define MIN_ACCURACY 1 +#define DEF_PWRPATH_RES 50 +#define WAIT_DSOC_DROP_SEC 15 +#define WAIT_SHTD_DROP_SEC 30 +#define MIN_ZERO_GAP_XSOC1 10 +#define MIN_ZERO_GAP_XSOC2 5 +#define MIN_ZERO_GAP_XSOC3 3 +#define MIN_ZERO_GAP_CALIB 5 + +#define ADC_CALIB_THRESHOLD 4 +#define ADC_CALIB_LMT_MIN 3 +#define ADC_CALIB_CNT 5 + +/* default param */ +#define DEFAULT_BAT_RES 135 +#define DEFAULT_SLP_ENTER_CUR 300 +#define DEFAULT_SLP_EXIT_CUR 300 +#define DEFAULT_SLP_FILTER_CUR 100 +#define DEFAULT_PWROFF_VOL_THRESD 3400 +#define DEFAULT_MONITOR_SEC 5 +#define DEFAULT_ALGR_VOL_THRESD1 3850 +#define DEFAULT_ALGR_VOL_THRESD2 3950 +#define DEFAULT_CHRG_VOL_SEL CHRG_VOL4200MV +#define DEFAULT_CHRG_CUR_SEL CHRG_CUR1400MA +#define DEFAULT_CHRG_CUR_INPUT INPUT_CUR2000MA +#define DEFAULT_POFFSET 42 +#define DEFAULT_MAX_SOC_OFFSET 60 +#define DEFAULT_FB_TEMP TEMP_115C +#define DEFAULT_ENERGY_MODE 0 +#define DEFAULT_ZERO_RESERVE_DSOC 10 +#define DEFAULT_SAMPLE_RES 20 + +/* sample resistor and division */ +#define SAMPLE_RES_10MR 10 +#define SAMPLE_RES_20MR 20 +#define SAMPLE_RES_DIV1 1 +#define SAMPLE_RES_DIV2 2 + +#define TIMER_MS_COUNTS 1000 +/* fcc */ +#define MIN_FCC 500 + +/* virtual params */ +#define VIRTUAL_CURRENT 1000 +#define VIRTUAL_VOLTAGE 3888 +#define VIRTUAL_SOC 66 +#define VIRTUAL_PRESET 1 +#define VIRTUAL_TEMPERATURE 188 +#define VIRTUAL_STATUS POWER_SUPPLY_STATUS_CHARGING + +enum work_mode { + MODE_ZERO = 0, + MODE_FINISH, + MODE_SMOOTH_CHRG, + MODE_SMOOTH_DISCHRG, + MODE_SMOOTH, +}; + +enum bat_mode { + MODE_BATTARY = 0, + MODE_VIRTUAL, +}; + +enum rk817_sample_time { + S_8_MIN, + S_16_MIN, + S_32_MIN, + S_48_MIN, +}; + +enum rk817_output_mode { + AVERAGE_MODE, + INSTANT_MODE, +}; + +enum rk817_battery_fields { + ADC_SLP_RATE, BAT_CUR_ADC_EN, BAT_VOL_ADC_EN, + USB_VOL_ADC_EN, TS_ADC_EN, SYS_VOL_ADC_EN, GG_EN, /*ADC_CONFIG0*/ + CUR_ADC_DITH_SEL, CUR_ADC_DIH_EN, CUR_ADC_CHOP_EN, + CUR_ADC_CHOP_SEL, CUR_ADC_CHOP_VREF_EN, /*CUR_ADC_CFG0*/ + CUR_ADC_VCOM_SEL, CUR_ADC_VCOM_BUF_INC, CUR_ADC_VREF_BUF_INC, + CUR_ADC_BIAS_DEC, CUR_ADC_IBIAS_SEL,/*CUR_ADC_CFG1*/ + VOL_ADC_EXT_VREF_EN, VOL_ADC_DITH_SEL, VOL_ADC_DITH_EN, + VOL_ADC_CHOP_EN, VOL_ADC_CHOP_SEL, VOL_ADC_CHOP_VREF_EN, + VOL_ADC_VCOM_SEL, VOL_ADC_VCOM_BUF_INC, VOL_ADC_VREF_BUF_INC, + VOL_ADC_IBIAS_SEL, /*VOL_ADC_CFG1*/ + RLX_CUR_FILTER, TS_FUN, VOL_ADC_TSCUR_SEL, + VOL_CALIB_UPD, CUR_CALIB_UPD, /*ADC_CONFIG1*/ + CUR_OUT_MOD, VOL_OUT_MOD, FRAME_SMP_INTERV, + ADC_OFF_CAL_INTERV, RLX_SPT, /*GG_CON*/ + OCV_UPD, RELAX_STS, RELAX_VOL2_UPD, RELAX_VOL1_UPD, BAT_CON, + QMAX_UPD_SOFT, TERM_UPD, OCV_STS, /*GG_STS*/ + RELAX_THRE_H, RELAX_THRE_L, /*RELAX_THRE*/ + RELAX_VOL1_H, RELAX_VOL1_L, + RELAX_VOL2_H, RELAX_VOL2_L, + RELAX_CUR1_H, RELAX_CUR1_L, + RELAX_CUR2_H, RELAX_CUR2_L, + OCV_THRE_VOL, + OCV_VOL_H, OCV_VOL_L, + OCV_VOL0_H, OCV_VOL0_L, + OCV_CUR_H, OCV_CUR_L, + OCV_CUR0_H, OCV_CUR0_L, + PWRON_VOL_H, PWRON_VOL_L, + PWRON_CUR_H, PWRON_CUR_L, + OFF_CNT, + Q_INIT_H3, Q_INIT_H2, Q_INIT_L1, Q_INIT_L0, + Q_PRESS_H3, Q_PRESS_H2, Q_PRESS_L1, Q_PRESS_L0, + BAT_VOL_H, BAT_VOL_L, + BAT_CUR_H, BAT_CUR_L, + BAT_TS_H, BAT_TS_L, + USB_VOL_H, USB_VOL_L, + SYS_VOL_H, SYS_VOL_L, + Q_MAX_H3, Q_MAX_H2, Q_MAX_L1, Q_MAX_L0, + Q_TERM_H3, Q_TERM_H2, Q_TERM_L1, Q_TERM_L0, + Q_OCV_H3, Q_OCV_H2, Q_OCV_L1, Q_OCV_L0, + OCV_CNT, + SLEEP_CON_SAMP_CUR_H, SLEEP_CON_SAMP_CUR_L, + CAL_OFFSET_H, CAL_OFFSET_L, + VCALIB0_H, VCALIB0_L, + VCALIB1_H, VCALIB1_L, + IOFFSET_H, IOFFSET_L, + BAT_R0, BAT_R1, BAT_R2, BAT_R3, + REMAIN_CAP_REG2, REMAIN_CAP_REG1, REMAIN_CAP_REG0, + NEW_FCC_REG2, NEW_FCC_REG1, NEW_FCC_REG0, + RESET_MODE, + SOC_REG, FG_INIT, HALT_CNT_REG, CALC_REST_REGL, CALC_REST_REGH, + VOL_ADC_B3, VOL_ADC_B2, VOL_ADC_B1, VOL_ADC_B0, + VOL_ADC_K3, VOL_ADC_K2, VOL_ADC_K1, VOL_ADC_K0, + CHIP_NAME_H, CHIP_NAME_L, + F_MAX_FIELDS +}; + +static const struct reg_field rk817_battery_reg_fields[] = { + [ADC_SLP_RATE] = REG_FIELD(0x50, 0, 0), + [BAT_CUR_ADC_EN] = REG_FIELD(0x50, 2, 2), + [BAT_VOL_ADC_EN] = REG_FIELD(0x50, 3, 3), + [USB_VOL_ADC_EN] = REG_FIELD(0x50, 4, 4), + [TS_ADC_EN] = REG_FIELD(0x50, 5, 5), + [SYS_VOL_ADC_EN] = REG_FIELD(0x50, 6, 6), + [GG_EN] = REG_FIELD(0x50, 7, 7),/*ADC_CONFIG0*/ + + [CUR_ADC_DITH_SEL] = REG_FIELD(0x51, 1, 3), + [CUR_ADC_DIH_EN] = REG_FIELD(0x51, 4, 4), + [CUR_ADC_CHOP_EN] = REG_FIELD(0x51, 5, 5), + [CUR_ADC_CHOP_SEL] = REG_FIELD(0x51, 6, 6), + [CUR_ADC_CHOP_VREF_EN] = REG_FIELD(0x51, 7, 7), /*CUR_ADC_COFG0*/ + + [CUR_ADC_VCOM_SEL] = REG_FIELD(0x52, 0, 1), + [CUR_ADC_VCOM_BUF_INC] = REG_FIELD(0x52, 2, 2), + [CUR_ADC_VREF_BUF_INC] = REG_FIELD(0x52, 3, 3), + [CUR_ADC_BIAS_DEC] = REG_FIELD(0x52, 4, 4), + [CUR_ADC_IBIAS_SEL] = REG_FIELD(0x52, 5, 6), /*CUR_ADC_COFG1*/ + + [VOL_ADC_EXT_VREF_EN] = REG_FIELD(0x53, 0, 0), + [VOL_ADC_DITH_SEL] = REG_FIELD(0x53, 1, 3), + [VOL_ADC_DITH_EN] = REG_FIELD(0x53, 4, 4), + [VOL_ADC_CHOP_EN] = REG_FIELD(0x53, 5, 5), + [VOL_ADC_CHOP_SEL] = REG_FIELD(0x53, 6, 6), + [VOL_ADC_CHOP_VREF_EN] = REG_FIELD(0x53, 7, 7),/*VOL_ADC_COFG0*/ + + [VOL_ADC_VCOM_SEL] = REG_FIELD(0x54, 0, 1), + [VOL_ADC_VCOM_BUF_INC] = REG_FIELD(0x54, 2, 2), + [VOL_ADC_VREF_BUF_INC] = REG_FIELD(0x54, 3, 3), + [VOL_ADC_IBIAS_SEL] = REG_FIELD(0x54, 5, 6), /*VOL_ADC_COFG1*/ + + [RLX_CUR_FILTER] = REG_FIELD(0x55, 0, 1), + [TS_FUN] = REG_FIELD(0x55, 3, 3), + [VOL_ADC_TSCUR_SEL] = REG_FIELD(0x55, 4, 5), + [VOL_CALIB_UPD] = REG_FIELD(0x55, 6, 6), + [CUR_CALIB_UPD] = REG_FIELD(0x55, 7, 7), /*ADC_CONFIG1*/ + + [CUR_OUT_MOD] = REG_FIELD(0x56, 0, 0), + [VOL_OUT_MOD] = REG_FIELD(0x56, 1, 1), + [FRAME_SMP_INTERV] = REG_FIELD(0x56, 2, 3), + [ADC_OFF_CAL_INTERV] = REG_FIELD(0x56, 4, 5), + [RLX_SPT] = REG_FIELD(0x56, 6, 7), /*GG_CON*/ + + [OCV_UPD] = REG_FIELD(0x57, 0, 0), + [RELAX_STS] = REG_FIELD(0x57, 1, 1), + [RELAX_VOL2_UPD] = REG_FIELD(0x57, 2, 2), + [RELAX_VOL1_UPD] = REG_FIELD(0x57, 3, 3), + [BAT_CON] = REG_FIELD(0x57, 4, 4), + [QMAX_UPD_SOFT] = REG_FIELD(0x57, 5, 5), + [TERM_UPD] = REG_FIELD(0x57, 6, 6), + [OCV_STS] = REG_FIELD(0x57, 7, 7), /*GG_STS*/ + + [RELAX_THRE_H] = REG_FIELD(0x58, 0, 7), + [RELAX_THRE_L] = REG_FIELD(0x59, 0, 7), + + [RELAX_VOL1_H] = REG_FIELD(0x5A, 0, 7), + [RELAX_VOL1_L] = REG_FIELD(0x5B, 0, 7), + [RELAX_VOL2_H] = REG_FIELD(0x5C, 0, 7), + [RELAX_VOL2_L] = REG_FIELD(0x5D, 0, 7), + + [RELAX_CUR1_H] = REG_FIELD(0x5E, 0, 7), + [RELAX_CUR1_L] = REG_FIELD(0x5F, 0, 7), + [RELAX_CUR2_H] = REG_FIELD(0x60, 0, 7), + [RELAX_CUR2_L] = REG_FIELD(0x61, 0, 7), + + [OCV_THRE_VOL] = REG_FIELD(0x62, 0, 7), + + [OCV_VOL_H] = REG_FIELD(0x63, 0, 7), + [OCV_VOL_L] = REG_FIELD(0x64, 0, 7), + [OCV_VOL0_H] = REG_FIELD(0x65, 0, 7), + [OCV_VOL0_L] = REG_FIELD(0x66, 0, 7), + [OCV_CUR_H] = REG_FIELD(0x67, 0, 7), + [OCV_CUR_L] = REG_FIELD(0x68, 0, 7), + [OCV_CUR0_H] = REG_FIELD(0x69, 0, 7), + [OCV_CUR0_L] = REG_FIELD(0x6A, 0, 7), + [PWRON_VOL_H] = REG_FIELD(0x6B, 0, 7), + [PWRON_VOL_L] = REG_FIELD(0x6C, 0, 7), + [PWRON_CUR_H] = REG_FIELD(0x6D, 0, 7), + [PWRON_CUR_L] = REG_FIELD(0x6E, 0, 7), + [OFF_CNT] = REG_FIELD(0x6F, 0, 7), + [Q_INIT_H3] = REG_FIELD(0x70, 0, 7), + [Q_INIT_H2] = REG_FIELD(0x71, 0, 7), + [Q_INIT_L1] = REG_FIELD(0x72, 0, 7), + [Q_INIT_L0] = REG_FIELD(0x73, 0, 7), + + [Q_PRESS_H3] = REG_FIELD(0x74, 0, 7), + [Q_PRESS_H2] = REG_FIELD(0x75, 0, 7), + [Q_PRESS_L1] = REG_FIELD(0x76, 0, 7), + [Q_PRESS_L0] = REG_FIELD(0x77, 0, 7), + + [BAT_VOL_H] = REG_FIELD(0x78, 0, 7), + [BAT_VOL_L] = REG_FIELD(0x79, 0, 7), + + [BAT_CUR_H] = REG_FIELD(0x7A, 0, 7), + [BAT_CUR_L] = REG_FIELD(0x7B, 0, 7), + + [BAT_TS_H] = REG_FIELD(0x7C, 0, 7), + [BAT_TS_L] = REG_FIELD(0x7D, 0, 7), + [USB_VOL_H] = REG_FIELD(0x7E, 0, 7), + [USB_VOL_L] = REG_FIELD(0x7F, 0, 7), + + [SYS_VOL_H] = REG_FIELD(0x80, 0, 7), + [SYS_VOL_L] = REG_FIELD(0x81, 0, 7), + [Q_MAX_H3] = REG_FIELD(0x82, 0, 7), + [Q_MAX_H2] = REG_FIELD(0x83, 0, 7), + [Q_MAX_L1] = REG_FIELD(0x84, 0, 7), + [Q_MAX_L0] = REG_FIELD(0x85, 0, 7), + + [Q_TERM_H3] = REG_FIELD(0x86, 0, 7), + [Q_TERM_H2] = REG_FIELD(0x87, 0, 7), + [Q_TERM_L1] = REG_FIELD(0x88, 0, 7), + [Q_TERM_L0] = REG_FIELD(0x89, 0, 7), + [Q_OCV_H3] = REG_FIELD(0x8A, 0, 7), + [Q_OCV_H2] = REG_FIELD(0x8B, 0, 7), + + [Q_OCV_L1] = REG_FIELD(0x8C, 0, 7), + [Q_OCV_L0] = REG_FIELD(0x8D, 0, 7), + [OCV_CNT] = REG_FIELD(0x8E, 0, 7), + [SLEEP_CON_SAMP_CUR_H] = REG_FIELD(0x8F, 0, 7), + [SLEEP_CON_SAMP_CUR_L] = REG_FIELD(0x90, 0, 7), + [CAL_OFFSET_H] = REG_FIELD(0x91, 0, 7), + [CAL_OFFSET_L] = REG_FIELD(0x92, 0, 7), + [VCALIB0_H] = REG_FIELD(0x93, 0, 7), + [VCALIB0_L] = REG_FIELD(0x94, 0, 7), + [VCALIB1_H] = REG_FIELD(0x95, 0, 7), + [VCALIB1_L] = REG_FIELD(0x96, 0, 7), + [IOFFSET_H] = REG_FIELD(0x97, 0, 7), + [IOFFSET_L] = REG_FIELD(0x98, 0, 7), + + [BAT_R0] = REG_FIELD(0x99, 0, 7), + [BAT_R1] = REG_FIELD(0x9A, 0, 7), + [BAT_R2] = REG_FIELD(0x9B, 0, 7), + [BAT_R3] = REG_FIELD(0x9C, 0, 7), + + [REMAIN_CAP_REG0] = REG_FIELD(0x9D, 0, 7), + [REMAIN_CAP_REG1] = REG_FIELD(0x9E, 0, 7), + [REMAIN_CAP_REG2] = REG_FIELD(0x9F, 0, 7), + [NEW_FCC_REG0] = REG_FIELD(0xA0, 0, 7), + [NEW_FCC_REG1] = REG_FIELD(0xA1, 0, 7), + [NEW_FCC_REG2] = REG_FIELD(0xA2, 0, 7), + [RESET_MODE] = REG_FIELD(0xA3, 0, 3), + [SOC_REG] = REG_FIELD(0xA5, 0, 6), + [FG_INIT] = REG_FIELD(0xA5, 7, 7), + + [HALT_CNT_REG] = REG_FIELD(0xA6, 0, 7), + [CALC_REST_REGL] = REG_FIELD(0xA7, 0, 7), + [CALC_REST_REGH] = REG_FIELD(0xA8, 0, 7), + + [VOL_ADC_B3] = REG_FIELD(0xA9, 0, 7), + [VOL_ADC_B2] = REG_FIELD(0xAA, 0, 7), + [VOL_ADC_B1] = REG_FIELD(0xAB, 0, 7), + [VOL_ADC_B0] = REG_FIELD(0xAC, 0, 7), + + [VOL_ADC_K3] = REG_FIELD(0xAD, 0, 7), + [VOL_ADC_K2] = REG_FIELD(0xAE, 0, 7), + [VOL_ADC_K1] = REG_FIELD(0xAF, 0, 7), + [VOL_ADC_K0] = REG_FIELD(0xB0, 0, 7), + [CHIP_NAME_H] = REG_FIELD(0xED, 0, 7), + [CHIP_NAME_L] = REG_FIELD(0xEE, 0, 7), +}; + +struct battery_platform_data { + u32 *ocv_table; + u32 *zero_table; + + u32 table_t[4][21]; + int temp_t[4]; + u32 temp_t_num; + + u32 *ntc_table; + u32 ocv_size; + u32 ntc_size; + int ntc_degree_from; + u32 ntc_factor; + u32 max_input_current; + u32 max_chrg_current; + u32 max_chrg_voltage; + u32 lp_input_current; + u32 lp_soc_min; + u32 lp_soc_max; + u32 pwroff_vol; + u32 monitor_sec; + u32 zero_algorithm_vol; + u32 zero_reserve_dsoc; + u32 bat_res; + u32 design_capacity; + u32 design_qmax; + u32 sleep_enter_current; + u32 sleep_exit_current; + u32 sleep_filter_current; + u32 power_dc2otg; + u32 max_soc_offset; + u32 bat_mode; + u32 fb_temp; + u32 energy_mode; + u32 cccv_hour; + u32 dc_det_adc; + int dc_det_pin; + u8 dc_det_level; + u32 sample_res; + bool extcon; +}; + +struct rk817_battery_device { + struct platform_device *pdev; + struct device *dev; + struct i2c_client *client; + struct rk808 *rk817; + struct power_supply *bat; + struct regmap *regmap; + struct regmap_field *rmap_fields[F_MAX_FIELDS]; + struct battery_platform_data *pdata; + struct workqueue_struct *bat_monitor_wq; + struct delayed_work bat_delay_work; + struct delayed_work calib_delay_work; + struct wake_lock wake_lock; + struct timer_list caltimer; + + int res_div; + int bat_res; + bool is_first_power_on; + int chrg_status; + int res_fac; + int over_20mR; + bool is_initialized; + bool bat_first_power_on; + u8 ac_in; + u8 usb_in; + u8 otg_in; + u8 dc_in; + u8 prop_status; + int cvtlmt_irq; + int current_avg; + int current_relax; + int voltage_sys; + int voltage_avg; + int voltage_ocv; + int voltage_relax; + int voltage_k;/* VCALIB0 VCALIB1 */ + int voltage_b; + u32 remain_cap; + int design_cap; + int nac; + int fcc; + int lock_fcc; + int qmax; + int dsoc; + int rsoc; + int poffset; + int fake_offline; + int age_ocv_soc; + bool age_allow_update; + int age_level; + int age_ocv_cap; + int pwron_voltage; + int age_voltage; + int age_adjust_cap; + unsigned long age_keep_sec; + int zero_timeout_cnt; + int zero_remain_cap; + int zero_dsoc; + int zero_linek; + u64 zero_drop_sec; + u64 shtd_drop_sec; + int sm_remain_cap; + int sm_linek; + int sm_chrg_dsoc; + int sm_dischrg_dsoc; + int smooth_soc; + int algo_rest_val; + int algo_rest_mode; + int sleep_sum_cap; + int sleep_remain_cap; + unsigned long sleep_dischrg_sec; + unsigned long sleep_sum_sec; + bool sleep_chrg_online; + u8 sleep_chrg_status; + bool adc_allow_update; + int fb_blank; + bool s2r; /*suspend to resume*/ + u32 work_mode; + int temperature; + int chrg_cur_lp_input; + int chrg_vol_sel; + int chrg_cur_input; + int chrg_cur_sel; + u32 monitor_ms; + u32 pwroff_min; + u32 adc_calib_cnt; + unsigned long chrg_finish_base; + unsigned long boot_base; + unsigned long flat_match_sec; + unsigned long plug_in_base; + unsigned long plug_out_base; + u8 halt_cnt; + bool is_halt; + bool is_max_soc_offset; + bool is_sw_reset; + bool is_ocv_calib; + bool is_first_on; + bool is_force_calib; + int last_dsoc; + u8 cvtlmt_int_event; + u8 slp_dcdc_en_reg; + int ocv_pre_dsoc; + int ocv_new_dsoc; + int max_pre_dsoc; + int max_new_dsoc; + int force_pre_dsoc; + int force_new_dsoc; + + int dbg_cap_low0; + int dbg_pwr_dsoc; + int dbg_pwr_rsoc; + int dbg_pwr_vol; + int dbg_chrg_min[10]; + int dbg_meet_soc; + int dbg_calc_dsoc; + int dbg_calc_rsoc; + +}; + +static const struct regmap_range rk817_battery_readonly_reg_ranges[] = { + regmap_reg_range(0x5A, 0x61), + regmap_reg_range(0x63, 0x6E), + regmap_reg_range(0x74, 0x81), + regmap_reg_range(0x86, 0x8D), + regmap_reg_range(0x93, 0x98), + regmap_reg_range(0xA9, 0xB0), +}; + +static const struct regmap_access_table rk817_battery_writeable_regs = { + .no_ranges = rk817_battery_readonly_reg_ranges, + .n_no_ranges = ARRAY_SIZE(rk817_battery_readonly_reg_ranges), +}; + +static const struct regmap_range rk817_battery_volatile_reg_ranges[] = { + regmap_reg_range(0x5A, 0x61), + regmap_reg_range(0x63, 0x6E), + regmap_reg_range(0x74, 0x81), + regmap_reg_range(0x86, 0x8D), + regmap_reg_range(0x93, 0x98), + regmap_reg_range(0xA9, 0xB0), +}; + +static const struct regmap_access_table rk817_battery_volatile_regs = { + .yes_ranges = rk817_battery_volatile_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(rk817_battery_volatile_reg_ranges), +}; + +static const struct regmap_config rk817_battery_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = 0xFF, + .cache_type = REGCACHE_RBTREE, + + .wr_table = &rk817_battery_writeable_regs, + .volatile_table = &rk817_battery_volatile_regs, +}; + +static u64 get_boot_sec(void) +{ + struct timespec ts; + + get_monotonic_boottime(&ts); + + return ts.tv_sec; +} + +static unsigned long base2sec(unsigned long x) +{ + if (x) + return (get_boot_sec() > x) ? (get_boot_sec() - x) : 0; + else + return 0; +} + +static u32 interpolate(int value, u32 *table, int size) +{ + u8 i; + u16 d; + + for (i = 0; i < size; i++) { + if (value < table[i]) + break; + } + + if ((i > 0) && (i < size)) { + d = (value - table[i - 1]) * (MAX_INTERPOLATE / (size - 1)); + d /= table[i] - table[i - 1]; + d = d + (i - 1) * (MAX_INTERPOLATE / (size - 1)); + } else { + d = i * ((MAX_INTERPOLATE + size / 2) / size); + } + + if (d > 1000) + d = 1000; + + return d; +} + +/* (a * b) / c */ +static int32_t ab_div_c(u32 a, u32 b, u32 c) +{ + bool sign; + u32 ans = MAX_INT; + int tmp; + + sign = ((((a ^ b) ^ c) & 0x80000000) != 0); + if (c != 0) { + if (sign) + c = -c; + tmp = (a * b + (c >> 1)) / c; + if (tmp < MAX_INT) + ans = tmp; + } + + if (sign) + ans = -ans; + + return ans; +} + +static int rk817_bat_field_read(struct rk817_battery_device *battery, + enum rk817_battery_fields field_id) +{ + int val; + int ret; + + ret = regmap_field_read(battery->rmap_fields[field_id], &val); + if (ret < 0) + return ret; + + return val; +} + +static int rk817_bat_field_write(struct rk817_battery_device *battery, + enum rk817_battery_fields field_id, + unsigned int val) +{ + return regmap_field_write(battery->rmap_fields[field_id], val); +} + +/*cal_offset: current offset value*/ +static int rk817_bat_get_coffset(struct rk817_battery_device *battery) +{ + int coffset_value = 0; + + coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_H) << 8; + coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_L); + + return coffset_value; +} + +static void rk817_bat_set_coffset(struct rk817_battery_device *battery, int val) +{ + u8 buf = 0; + + buf = (val >> 8) & 0xff; + rk817_bat_field_write(battery, CAL_OFFSET_H, buf); + buf = (val >> 0) & 0xff; + rk817_bat_field_write(battery, CAL_OFFSET_L, buf); +} + +/* current offset value calculated */ +static int rk817_bat_get_ioffset(struct rk817_battery_device *battery) +{ + int ioffset_value = 0; + + ioffset_value |= rk817_bat_field_read(battery, IOFFSET_H) << 8; + ioffset_value |= rk817_bat_field_read(battery, IOFFSET_H); + + return ioffset_value; +} + +static void rk817_bat_current_calibration(struct rk817_battery_device *battery) +{ + int pwron_value, ioffset, cal_offset; + + if (rk817_bat_field_read(battery, CUR_CALIB_UPD)) { + pwron_value = rk817_bat_field_read(battery, PWRON_CUR_L); + pwron_value |= rk817_bat_field_read(battery, PWRON_CUR_H) << 8; + + ioffset = rk817_bat_get_ioffset(battery); + + cal_offset = pwron_value + ioffset; + rk817_bat_set_coffset(battery, cal_offset); + rk817_bat_field_write(battery, CUR_CALIB_UPD, 0x00); + } +} + +static int rk817_bat_get_vaclib0(struct rk817_battery_device *battery) +{ + int vcalib_value = 0; + + vcalib_value |= rk817_bat_field_read(battery, VCALIB0_H) << 8; + vcalib_value |= rk817_bat_field_read(battery, VCALIB0_L); + + return vcalib_value; +} + +static int rk817_bat_get_vaclib1(struct rk817_battery_device *battery) +{ + int vcalib_value = 0; + + vcalib_value |= rk817_bat_field_read(battery, VCALIB1_H) << 8; + vcalib_value |= rk817_bat_field_read(battery, VCALIB1_L); + + return vcalib_value; +} + +static void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery) +{ + int vcalib0, vcalib1; + + vcalib0 = rk817_bat_get_vaclib0(battery); + vcalib1 = rk817_bat_get_vaclib1(battery); + battery->voltage_k = (4025 - 2300) * 1000 / DIV(vcalib1 - vcalib0); + battery->voltage_b = 4025 - (battery->voltage_k * vcalib1) / 1000; +} + +static void rk817_bat_restart_relax(struct rk817_battery_device *battery) +{ + rk817_bat_field_write(battery, RELAX_VOL1_UPD, 0x00); + rk817_bat_field_write(battery, RELAX_VOL2_UPD, 0x00); +} + +static bool is_rk817_bat_relax_mode(struct rk817_battery_device *battery) +{ + u8 relax_sts, relax_vol1_upd, relax_vol2_upd; + + relax_sts = rk817_bat_field_read(battery, RELAX_STS); + relax_vol1_upd = rk817_bat_field_read(battery, RELAX_VOL1_UPD); + relax_vol2_upd = rk817_bat_field_read(battery, RELAX_VOL2_UPD); + + if (relax_sts && relax_vol1_upd && relax_vol2_upd) + return true; + else + return false; +} + +static u16 rk817_bat_get_relax_vol1(struct rk817_battery_device *battery) +{ + u16 vol, val = 0; + + val |= rk817_bat_field_read(battery, RELAX_VOL1_L); + val |= rk817_bat_field_read(battery, RELAX_VOL1_H) << 8; + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +static u16 rk817_bat_get_relax_vol2(struct rk817_battery_device *battery) +{ + u16 vol, val = 0; + + val |= rk817_bat_field_read(battery, RELAX_VOL2_L); + val |= rk817_bat_field_read(battery, RELAX_VOL2_H) << 8; + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +static u16 rk817_bat_get_relax_voltage(struct rk817_battery_device *battery) +{ + u16 relax_vol1, relax_vol2; + + if (!is_rk817_bat_relax_mode(battery)) + return 0; + + relax_vol1 = rk817_bat_get_relax_vol1(battery); + relax_vol2 = rk817_bat_get_relax_vol2(battery); + + return relax_vol1 > relax_vol2 ? relax_vol1 : relax_vol2; +} + +static void rk817_bat_set_relax_sample(struct rk817_battery_device *battery) +{ + u8 buf; + int enter_thres, filter_thres; + struct battery_platform_data *pdata = battery->pdata; + + filter_thres = pdata->sleep_filter_current * 1000 / 1506; + + enter_thres = CURRENT_TO_ADC(pdata->sleep_enter_current, + battery->res_div); + filter_thres = CURRENT_TO_ADC(pdata->sleep_filter_current, + battery->res_div); + + /* set relax enter and exit threshold */ + buf = enter_thres & 0xff; + rk817_bat_field_write(battery, RELAX_THRE_L, buf); + buf = (enter_thres >> 8) & 0xff; + rk817_bat_field_write(battery, RELAX_THRE_H, buf); + /* set sample current threshold */ + buf = filter_thres & 0xff; + rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_L, buf); + buf = (filter_thres >> 8) & 0xff; + rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_H, buf); + + /* reset relax update state */ + rk817_bat_restart_relax(battery); + DBG("<%s>. sleep_enter_current = %d, sleep_exit_current = %d\n", + __func__, pdata->sleep_enter_current, pdata->sleep_exit_current); +} + +/* runtime OCV voltage, |RLX_VOL2 - RLX_VOL1| < OCV_THRE, + * the OCV reg update every 120s + */ +static int rk817_bat_get_ocv_voltage(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + val = rk817_bat_field_read(battery, OCV_VOL_L); + val |= rk817_bat_field_read(battery, OCV_VOL_H) << 8; + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +static int rk817_bat_get_ocv0_voltage0(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + val = rk817_bat_field_read(battery, OCV_VOL0_L); + val |= rk817_bat_field_read(battery, OCV_VOL0_H) << 8; + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +/* power on battery voltage */ +static int rk817_bat_get_pwron_voltage(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + val = rk817_bat_field_read(battery, PWRON_VOL_L); + val |= rk817_bat_field_read(battery, PWRON_VOL_H) << 8; + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +static int rk817_bat_get_battery_voltage(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + val = rk817_bat_field_read(battery, BAT_VOL_L) << 0; + val |= rk817_bat_field_read(battery, BAT_VOL_H) << 8; + + vol = battery->voltage_k * val / 1000 + battery->voltage_b; + + return vol; +} + +static int rk817_bat_get_USB_voltage(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + rk817_bat_field_write(battery, USB_VOL_ADC_EN, 0x01); + + val = rk817_bat_field_read(battery, USB_VOL_L) << 0; + val |= rk817_bat_field_read(battery, USB_VOL_H) << 8; + + vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46; + + return vol; +} + +static int rk817_bat_get_sys_voltage(struct rk817_battery_device *battery) +{ + int vol, val = 0; + + val = rk817_bat_field_read(battery, SYS_VOL_L) << 0; + val |= rk817_bat_field_read(battery, SYS_VOL_H) << 8; + + vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46; + + return vol; +} + +static int rk817_bat_get_avg_current(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, BAT_CUR_L); + val |= rk817_bat_field_read(battery, BAT_CUR_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static int rk817_bat_get_relax_cur1(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, RELAX_CUR1_L); + val |= rk817_bat_field_read(battery, RELAX_CUR1_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static int rk817_bat_get_relax_cur2(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, RELAX_CUR2_L); + val |= rk817_bat_field_read(battery, RELAX_CUR2_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static int rk817_bat_get_relax_current(struct rk817_battery_device *battery) +{ + int relax_cur1, relax_cur2; + + if (!is_rk817_bat_relax_mode(battery)) + return 0; + + relax_cur1 = rk817_bat_get_relax_cur1(battery); + relax_cur2 = rk817_bat_get_relax_cur2(battery); + + return (relax_cur1 < relax_cur2) ? relax_cur1 : relax_cur2; +} + +static int rk817_bat_get_ocv_current(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, OCV_CUR_L); + val |= rk817_bat_field_read(battery, OCV_CUR_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static int rk817_bat_get_ocv_current0(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, OCV_CUR0_L); + val |= rk817_bat_field_read(battery, OCV_CUR0_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static int rk817_bat_get_pwron_current(struct rk817_battery_device *battery) +{ + int cur, val = 0; + + val |= rk817_bat_field_read(battery, PWRON_CUR_L); + val |= rk817_bat_field_read(battery, PWRON_CUR_H) << 8; + + if (val & 0x8000) + val -= 0x10000; + cur = ADC_TO_CURRENT(val, battery->res_div); + + return cur; +} + +static u32 rk817_bat_get_capacity_uah(struct rk817_battery_device *battery) +{ + u32 val = 0, capacity; + + val = rk817_bat_field_read(battery, Q_PRESS_H3) << 24; + val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 16; + val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 8; + val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0; + + capacity = ADC_TO_CAPACITY_UAH(val, battery->res_div); + + return capacity; +} + +static u32 rk817_bat_get_capacity_mah(struct rk817_battery_device *battery) +{ + u32 val, capacity; + + val = rk817_bat_field_read(battery, Q_PRESS_H3) << 24; + val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 16; + val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 8; + val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0; + + capacity = ADC_TO_CAPACITY(val, battery->res_div); + + return capacity; +} + +static void rk817_bat_init_coulomb_cap(struct rk817_battery_device *battery, + u32 capacity) +{ + u8 buf; + u32 cap; + + cap = CAPACITY_TO_ADC(capacity, battery->res_div); + + buf = (cap >> 24) & 0xff; + rk817_bat_field_write(battery, Q_INIT_H3, buf); + buf = (cap >> 16) & 0xff; + rk817_bat_field_write(battery, Q_INIT_H2, buf); + buf = (cap >> 8) & 0xff; + rk817_bat_field_write(battery, Q_INIT_L1, buf); + buf = (cap >> 0) & 0xff; + rk817_bat_field_write(battery, Q_INIT_L0, buf); + + battery->rsoc = capacity * 1000 * 100 / battery->fcc; + battery->remain_cap = capacity * 1000; +} + +static void rk817_bat_save_cap(struct rk817_battery_device *battery, + int capacity) +{ + u8 buf; + static u32 old_cap; + + if (capacity >= battery->qmax) + capacity = battery->qmax; + if (capacity <= 0) + capacity = 0; + if (old_cap == capacity) + return; + + old_cap = capacity; + buf = (capacity >> 16) & 0xff; + rk817_bat_field_write(battery, REMAIN_CAP_REG2, buf); + buf = (capacity >> 8) & 0xff; + rk817_bat_field_write(battery, REMAIN_CAP_REG1, buf); + buf = (capacity >> 0) & 0xff; + rk817_bat_field_write(battery, REMAIN_CAP_REG0, buf); +} + +static void rk817_bat_update_qmax(struct rk817_battery_device *battery, + u32 capacity) +{ + u8 buf; + u32 cap_adc; + + if (!rk817_bat_field_read(battery, QMAX_UPD_SOFT) && + capacity != 0 && capacity != battery->qmax) { + cap_adc = CAPACITY_TO_ADC(capacity, battery->res_div); + buf = (cap_adc >> 24) & 0xff; + rk817_bat_field_write(battery, Q_MAX_H3, buf); + buf = (cap_adc >> 16) & 0xff; + rk817_bat_field_write(battery, Q_MAX_H2, buf); + buf = (cap_adc >> 8) & 0xff; + rk817_bat_field_write(battery, Q_MAX_L1, buf); + buf = (cap_adc >> 0) & 0xff; + rk817_bat_field_write(battery, Q_MAX_L0, buf); + + battery->qmax = capacity; + rk817_bat_field_write(battery, QMAX_UPD_SOFT, 0x01); + } +} + +static int rk817_bat_get_qmax(struct rk817_battery_device *battery) +{ + u32 capacity; + int val = 0; + + /* check lock flag, 1: yes, 0: no */ + if (!rk817_bat_field_read(battery, QMAX_UPD_SOFT)) + return 0; + + val = rk817_bat_field_read(battery, Q_MAX_H3) << 24; + val |= rk817_bat_field_read(battery, Q_MAX_H2) << 16; + val |= rk817_bat_field_read(battery, Q_MAX_L1) << 8; + val |= rk817_bat_field_read(battery, Q_MAX_L0) << 0; + + capacity = ADC_TO_CAPACITY(val, battery->res_div); + + /* clear lock flag */ + rk817_bat_field_write(battery, QMAX_UPD_SOFT, 0x00); + + battery->qmax = capacity; + + return capacity; +} + +static void rk817_bat_save_fcc(struct rk817_battery_device *battery, int fcc) +{ + u8 buf; + + buf = (fcc >> 16) & 0xff; + rk817_bat_field_write(battery, NEW_FCC_REG2, buf); + buf = (fcc >> 8) & 0xff; + rk817_bat_field_write(battery, NEW_FCC_REG1, buf); + buf = (fcc >> 0) & 0xff; + rk817_bat_field_write(battery, NEW_FCC_REG0, buf); +} + +static int rk817_bat_get_fcc(struct rk817_battery_device *battery) +{ + u32 fcc = 0; + + fcc |= rk817_bat_field_read(battery, NEW_FCC_REG2) << 16; + fcc |= rk817_bat_field_read(battery, NEW_FCC_REG1) << 8; + fcc |= rk817_bat_field_read(battery, NEW_FCC_REG0) << 0; + + if (fcc < MIN_FCC) { + DBG("invalid fcc(%d), use design cap", fcc); + fcc = battery->pdata->design_capacity; + rk817_bat_save_fcc(battery, fcc); + } else if (fcc > battery->pdata->design_qmax) { + DBG("invalid fcc(%d), use qmax", fcc); + fcc = battery->pdata->design_qmax; + rk817_bat_save_fcc(battery, fcc); + } + + return fcc; +} + +static int rk817_bat_get_rsoc(struct rk817_battery_device *battery) +{ + int remain_cap; + + remain_cap = rk817_bat_get_capacity_uah(battery); + + return remain_cap * 100 / DIV(battery->fcc); +} + +static int rk817_bat_get_off_count(struct rk817_battery_device *battery) +{ + return rk817_bat_field_read(battery, OFF_CNT); +} + +static int rk817_bat_get_ocv_count(struct rk817_battery_device *battery) +{ + return rk817_bat_field_read(battery, OCV_CNT); +} + +static int rk817_bat_vol_to_soc(struct rk817_battery_device *battery, + int voltage) +{ + u32 *ocv_table, temp; + int ocv_size, ocv_soc; + + ocv_table = battery->pdata->ocv_table; + ocv_size = battery->pdata->ocv_size; + temp = interpolate(voltage, ocv_table, ocv_size); + ocv_soc = ab_div_c(temp, MAX_PERCENTAGE, MAX_INTERPOLATE); + + return ocv_soc; +} + +static int rk817_bat_vol_to_cap(struct rk817_battery_device *battery, + int voltage) +{ + u32 *ocv_table, temp; + int ocv_size, capacity; + + ocv_table = battery->pdata->ocv_table; + ocv_size = battery->pdata->ocv_size; + temp = interpolate(voltage, ocv_table, ocv_size); + capacity = ab_div_c(temp, battery->fcc, MAX_INTERPOLATE); + + return capacity; +} + +static void rk817_bat_save_dsoc(struct rk817_battery_device *battery, + u8 save_soc) +{ + static int last_soc = -1; + + if (last_soc != save_soc) { + rk817_bat_field_write(battery, SOC_REG, save_soc); + last_soc = save_soc; + } +} + +static int rk817_bat_get_prev_dsoc(struct rk817_battery_device *battery) +{ + return rk817_bat_field_read(battery, SOC_REG); +} + +static bool is_rk817_bat_first_pwron(struct rk817_battery_device *battery) +{ + if (rk817_bat_field_read(battery, BAT_CON)) { + rk817_bat_field_write(battery, BAT_CON, 0x00); + return true; + } + + return false; +} + +static bool is_rk817_bat_ocv_valid(struct rk817_battery_device *battery) +{ + return (!battery->is_initialized && battery->pwroff_min >= 30); +} + +static void rk817_bat_gas_gaugle_enable(struct rk817_battery_device *battery) +{ + rk817_bat_field_write(battery, GG_EN, ENABLE); +} + +static void rk817_bat_gg_con_init(struct rk817_battery_device *battery) +{ + rk817_bat_field_write(battery, RLX_SPT, S_8_MIN); + rk817_bat_field_write(battery, ADC_OFF_CAL_INTERV, S_8_MIN); + rk817_bat_field_write(battery, VOL_OUT_MOD, AVERAGE_MODE); + rk817_bat_field_write(battery, CUR_OUT_MOD, AVERAGE_MODE); +} + +static void rk817_bat_adc_init(struct rk817_battery_device *battery) +{ + rk817_bat_field_write(battery, SYS_VOL_ADC_EN, ENABLE); + rk817_bat_field_write(battery, TS_ADC_EN, ENABLE); + rk817_bat_field_write(battery, USB_VOL_ADC_EN, ENABLE); + rk817_bat_field_write(battery, BAT_VOL_ADC_EN, ENABLE); + rk817_bat_field_write(battery, BAT_CUR_ADC_EN, ENABLE); +} + +static void rk817_bat_init_info(struct rk817_battery_device *battery) +{ + battery->design_cap = battery->pdata->design_capacity; + battery->qmax = battery->pdata->design_qmax; + battery->bat_res = battery->pdata->bat_res; + battery->monitor_ms = battery->pdata->monitor_sec * TIMER_MS_COUNTS; + battery->res_div = (battery->pdata->sample_res == SAMPLE_RES_20MR) ? + SAMPLE_RES_DIV2 : SAMPLE_RES_DIV1; +} + +static int rk817_bat_get_prev_cap(struct rk817_battery_device *battery) +{ + int val = 0; + + val |= rk817_bat_field_read(battery, REMAIN_CAP_REG2) << 16; + val |= rk817_bat_field_read(battery, REMAIN_CAP_REG1) << 8; + val |= rk817_bat_field_read(battery, REMAIN_CAP_REG0) << 0; + + return val; +} + +static u8 rk817_bat_get_halt_cnt(struct rk817_battery_device *battery) +{ + return rk817_bat_field_read(battery, HALT_CNT_REG); +} + +static void rk817_bat_inc_halt_cnt(struct rk817_battery_device *battery) +{ + u8 cnt; + + cnt = rk817_bat_field_read(battery, HALT_CNT_REG); + rk817_bat_field_write(battery, HALT_CNT_REG, ++cnt); +} + +static bool is_rk817_bat_last_halt(struct rk817_battery_device *battery) +{ + int pre_cap = rk817_bat_get_prev_cap(battery); + int now_cap = rk817_bat_get_capacity_mah(battery); + + /* over 10%: system halt last time */ + if (abs(now_cap - pre_cap) > (battery->fcc / 10)) { + rk817_bat_inc_halt_cnt(battery); + return true; + } else { + return false; + } +} + +static u8 is_rk817_bat_initialized(struct rk817_battery_device *battery) +{ + u8 val = rk817_bat_field_read(battery, FG_INIT); + + if (val) { + rk817_bat_field_write(battery, FG_INIT, 0x00); + return true; + } else { + return false; + } +} + +static void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery) +{ + int linek; + int diff, delta; + + delta = abs(battery->dsoc - battery->rsoc); + diff = delta * 3;/* speed:3/4 */ + + if (battery->dsoc < battery->rsoc) + linek = -1000 * diff / DIV(delta + diff); + else if (battery->dsoc > battery->rsoc) + linek = -1000 * (delta + diff) / DIV(diff); + else + linek = -1000; + battery->dbg_meet_soc = (battery->dsoc >= battery->rsoc) ? + (battery->dsoc - diff) : (battery->rsoc - diff); + + battery->sm_linek = linek; + battery->sm_remain_cap = battery->remain_cap; + battery->dbg_calc_dsoc = battery->dsoc; + battery->dbg_calc_rsoc = battery->rsoc; +} + +static void rk817_bat_smooth_algo_prepare(struct rk817_battery_device *battery) +{ + battery->smooth_soc = battery->dsoc; + + DBG("<%s>. dsoc=%d, dsoc:smooth_soc=%d\n", + __func__, battery->dsoc, battery->smooth_soc); + rk817_bat_calc_sm_linek(battery); +} + +static void rk817_bat_init_dsoc_algorithm(struct rk817_battery_device *battery) +{ + if (battery->dsoc >= 100 * 1000) + battery->dsoc = 100 * 1000; + else if (battery->dsoc <= 0) + battery->dsoc = 0; + /* init current mode */ + battery->voltage_avg = rk817_bat_get_battery_voltage(battery); + battery->current_avg = rk817_bat_get_avg_current(battery); + + rk817_bat_smooth_algo_prepare(battery); + battery->work_mode = MODE_SMOOTH; + DBG("%s, sm_remain_cap = %d, smooth_soc = %d\n", + __func__, battery->sm_remain_cap, battery->smooth_soc); +} + +static void rk817_bat_first_pwron(struct rk817_battery_device *battery) +{ + battery->rsoc = + rk817_bat_vol_to_soc(battery, + battery->pwron_voltage) * 1000;/* uAH */ + battery->dsoc = battery->rsoc; + battery->fcc = battery->pdata->design_capacity; + battery->nac = rk817_bat_vol_to_cap(battery, battery->pwron_voltage); + + rk817_bat_update_qmax(battery, battery->qmax); + rk817_bat_save_fcc(battery, battery->fcc); + DBG("%s, rsoc = %d, dsoc = %d, fcc = %d, nac = %d\n", + __func__, battery->rsoc, battery->dsoc, battery->fcc, battery->nac); +} + +static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery) +{ + int now_cap, pre_soc, pre_cap, ocv_cap, ocv_soc, ocv_vol; + + battery->fcc = rk817_bat_get_fcc(battery); + pre_soc = rk817_bat_get_prev_dsoc(battery); + pre_cap = rk817_bat_get_prev_cap(battery); + now_cap = rk817_bat_get_capacity_mah(battery); + battery->remain_cap = pre_cap * 1000; + battery->is_halt = is_rk817_bat_last_halt(battery); + battery->halt_cnt = rk817_bat_get_halt_cnt(battery); + battery->is_initialized = is_rk817_bat_initialized(battery); + battery->is_ocv_calib = is_rk817_bat_ocv_valid(battery); + + if (battery->is_halt) { + BAT_INFO("system halt last time... cap: pre=%d, now=%d\n", + pre_cap, now_cap); + if (now_cap < 0) + now_cap = 0; + rk817_bat_init_coulomb_cap(battery, now_cap); + pre_cap = now_cap; + pre_soc = battery->rsoc; + goto finish; + } else if (battery->is_initialized) { + /* uboot initialized */ + BAT_INFO("initialized yet..\n"); + goto finish; + } else if (battery->is_ocv_calib) { + /* not initialized and poweroff_cnt above 30 min */ + ocv_vol = rk817_bat_get_ocv_voltage(battery); + ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol); + ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol); + pre_cap = ocv_cap; + battery->ocv_pre_dsoc = pre_soc; + battery->ocv_new_dsoc = ocv_soc; + if (abs(ocv_soc - pre_soc) >= battery->pdata->max_soc_offset) { + battery->ocv_pre_dsoc = pre_soc; + battery->ocv_new_dsoc = ocv_soc; + battery->is_max_soc_offset = true; + BAT_INFO("trigger max soc offset, dsoc: %d -> %d\n", + pre_soc, ocv_soc); + pre_soc = ocv_soc; + } + BAT_INFO("OCV calib: cap=%d, rsoc=%d\n", ocv_cap, ocv_soc); + } else if (battery->pwroff_min > 0) { + ocv_vol = rk817_bat_get_ocv_voltage(battery); + ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol); + ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol); + battery->force_pre_dsoc = pre_soc; + battery->force_new_dsoc = ocv_soc; + if (abs(ocv_soc - pre_soc) >= 80) { + battery->is_force_calib = true; + BAT_INFO("dsoc force calib: %d -> %d\n", + pre_soc, ocv_soc); + pre_soc = ocv_soc; + pre_cap = ocv_cap; + } + } +finish: + battery->dsoc = pre_soc * 1000; + battery->nac = pre_cap; + if (battery->nac < 0) + battery->nac = 0; + + DBG("dsoc=%d cap=%d v=%d ov=%d rv=%d min=%d psoc=%d pcap=%d\n", + battery->dsoc, battery->nac, rk817_bat_get_battery_voltage(battery), + rk817_bat_get_ocv_voltage(battery), + rk817_bat_get_relax_voltage(battery), + battery->pwroff_min, rk817_bat_get_prev_dsoc(battery), + rk817_bat_get_prev_cap(battery)); +} + +static void rk817_bat_rsoc_init(struct rk817_battery_device *battery) +{ + battery->is_first_power_on = is_rk817_bat_first_pwron(battery); + battery->pwroff_min = rk817_bat_get_off_count(battery); + battery->pwron_voltage = rk817_bat_get_pwron_voltage(battery); + + DBG("%s, is_first_power_on = %d, pwroff_min = %d, pwron_voltage = %d\n", + __func__, battery->is_first_power_on, + battery->pwroff_min, battery->pwron_voltage); + + if (battery->is_first_power_on) + rk817_bat_first_pwron(battery); + else + rk817_bat_not_first_pwron(battery); + + rk817_bat_save_dsoc(battery, battery->dsoc); +} + +static void rk817_bat_caltimer_isr(unsigned long data) +{ + struct rk817_battery_device *battery = + (struct rk817_battery_device *)data; + + mod_timer(&battery->caltimer, jiffies + MINUTE(8) * HZ); + queue_delayed_work(battery->bat_monitor_wq, + &battery->calib_delay_work, + msecs_to_jiffies(10)); +} + +static void rk817_bat_internal_calib(struct work_struct *work) +{ + struct rk817_battery_device *battery = container_of(work, + struct rk817_battery_device, calib_delay_work.work); + + rk817_bat_current_calibration(battery); + /* calib voltage kb */ + rk817_bat_init_voltage_kb(battery); + + DBG("caltimer:coffset=0x%x\n", rk817_bat_get_coffset(battery)); +} + +static void rk817_bat_init_caltimer(struct rk817_battery_device *battery) +{ + setup_timer(&battery->caltimer, + rk817_bat_caltimer_isr, + (unsigned long)battery); + battery->caltimer.expires = jiffies + MINUTE(8) * HZ; + add_timer(&battery->caltimer); + INIT_DELAYED_WORK(&battery->calib_delay_work, rk817_bat_internal_calib); +} + +static void rk817_bat_init_fg(struct rk817_battery_device *battery) +{ + rk817_bat_adc_init(battery); + rk817_bat_gas_gaugle_enable(battery); + rk817_bat_gg_con_init(battery); + rk817_bat_init_voltage_kb(battery); + rk817_bat_set_relax_sample(battery); + rk817_bat_init_caltimer(battery); + rk817_bat_rsoc_init(battery); + rk817_bat_init_coulomb_cap(battery, battery->nac); + DBG("rsoc%d, fcc = %d\n", battery->rsoc, battery->fcc); + rk817_bat_init_dsoc_algorithm(battery); + battery->qmax = rk817_bat_get_qmax(battery); + battery->voltage_avg = rk817_bat_get_battery_voltage(battery); + battery->voltage_sys = rk817_bat_get_sys_voltage(battery); + + battery->voltage_ocv = rk817_bat_get_ocv_voltage(battery); + battery->voltage_relax = rk817_bat_get_relax_voltage(battery); + battery->current_avg = rk817_bat_get_avg_current(battery); + battery->dbg_pwr_dsoc = battery->dsoc; + battery->dbg_pwr_rsoc = battery->rsoc; + battery->dbg_pwr_vol = battery->voltage_avg; + + DBG("probe init: battery->dsoc = %d, rsoc = %d\n" + "remain_cap = %d\n, battery_vol = %d\n, system_vol = %d\n", + battery->dsoc, battery->rsoc, battery->remain_cap, + battery->voltage_avg, battery->voltage_sys); +} + +static int rk817_bat_parse_dt(struct rk817_battery_device *battery) +{ + u32 out_value; + int length, ret; + size_t size; + struct battery_platform_data *pdata; + struct device *dev = battery->dev; + struct device_node *np = battery->dev->of_node; + + pdata = devm_kzalloc(battery->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + battery->pdata = pdata; + /* init default param */ + pdata->bat_res = DEFAULT_BAT_RES; + pdata->monitor_sec = DEFAULT_MONITOR_SEC; + pdata->pwroff_vol = DEFAULT_PWROFF_VOL_THRESD; + pdata->sleep_exit_current = DEFAULT_SLP_EXIT_CUR; + pdata->sleep_enter_current = DEFAULT_SLP_ENTER_CUR; + + pdata->sleep_filter_current = DEFAULT_SLP_FILTER_CUR; + pdata->bat_mode = MODE_BATTARY; + pdata->max_soc_offset = DEFAULT_MAX_SOC_OFFSET; + pdata->fb_temp = DEFAULT_FB_TEMP; + pdata->energy_mode = DEFAULT_ENERGY_MODE; + pdata->zero_reserve_dsoc = DEFAULT_ZERO_RESERVE_DSOC; + + pdata->sample_res = DEFAULT_SAMPLE_RES; + + /* parse necessary param */ + if (!of_find_property(np, "ocv_table", &length)) { + dev_err(dev, "ocv_table not found!\n"); + return -EINVAL; + } + + pdata->ocv_size = length / sizeof(u32); + if (pdata->ocv_size <= 0) { + dev_err(dev, "invalid ocv table\n"); + return -EINVAL; + } + + size = sizeof(*pdata->ocv_table) * pdata->ocv_size; + pdata->ocv_table = devm_kzalloc(battery->dev, size, GFP_KERNEL); + if (!pdata->ocv_table) + return -ENOMEM; + + ret = of_property_read_u32_array(np, "ocv_table", pdata->ocv_table, + pdata->ocv_size); + if (ret < 0) + return ret; + + ret = of_property_read_u32(np, "design_capacity", &out_value); + if (ret < 0) { + dev_err(dev, "design_capacity not found!\n"); + return ret; + } + pdata->design_capacity = out_value; + + ret = of_property_read_u32(np, "design_qmax", &out_value); + if (ret < 0) { + dev_err(dev, "design_qmax not found!\n"); + return ret; + } + pdata->design_qmax = out_value; + + /* parse unnecessary param */ + ret = of_property_read_u32(np, "sample_res", &pdata->sample_res); + if (ret < 0) + dev_err(dev, "sample_res missing!\n"); + + ret = of_property_read_u32(np, "fb_temperature", &pdata->fb_temp); + if (ret < 0) + dev_err(dev, "fb_temperature missing!\n"); + + ret = of_property_read_u32(np, "energy_mode", &pdata->energy_mode); + if (ret < 0) + dev_err(dev, "energy_mode missing!\n"); + + ret = of_property_read_u32(np, "max_soc_offset", + &pdata->max_soc_offset); + if (ret < 0) + dev_err(dev, "max_soc_offset missing!\n"); + + ret = of_property_read_u32(np, "monitor_sec", &pdata->monitor_sec); + if (ret < 0) + dev_err(dev, "monitor_sec missing!\n"); + + ret = of_property_read_u32(np, "zero_algorithm_vol", + &pdata->zero_algorithm_vol); + if (ret < 0) + dev_err(dev, "zero_algorithm_vol missing!\n"); + + ret = of_property_read_u32(np, "zero_reserve_dsoc", + &pdata->zero_reserve_dsoc); + if (ret < 0) + dev_err(dev, "zero_reserve_dsoc missing!\n"); + + ret = of_property_read_u32(np, "virtual_power", &pdata->bat_mode); + if (ret < 0) + dev_err(dev, "virtual_power missing!\n"); + + ret = of_property_read_u32(np, "bat_res", &pdata->bat_res); + if (ret < 0) + dev_err(dev, "bat_res missing!\n"); + + ret = of_property_read_u32(np, "sleep_enter_current", + &pdata->sleep_enter_current); + if (ret < 0) + dev_err(dev, "sleep_enter_current missing!\n"); + + ret = of_property_read_u32(np, "sleep_exit_current", + &pdata->sleep_exit_current); + if (ret < 0) + dev_err(dev, "sleep_exit_current missing!\n"); + + ret = of_property_read_u32(np, "sleep_filter_current", + &pdata->sleep_filter_current); + if (ret < 0) + dev_err(dev, "sleep_filter_current missing!\n"); + + ret = of_property_read_u32(np, "power_off_thresd", &pdata->pwroff_vol); + if (ret < 0) + dev_err(dev, "power_off_thresd missing!\n"); + + DBG("the battery dts info dump:\n" + "bat_res:%d\n" + "res_sample:%d\n" + "design_capacity:%d\n" + "design_qmax :%d\n" + "sleep_enter_current:%d\n" + "sleep_exit_current:%d\n" + "sleep_filter_current:%d\n" + "zero_algorithm_vol:%d\n" + "zero_reserve_dsoc:%d\n" + "monitor_sec:%d\n" + "max_soc_offset:%d\n" + "virtual_power:%d\n" + "pwroff_vol:%d\n", + pdata->bat_res, + pdata->sample_res, + pdata->design_capacity, + pdata->design_qmax, + pdata->sleep_enter_current, + pdata->sleep_exit_current, + pdata->sleep_filter_current, + pdata->zero_algorithm_vol, + pdata->zero_reserve_dsoc, + pdata->monitor_sec, + pdata->max_soc_offset, + pdata->bat_mode, + pdata->pwroff_vol); + + return 0; +} + +static enum power_supply_property rk817_bat_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, +}; + +static int rk817_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct rk817_battery_device *battery = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battery->current_avg * 1000;/*uA*/ + if (battery->pdata->bat_mode == MODE_VIRTUAL) + val->intval = VIRTUAL_CURRENT * 1000; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battery->voltage_avg * 1000;/*uV*/ + if (battery->pdata->bat_mode == MODE_VIRTUAL) + val->intval = VIRTUAL_VOLTAGE * 1000; + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = (battery->dsoc + 500) / 1000; + if (battery->pdata->bat_mode == MODE_VIRTUAL) + val->intval = VIRTUAL_SOC; + break; + case POWER_SUPPLY_PROP_HEALTH: + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = battery->temperature; + if (battery->pdata->bat_mode == MODE_VIRTUAL) + val->intval = VIRTUAL_TEMPERATURE; + break; + case POWER_SUPPLY_PROP_STATUS: + if (battery->pdata->bat_mode == MODE_VIRTUAL) + val->intval = VIRTUAL_STATUS; + else if (battery->dsoc == 100 * 1000) + val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = 4500 * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = 5000 * 1000; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct power_supply_desc rk817_bat_desc = { + .name = "battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = rk817_bat_props, + .num_properties = ARRAY_SIZE(rk817_bat_props), + .get_property = rk817_battery_get_property, +}; + +static int rk817_bat_init_power_supply(struct rk817_battery_device *battery) +{ + struct power_supply_config psy_cfg = { .drv_data = battery, }; + + battery->bat = devm_power_supply_register(battery->dev, + &rk817_bat_desc, + &psy_cfg); + if (IS_ERR(battery->bat)) { + dev_err(battery->dev, "register bat power supply fail\n"); + return PTR_ERR(battery->bat); + } + + return 0; +} + +static void rk817_bat_power_supply_changed(struct rk817_battery_device *battery) +{ + static int old_soc = -1; + + if (battery->dsoc > 100) + battery->dsoc = 100; + else if (battery->dsoc < 0) + battery->dsoc = 0; + + if (battery->dsoc == old_soc) + return; + + old_soc = battery->dsoc; + battery->last_dsoc = battery->dsoc; + power_supply_changed(battery->bat); + DBG("changed: dsoc=%d, rsoc=%d, v=%d, ov=%d c=%d, cap=%d, f=%d\n", + battery->dsoc, battery->rsoc, battery->voltage_avg, + battery->voltage_ocv, battery->current_avg, + battery->remain_cap, battery->fcc); + + DBG("dl=%d, rl=%d, v=%d, halt=%d, halt_n=%d, max=%d\n" + "init=%d, sw=%d, calib=%d, below0=%d, force=%d\n", + battery->dbg_pwr_dsoc, battery->dbg_pwr_rsoc, + battery->dbg_pwr_vol, + battery->is_halt, battery->halt_cnt, + battery->is_max_soc_offset, + battery->is_initialized, battery->is_sw_reset, + battery->is_ocv_calib, + battery->dbg_cap_low0, battery->is_force_calib); +} + +static void rk817_battery_debug_info(struct rk817_battery_device *battery) +{ + rk817_bat_get_battery_voltage(battery); + rk817_bat_get_sys_voltage(battery); + rk817_bat_get_USB_voltage(battery); + rk817_bat_get_pwron_voltage(battery); + rk817_bat_get_ocv_voltage(battery); + rk817_bat_get_ocv0_voltage0(battery); + + rk817_bat_current_calibration(battery); + rk817_bat_get_avg_current(battery); + rk817_bat_get_relax_cur1(battery); + rk817_bat_get_relax_cur2(battery); + rk817_bat_get_relax_current(battery); + rk817_bat_get_ocv_current(battery); + rk817_bat_get_ocv_current0(battery); + rk817_bat_get_pwron_current(battery); + rk817_bat_init_coulomb_cap(battery, 500); + rk817_bat_update_qmax(battery, 1000); + rk817_bat_get_ocv_count(battery); + rk817_bat_save_dsoc(battery, battery->dsoc); + DBG("capactiy = %d\n", rk817_bat_get_capacity_mah(battery)); +} + +static void rk817_bat_update_info(struct rk817_battery_device *battery) +{ + battery->voltage_avg = rk817_bat_get_battery_voltage(battery); + battery->voltage_sys = rk817_bat_get_sys_voltage(battery); + battery->current_avg = rk817_bat_get_avg_current(battery); + battery->voltage_relax = rk817_bat_get_relax_voltage(battery); + battery->rsoc = rk817_bat_get_rsoc(battery); + battery->remain_cap = rk817_bat_get_capacity_uah(battery); + + DBG("UPDATE: voltage_avg = %d\n" + "voltage_sys = %d\n" + "curren_avg = %d\n" + "rsoc = %d\n" + "remain_cap = %d\n", + battery->voltage_avg, + battery->voltage_sys, + battery->current_avg, + battery->rsoc, + battery->remain_cap); + + /* smooth charge */ + if (battery->remain_cap / 1000 > battery->fcc) { + battery->sm_remain_cap -= (battery->remain_cap - battery->fcc); + DBG("<%s>. cap: remain=%d, sm_remain=%d\n", + __func__, battery->remain_cap, battery->sm_remain_cap); + rk817_bat_init_coulomb_cap(battery, battery->fcc); + } +} + +static void rk817_bat_save_data(struct rk817_battery_device *battery) +{ + rk817_bat_save_dsoc(battery, battery->dsoc / 1000); + rk817_bat_save_cap(battery, battery->remain_cap / 1000); +} + +/* high load: current < 0 with charger in. + * System will not shutdown while dsoc=0% with charging state(ac_in), + * which will cause over discharge, so oppose status before report states. + */ +static void rk817_bat_lowpwr_check(struct rk817_battery_device *battery) +{ + static u64 time; + int pwr_off_thresd = battery->pdata->pwroff_vol; + + if (battery->current_avg < 0 && battery->voltage_avg < pwr_off_thresd) { + if (!time) + time = get_boot_sec(); + + if ((base2sec(time) > MINUTE(1)) || + (battery->voltage_avg <= pwr_off_thresd - 50)) { + battery->fake_offline = 1; + if (battery->voltage_avg <= pwr_off_thresd - 50) + battery->dsoc--; + DBG("low power, soc=%d, current=%d\n", + battery->dsoc, battery->current_avg); + } + } else { + time = 0; + battery->fake_offline = 0; + } + + DBG("<%s>. t=%lu, dsoc=%d, current=%d, fake_offline=%d\n", + __func__, base2sec(time), battery->dsoc, + battery->current_avg, battery->fake_offline); +} + +static void rk817_bat_calc_smooth_dischrg(struct rk817_battery_device *battery) +{ + int tmp_soc = 0; + /* check new dsoc */ + if (battery->smooth_soc < 0) + battery->smooth_soc = 0; + + tmp_soc = battery->smooth_soc / 1000; + + if (tmp_soc != battery->dsoc / 1000) { + battery->dsoc = battery->smooth_soc; + if (battery->dsoc <= 0) + battery->dsoc = 0; + } +} + +static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) +{ + int ydsoc = 0, delta_cap = 0, old_cap = 0; + + battery->remain_cap = rk817_bat_get_capacity_uah(battery); + + old_cap = battery->sm_remain_cap; + DBG("smooth: smooth_soc = %d, dsoc = %d, battery->sm_linek = %d\n", + battery->smooth_soc, battery->dsoc, battery->sm_linek); + + /* discharge status: sm_remain_cap > remain_cap, delta_cap > 0 */ + /* from charge to discharge: + * remain_cap may be above sm_remain_cap, delta_cap <= 0 + */ + delta_cap = battery->sm_remain_cap - battery->remain_cap; + DBG("smooth: sm_remain_cap = %d, remain_cap = %d\n", + battery->sm_remain_cap, battery->remain_cap); + DBG("smooth: delta_cap = %d, dsoc = %d\n", + delta_cap, battery->dsoc); + + if (delta_cap == 0) { + DBG("<%s>. delta_cap = 0\n", __func__); + return; + } + + /* discharge: sm_linek < 0, if delate_cap <0, ydsoc > 0 */ + ydsoc = battery->sm_linek * (delta_cap / DIV(battery->fcc)) / 10; + + DBG("smooth: ydsoc = %d, fcc = %d\n", ydsoc, battery->fcc); + if (ydsoc == 0) { + DBG("<%s>. ydsoc = 0\n", __func__); + return; + } + battery->sm_remain_cap = battery->remain_cap; + + DBG("<%s>. k=%d, ydsoc=%d; cap:old=%d, new:%d; delta_cap=%d\n", + __func__, battery->sm_linek, ydsoc, old_cap, + battery->sm_remain_cap, delta_cap); + + /* discharge mode */ + /* discharge mode, but ydsoc > 0, + * from charge status to dischrage + */ + battery->smooth_soc += ydsoc; + if (ydsoc < 0) + rk817_bat_calc_smooth_dischrg(battery); + DBG("smooth: smooth_soc = %d, dsoc = %d\n", + battery->smooth_soc, battery->dsoc); + DBG("smooth: delta_cap = %d, dsoc = %d\n", + delta_cap, battery->dsoc); +} + +static void rk817_bat_calc_zero_linek(struct rk817_battery_device *battery) +{ + int dead_voltage, ocv_voltage; + int voltage_avg, current_avg, vsys; + int ocv_cap, dead_cap, xsoc; + int ocv_soc, dead_soc; + int pwroff_vol; + int min_gap_xsoc; + int powerpatch_res; + + if ((abs(battery->current_avg) < 400) && (battery->dsoc > 5)) + pwroff_vol = battery->pdata->pwroff_vol + 50; + else + pwroff_vol = battery->pdata->pwroff_vol; + + /* calc estimate ocv voltage */ + voltage_avg = rk817_bat_get_battery_voltage(battery); + current_avg = rk817_bat_get_avg_current(battery); + vsys = voltage_avg + (current_avg * DEF_PWRPATH_RES) / 1000; + + powerpatch_res = (voltage_avg - vsys) * 1000 / current_avg; + + DBG("Zero: voltage_avg = %d, Vsys = %d\n", voltage_avg, vsys); + DBG("Zero: powerpatch_res = %d\n", powerpatch_res); + DBG("ZERO0: shtd_vol: poweroff_vol(usr) = %d\n" + "pwroff_vol = %d\n" + "zero_reserve_dsoc = %d\n", + battery->pdata->pwroff_vol, + pwroff_vol, + battery->pdata->zero_reserve_dsoc); + + /* get the dead ocv voltage, pwroff_vol is vsys */ + dead_voltage = pwroff_vol - current_avg * + (battery->bat_res + DEF_PWRPATH_RES) / 1000; + + ocv_voltage = voltage_avg - (current_avg * battery->bat_res) / 1000; + DBG("ZERO0: dead_voltage(shtd) = %d, ocv_voltage(now) = %d\n", + dead_voltage, ocv_voltage); + + /* calc estimate soc and cap */ + dead_soc = rk817_bat_vol_to_soc(battery, dead_voltage); + dead_cap = rk817_bat_vol_to_cap(battery, dead_voltage); + DBG("ZERO0: dead_soc = %d, dead_cap = %d\n", + dead_soc, dead_cap); + + ocv_soc = rk817_bat_vol_to_soc(battery, ocv_voltage); + ocv_cap = rk817_bat_vol_to_cap(battery, ocv_voltage); + DBG("ZERO0: ocv_soc = %d, ocv_cap = %d\n", + ocv_soc, ocv_cap); + + /* xsoc: available rsoc */ + xsoc = ocv_soc - dead_soc; + + DBG("Zero: xsoc = %d\n", xsoc); + /* min_gap_xsoc: reserve xsoc */ + if (abs(current_avg) > ZERO_LOAD_LVL1) + min_gap_xsoc = MIN_ZERO_GAP_XSOC3; + else if (abs(current_avg) > ZERO_LOAD_LVL2) + min_gap_xsoc = MIN_ZERO_GAP_XSOC2; + else + min_gap_xsoc = MIN_ZERO_GAP_XSOC1; + + if ((xsoc <= 30) && + (battery->dsoc >= battery->pdata->zero_reserve_dsoc)) + min_gap_xsoc = min_gap_xsoc + MIN_ZERO_GAP_CALIB; + + battery->zero_remain_cap = battery->remain_cap; + battery->zero_timeout_cnt = 0; + if ((battery->dsoc <= 1) && (xsoc > 0)) { + battery->zero_linek = 400; + battery->zero_drop_sec = 0; + } else if (xsoc >= 0) { + battery->zero_drop_sec = 0; + battery->zero_linek = + (battery->zero_dsoc + xsoc / 2) / DIV(xsoc); + /* battery energy mode to use up voltage */ + if ((battery->pdata->energy_mode) && + (xsoc - battery->dsoc >= MIN_ZERO_GAP_XSOC3) && + (battery->dsoc <= 10) && (battery->zero_linek < 300)) { + battery->zero_linek = 300; + DBG("ZERO-new: zero_linek adjust step0...\n"); + /* reserve enough power yet, slow down any way */ + } else if ((xsoc - battery->dsoc >= min_gap_xsoc) || + ((xsoc - battery->dsoc >= MIN_ZERO_GAP_XSOC2) && + (battery->dsoc <= 10) && (xsoc > 15))) { + if (xsoc <= 20 && + battery->dsoc >= battery->pdata->zero_reserve_dsoc) + battery->zero_linek = 1200; + else if (xsoc - battery->dsoc >= 2 * min_gap_xsoc) + battery->zero_linek = 400; + else if (xsoc - battery->dsoc >= 3 + min_gap_xsoc) + battery->zero_linek = 600; + else + battery->zero_linek = 800; + DBG("ZERO-new: zero_linek adjust step1...\n"); + /* control zero mode beginning enter */ + } else if ((battery->zero_linek > 1800) && + (battery->dsoc > 70)) { + battery->zero_linek = 1800; + DBG("ZERO-new: zero_linek adjust step2...\n"); + /* dsoc close to xsoc: it must reserve power */ + } else if ((battery->zero_linek > 1000) && + (battery->zero_linek < 1200)) { + battery->zero_linek = 1200; + DBG("ZERO-new: zero_linek adjust step3...\n"); + /* dsoc[5~15], dsoc < xsoc */ + } else if ((battery->dsoc <= 15 && battery->dsoc > 5) && + (battery->zero_linek <= 1200)) { + /* slow down */ + if ((xsoc - battery->dsoc) >= min_gap_xsoc) + battery->zero_linek = 800; + /* reserve power */ + else + battery->zero_linek = 1200; + DBG("ZERO-new: zero_linek adjust step4...\n"); + /* dsoc[5, 100], dsoc < xsoc */ + } else if ((battery->zero_linek < 1000) && + (battery->dsoc >= 5)) { + if ((xsoc - battery->dsoc) < min_gap_xsoc) { + /* reserve power */ + battery->zero_linek = 1200; + } else { + if (abs(battery->current_avg) > 500)/* heavy */ + battery->zero_linek = 900; + else + battery->zero_linek = 1000; + } + DBG("ZERO-new: zero_linek adjust step5...\n"); + /* dsoc[0~5], dsoc < xsoc */ + } else if ((battery->zero_linek < 1000) && + (battery->dsoc <= 5)) { + if ((xsoc - battery->dsoc) <= 3) + battery->zero_linek = 1200; + else + battery->zero_linek = 800; + DBG("ZERO-new: zero_linek adjust step6...\n"); + } + } else { + /* xsoc < 0 */ + battery->zero_linek = 1000; + if (!battery->zero_drop_sec) + battery->zero_drop_sec = get_boot_sec(); + if (base2sec(battery->zero_drop_sec) >= WAIT_DSOC_DROP_SEC) { + DBG("ZERO0: t=%lu\n", base2sec(battery->zero_drop_sec)); + battery->zero_drop_sec = 0; + battery->dsoc -= 1000; + if (battery->dsoc < 0) + battery->dsoc = 0; + battery->zero_dsoc = battery->dsoc; + } + } + + if (voltage_avg < pwroff_vol - 70) { + if (!battery->shtd_drop_sec) + battery->shtd_drop_sec = get_boot_sec(); + if (base2sec(battery->shtd_drop_sec) > WAIT_SHTD_DROP_SEC) { + DBG("voltage extreme low...soc:%d->0\n", battery->dsoc); + battery->shtd_drop_sec = 0; + battery->dsoc = 0; + } + } else { + battery->shtd_drop_sec = 0; + } + + DBG("Zero: zero_linek = %d\n", battery->zero_linek); +} + +static void rk817_bat_zero_algo_prepare(struct rk817_battery_device *battery) +{ + int tmp_dsoc; + + tmp_dsoc = battery->zero_dsoc / 1000; + + if (tmp_dsoc != battery->smooth_soc / 1000) + battery->zero_dsoc = battery->smooth_soc; + + DBG("zero_smooth: zero_dsoc = %d\n", battery->zero_dsoc); + + rk817_bat_calc_zero_linek(battery); +} + +static void rk817_bat_calc_zero_algorithm(struct rk817_battery_device *battery) +{ +} + +static void rk817_bat_zero_algorithm(struct rk817_battery_device *battery) +{ + int delta_cap = 0, delta_soc = 0; + + battery->zero_timeout_cnt++; + delta_cap = battery->zero_remain_cap - battery->remain_cap; + delta_soc = battery->zero_linek * (delta_cap / DIV(battery->fcc)) / 10; + + DBG("Zero: zero_remain_cap = %d, remain_cap = %d\n", + battery->zero_remain_cap, battery->remain_cap); + DBG("Zero: zero_delta_cap = %d, zero_link = %d, delta_soc = %d\n", + delta_cap, battery->zero_linek, delta_soc); + + if ((delta_soc >= MIN_ZERO_DSOC_ACCURACY) || + (battery->zero_timeout_cnt > MIN_ZERO_OVERCNT) || + (battery->zero_linek == 0)) { + DBG("ZERO1:--------- enter calc -----------\n"); + battery->zero_timeout_cnt = 0; + battery->zero_dsoc -= delta_soc; + rk817_bat_calc_zero_algorithm(battery); + rk817_bat_calc_zero_linek(battery); + } +} + +static void rk817_bat_display_smooth(struct rk817_battery_device *battery) +{ + if (battery->work_mode == MODE_ZERO) { + DBG("step2: zero algorithm...\n"); + rk817_bat_zero_algorithm(battery); + if ((battery->voltage_avg >= + battery->pdata->zero_algorithm_vol + 50) || + (battery->current_avg >= 0)) { + DBG("step2: change to smooth mode...\n"); + rk817_bat_smooth_algo_prepare(battery); + battery->work_mode = MODE_SMOOTH; + } + } else { + DBG("step3: smooth algorithm...\n"); + rk817_bat_smooth_algorithm(battery); + if ((battery->current_avg < 0) && + (battery->voltage_avg < + battery->pdata->zero_algorithm_vol)) { + DBG("step3: change to zero mode...\n"); + rk817_bat_zero_algo_prepare(battery); + battery->work_mode = MODE_ZERO; + } + } +} + +static void rk817_bat_output_info(struct rk817_battery_device *battery) +{ + DBG("info start:\n"); + DBG("info: voltage_k = %d\n", battery->voltage_k); + DBG("info: voltage_b = %d\n", battery->voltage_b); + DBG("info: voltage = %d\n", battery->voltage_avg); + DBG("info: voltage_sys = %d\n", battery->voltage_sys); + DBG("info: current = %d\n", battery->current_avg); + + DBG("info: FCC = %d\n", battery->fcc); + DBG("info: remain_cap = %d\n", battery->remain_cap); + DBG("info: sm_remain_cap = %d\n", battery->sm_remain_cap); + DBG("info: sm_link = %d\n", battery->sm_linek); + DBG("info: smooth_soc = %d\n", battery->smooth_soc); + + DBG("info: zero_remain_cap = %d\n", battery->zero_remain_cap); + DBG("info: zero_link = %d\n", battery->zero_linek); + DBG("info: zero_dsoc = %d\n", battery->zero_dsoc); + + DBG("info: remain_cap = %d\n", battery->remain_cap); + DBG("info: dsoc = %d, dsoc/1000 = %d\n", + battery->dsoc, battery->dsoc / 1000); + DBG("info: rsoc = %d\n", battery->rsoc); + DBG("info END.\n"); +} + +static void rk817_battery_work(struct work_struct *work) +{ + struct rk817_battery_device *battery = + container_of(work, + struct rk817_battery_device, + bat_delay_work.work); + + rk817_bat_update_info(battery); + rk817_bat_lowpwr_check(battery); + rk817_bat_display_smooth(battery); + + rk817_bat_power_supply_changed(battery); + rk817_bat_save_data(battery); + rk817_bat_output_info(battery); + + queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work, + msecs_to_jiffies(battery->monitor_ms)); +} + +#ifdef CONFIG_OF +static const struct of_device_id rk817_bat_of_match[] = { + { .compatible = "rk817,battery", }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk817_bat_of_match); +#else +static const struct of_device_id rk817_bat_of_match[] = { + { }, +}; +#endif + +static int rk817_battery_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(rk817_bat_of_match, &pdev->dev); + struct rk817_battery_device *battery; + struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *client = rk817->i2c; + int i, ret; + + if (!of_id) { + dev_err(&pdev->dev, "Failed to find matching dt id\n"); + return -ENODEV; + } + + battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL); + if (!battery) + return -EINVAL; + + battery->rk817 = rk817; + battery->client = client; + battery->dev = &pdev->dev; + platform_set_drvdata(pdev, battery); + + battery->regmap = devm_regmap_init_i2c(client, + &rk817_battery_regmap_config); + if (IS_ERR(battery->regmap)) { + dev_err(battery->dev, "Failed to initialize regmap\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(rk817_battery_reg_fields); i++) { + const struct reg_field *reg_fields = rk817_battery_reg_fields; + + battery->rmap_fields[i] = + devm_regmap_field_alloc(battery->dev, + battery->regmap, + reg_fields[i]); + if (IS_ERR(battery->rmap_fields[i])) { + dev_err(battery->dev, "cannot allocate regmap field\n"); + return PTR_ERR(battery->rmap_fields[i]); + } + } + + ret = rk817_bat_parse_dt(battery); + if (ret < 0) { + dev_err(battery->dev, "battery parse dt failed!\n"); + return ret; + } + + rk817_bat_init_info(battery); + rk817_bat_init_fg(battery); + + rk817_battery_debug_info(battery); + + rk817_bat_update_info(battery); + + battery->bat_monitor_wq = alloc_ordered_workqueue("%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk817-bat-monitor-wq"); + INIT_DELAYED_WORK(&battery->bat_delay_work, rk817_battery_work); + queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work, + msecs_to_jiffies(TIMER_MS_COUNTS * 5)); + + ret = rk817_bat_init_power_supply(battery); + if (ret) { + dev_err(battery->dev, "rk817 power supply register failed!\n"); + return ret; + } + + DBG("name: 0x%x", rk817_bat_field_read(battery, CHIP_NAME_H)); + DBG("%x\n", rk817_bat_field_read(battery, CHIP_NAME_L)); + + DBG("driver version %s\n", DRIVER_VERSION); + return 0; +} + +static void rk817_battery_shutdown(struct platform_device *dev) +{ +} + +#ifdef CONFIG_PM_SLEEP +static int rk817_bat_pm_suspend(struct device *dev) +{ + return 0; +} + +static int rk817_bat_pm_resume(struct device *dev) +{ + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(rk817_bat_pm_ops, + rk817_bat_pm_suspend, + rk817_bat_pm_resume); + +static struct platform_driver rk817_battery_driver = { + .probe = rk817_battery_probe, + .shutdown = rk817_battery_shutdown, + .driver = { + .name = "rk817-battery", + .pm = &rk817_bat_pm_ops, + .of_match_table = of_match_ptr(rk817_bat_of_match), + }, +}; + +static int __init rk817_battery_init(void) +{ + return platform_driver_register(&rk817_battery_driver); +} +fs_initcall_sync(rk817_battery_init); + +static void __exit rk817_battery_exit(void) +{ + platform_driver_unregister(&rk817_battery_driver); +} +module_exit(rk817_battery_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("shengfeixu "); +MODULE_DESCRIPTION("rk817 battery Charger Driver"); + From 3e1d04be48d237cf5d8aead5d2d475c7b4f08837 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Mon, 5 Feb 2018 14:43:58 +0800 Subject: [PATCH 203/427] arm64: rockchip_defconfig: enable CONFIG_BATTERY_RK817 Change-Id: Iec1ff6aad066f3d137168983104767b27c8037ef Signed-off-by: shengfei Xu --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 0ac303b9548e..eddbe8480456 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -425,6 +425,7 @@ CONFIG_TEST_POWER=y CONFIG_CHARGER_BQ25700=y CONFIG_BATTERY_EC=y CONFIG_BATTERY_CW2015=y +CONFIG_BATTERY_RK817=y CONFIG_CHARGER_RK817=y CONFIG_BATTERY_RK818=y CONFIG_CHARGER_RK818=y From 05f148f30f4c95c988099a76977a56f546707215 Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Fri, 2 Feb 2018 09:25:38 +0800 Subject: [PATCH 204/427] camera: rockchip: camsys_drv: v0.0x26.0 fix iommu resource not been released when process mediaserver crashes unexpectly. Change-Id: Ia8209f7d0a60f6a86d273e313260b87d5facecc3 Signed-off-by: Zhong Yichong --- drivers/media/video/rk_camsys/camsys_drv.c | 18 ++++++++++++++++++ .../media/video/rk_camsys/camsys_internal.h | 6 +++++- drivers/media/video/rk_camsys/camsys_marvin.c | 9 ++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/rk_camsys/camsys_drv.c b/drivers/media/video/rk_camsys/camsys_drv.c index 94a07edfd93b..ba47c656ed62 100644 --- a/drivers/media/video/rk_camsys/camsys_drv.c +++ b/drivers/media/video/rk_camsys/camsys_drv.c @@ -848,6 +848,9 @@ static int camsys_release(struct inode *inode, struct file *file) { camsys_dev_t *camsys_dev = (camsys_dev_t *)file->private_data; unsigned int i, phycnt; + camsys_sysctrl_t devctl; + camsys_iommu_t *iommu_par; + int index; camsys_irq_disconnect(NULL, camsys_dev, true); @@ -860,6 +863,21 @@ static int camsys_release(struct inode *inode, struct file *file) } } } + /* + * iommu resource might not been released when mediaserver process + * died unexpectly, so we force to release the iommu resource here + */ + devctl.dev_mask = camsys_dev->dev_id; + devctl.ops = CamSys_IOMMU; + devctl.on = 0; + iommu_par = (camsys_iommu_t *)(devctl.rev); + /* used as force release flag */ + iommu_par->client_fd = -1; + for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM ; index++) { + if (camsys_dev->iommu_cb(camsys_dev, &devctl) != 0) + break; + } + atomic_dec(&camsys_dev->refcount); camsys_trace(1, "%s(%p) is closed", diff --git a/drivers/media/video/rk_camsys/camsys_internal.h b/drivers/media/video/rk_camsys/camsys_internal.h index 78672437336b..63f06803697c 100644 --- a/drivers/media/video/rk_camsys/camsys_internal.h +++ b/drivers/media/video/rk_camsys/camsys_internal.h @@ -192,9 +192,13 @@ 1) function is the same as commit in v0.0x22.3 but now is better way. *v0.0x25.0: 1) support px30. +*v0.0x26.0: + 1) v0.0x21.9 may not fix all the case of iommu issue caused by the + unexpected termination of process cameraserver, so we force to release + all iommu resource in |.release| of fops aganin if needed. */ -#define CAMSYS_DRIVER_VERSION KERNEL_VERSION(0, 0x25, 0) +#define CAMSYS_DRIVER_VERSION KERNEL_VERSION(0, 0x26, 0) #define CAMSYS_PLATFORM_DRV_NAME "RockChip-CamSys" #define CAMSYS_PLATFORM_MARVIN_NAME "Platform_MarvinDev" diff --git a/drivers/media/video/rk_camsys/camsys_marvin.c b/drivers/media/video/rk_camsys/camsys_marvin.c index ffabb4f51ddb..bef1dc1536a9 100644 --- a/drivers/media/video/rk_camsys/camsys_marvin.c +++ b/drivers/media/video/rk_camsys/camsys_marvin.c @@ -479,11 +479,14 @@ static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl) (index >= CAMSYS_DMA_BUF_MAX_NUM)) return -EINVAL; - for (index = 0; index < camsys_dev->dma_buf_cnt; index++) { - if (camsys_dev->dma_buf[index].fd == iommu->map_fd) + for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM; index++) { + if (camsys_dev->dma_buf[index].fd == iommu->map_fd || + /* force release */ + (camsys_dev->dma_buf[index].fd != -1 && + iommu->client_fd == -1)) break; } - if (index == camsys_dev->dma_buf_cnt) { + if (index == CAMSYS_DMA_BUF_MAX_NUM) { camsys_warn("can't find map fd %d", iommu->map_fd); return -EINVAL; } From 865ddcf6c833db99b323180601d33338defb9d2b Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Fri, 2 Feb 2018 18:14:25 +0800 Subject: [PATCH 205/427] arm64: rockchip_defconfig: change CONFIG_MALI_MIDGARD from y to m Change-Id: Ibd59ece75821729b16b42c92a3ad0f5f818c1488 Signed-off-by: Zhen Chen --- arch/arm64/configs/rockchip_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index eddbe8480456..3cecc1487ebd 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -495,7 +495,7 @@ CONFIG_MALI450=y CONFIG_MALI_SHARED_INTERRUPTS=y CONFIG_MALI_DT=y CONFIG_MALI_DEVFREQ=y -CONFIG_MALI_MIDGARD=y +CONFIG_MALI_MIDGARD=m CONFIG_MALI_EXPERT=y CONFIG_MALI_PLATFORM_THIRDPARTY=y CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk" From 215241962183399024fe323d2ba74b19d0b6b7f7 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Tue, 16 Jan 2018 12:03:03 +0800 Subject: [PATCH 206/427] MALI: midgard: RK: rename output mali_kbase.ko to midgard_kbase.ko Some optimizations on files of KBuild in addition. Change-Id: I1db012e116b8b69897a2791ae610da35365a1a61 Signed-off-by: Zhen Chen --- drivers/gpu/arm/midgard/Kbuild | 18 +++++++----------- drivers/gpu/arm/midgard/platform/Kbuild | 21 --------------------- drivers/gpu/arm/midgard/platform/rk/Kbuild | 12 ++---------- 3 files changed, 9 insertions(+), 42 deletions(-) delete mode 100644 drivers/gpu/arm/midgard/platform/Kbuild diff --git a/drivers/gpu/arm/midgard/Kbuild b/drivers/gpu/arm/midgard/Kbuild index 4348704e7640..34725d60995e 100644 --- a/drivers/gpu/arm/midgard/Kbuild +++ b/drivers/gpu/arm/midgard/Kbuild @@ -13,7 +13,6 @@ # - # Driver version string which is returned to userspace via an ioctl MALI_RELEASE_NAME ?= "r14p0-01rel0" @@ -189,20 +188,17 @@ ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name) ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR) -ifeq ($(CONFIG_MALI_MIDGARD),m) +MALI_PLATFORM_DIR := platform/$(platform_name) include $(src)/platform/$(platform_name)/Kbuild -else ifeq ($(CONFIG_MALI_MIDGARD),y) -obj-$(CONFIG_MALI_MIDGARD) += platform/ -endif endif # Tell the Linux build system from which .o file to create the kernel module -obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o +obj-$(CONFIG_MALI_MIDGARD) += midgard_kbase.o # Tell the Linux build system to enable building of our .c files -mali_kbase-y := $(SRC:.c=.o) +midgard_kbase-y := $(SRC:.c=.o) -mali_kbase-$(CONFIG_MALI_DMA_FENCE) += mali_kbase_dma_fence.o +midgard_kbase-$(CONFIG_MALI_DMA_FENCE) += mali_kbase_dma_fence.o MALI_BACKEND_PATH ?= backend CONFIG_MALI_BACKEND ?= gpu @@ -211,12 +207,12 @@ CONFIG_MALI_BACKEND_REAL ?= $(CONFIG_MALI_BACKEND) ifeq ($(MALI_MOCK_TEST),1) ifeq ($(CONFIG_MALI_BACKEND_REAL),gpu) # Test functionality -mali_kbase-y += tests/internal/src/mock/mali_kbase_pm_driver_mock.o +midgard_kbase-y += tests/internal/src/mock/mali_kbase_pm_driver_mock.o endif endif include $(src)/$(MALI_BACKEND_PATH)/$(CONFIG_MALI_BACKEND_REAL)/Kbuild -mali_kbase-y += $(BACKEND:.c=.o) +midgard_kbase-y += $(BACKEND:.c=.o) ccflags-y += -I$(src)/$(MALI_BACKEND_PATH)/$(CONFIG_MALI_BACKEND_REAL) subdir-ccflags-y += -I$(src)/$(MALI_BACKEND_PATH)/$(CONFIG_MALI_BACKEND_REAL) @@ -227,7 +223,7 @@ ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY)$(CONFIG_MALI_PLATFORM_FAKE),) CONFIG_MALI_PLATFORM_DEVICETREE := y endif -mali_kbase-$(CONFIG_MALI_PLATFORM_DEVICETREE) += \ +midgard_kbase-$(CONFIG_MALI_PLATFORM_DEVICETREE) += \ platform/devicetree/mali_kbase_runtime_pm.o \ platform/devicetree/mali_kbase_config_devicetree.o ccflags-$(CONFIG_MALI_PLATFORM_DEVICETREE) += -I$(src)/platform/devicetree diff --git a/drivers/gpu/arm/midgard/platform/Kbuild b/drivers/gpu/arm/midgard/platform/Kbuild deleted file mode 100644 index 558657bbced9..000000000000 --- a/drivers/gpu/arm/midgard/platform/Kbuild +++ /dev/null @@ -1,21 +0,0 @@ -# -# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the -# GNU General Public License version 2 as published by the Free Software -# Foundation, and any use by you of this program is subject to the terms -# of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained -# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# - - - -ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) -# remove begin and end quotes from the Kconfig string type - platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) - obj-y += $(platform_name)/ -endif diff --git a/drivers/gpu/arm/midgard/platform/rk/Kbuild b/drivers/gpu/arm/midgard/platform/rk/Kbuild index 700fd4341da5..95ca23bd9695 100755 --- a/drivers/gpu/arm/midgard/platform/rk/Kbuild +++ b/drivers/gpu/arm/midgard/platform/rk/Kbuild @@ -12,14 +12,6 @@ # # -ccflags-y += -I$(srctree)/drivers/staging/android +SRC += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_rk.o \ -ifeq ($(CONFIG_MALI_MIDGARD),y) -obj-y += mali_kbase_config_rk.o -# obj-y += mali_kbase_dvfs.o -# obj-y += mali_kbase_platform.o -else ifeq ($(CONFIG_MALI_MIDGARD),m) -SRC += platform/rk/mali_kbase_config_rk.c -# SRC += platform/rk/mali_kbase_dvfs.c -# SRC += platform/rk/mali_kbase_platform.c -endif From 7481e8328c0986d3177bfc30b5f7dd568d91317b Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 17 Jan 2018 14:48:17 +0800 Subject: [PATCH 207/427] MALI: bifrost: add rk_platform_specific_code Copyed from midgard/platform/rk at commit 77a680a3. Change-Id: Iaa218e2183e5fc6ef34f50678fc34376a54a29a4 Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/platform/rk/Kbuild | 25 + .../gpu/arm/bifrost/platform/rk/custom_log.h | 192 +++++ .../platform/rk/mali_kbase_config_platform.h | 88 +++ .../platform/rk/mali_kbase_config_rk.c | 721 ++++++++++++++++++ .../arm/bifrost/platform/rk/mali_kbase_rk.h | 62 ++ 5 files changed, 1088 insertions(+) create mode 100755 drivers/gpu/arm/bifrost/platform/rk/Kbuild create mode 100755 drivers/gpu/arm/bifrost/platform/rk/custom_log.h create mode 100755 drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_platform.h create mode 100755 drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c create mode 100755 drivers/gpu/arm/bifrost/platform/rk/mali_kbase_rk.h diff --git a/drivers/gpu/arm/bifrost/platform/rk/Kbuild b/drivers/gpu/arm/bifrost/platform/rk/Kbuild new file mode 100755 index 000000000000..700fd4341da5 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/rk/Kbuild @@ -0,0 +1,25 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +ccflags-y += -I$(srctree)/drivers/staging/android + +ifeq ($(CONFIG_MALI_MIDGARD),y) +obj-y += mali_kbase_config_rk.o +# obj-y += mali_kbase_dvfs.o +# obj-y += mali_kbase_platform.o +else ifeq ($(CONFIG_MALI_MIDGARD),m) +SRC += platform/rk/mali_kbase_config_rk.c +# SRC += platform/rk/mali_kbase_dvfs.c +# SRC += platform/rk/mali_kbase_platform.c +endif diff --git a/drivers/gpu/arm/bifrost/platform/rk/custom_log.h b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h new file mode 100755 index 000000000000..5de70ee13d25 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h @@ -0,0 +1,192 @@ +/* + * (C) COPYRIGHT RockChip Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + */ + +#ifndef __CUSTOM_LOG_H__ +#define __CUSTOM_LOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------------------------- + * Include Files + * ----------------------------------------------------------------------------- + */ +#include +#include + +/* ----------------------------------------------------------------------------- + * Macros Definition + * ----------------------------------------------------------------------------- + */ + +/** 若下列 macro 有被定义, æ‰ ä½¿èƒ½ log 输出. */ +/* #define ENABLE_DEBUG_LOG */ + +/*----------------------------------------------------------------------------*/ + +#ifdef ENABLE_VERBOSE_LOG +/** Verbose log. */ +#define V(fmt, args...) \ + pr_debug("V : [File] : %s; [Line] : %d; [Func] : %s(); " fmt \ + "\n", \ + __FILE__, \ + __LINE__, \ + __func__, \ + ## args) +#else +#define V(...) ((void)0) +#endif + +#ifdef ENABLE_DEBUG_LOG +/** Debug log. */ +#define D(fmt, args...) \ + pr_info("D : [File] : %s; [Line] : %d; [Func] : %s(); " fmt \ + "\n", \ + __FILE__, \ + __LINE__, \ + __func__, \ + ## args) +#else +#define D(...) ((void)0) +#endif + +#define I(fmt, args...) \ + pr_info("I : [File] : %s; [Line] : %d; [Func] : %s(); " fmt \ + "\n", \ + __FILE__, \ + __LINE__, \ + __func__, \ + ## args) + +#define W(fmt, args...) \ + pr_warn("W : [File] : %s; [Line] : %d; [Func] : %s(); " \ + fmt "\n", \ + __FILE__, \ + __LINE__, \ + __func__, \ + ## args) + +#define E(fmt, args...) \ + pr_err("E : [File] : %s; [Line] : %d; [Func] : %s(); " fmt \ + "\n", \ + __FILE__, \ + __LINE__, \ + __func__, \ + ## args) + +/*-------------------------------------------------------*/ + +/** 使用 D(), 以åè¿›åˆ¶çš„å½¢å¼æ‰“å°å˜é‡ 'var' çš„ value. */ +#define D_DEC(var) D(#var " = %d.", var) + +#define E_DEC(var) E(#var " = %d.", var) + +/** 使用 D(), 以åå…­è¿›åˆ¶çš„å½¢å¼æ‰“å°å˜é‡ 'var' çš„ value. */ +#define D_HEX(var) D(#var " = 0x%x.", var) + +#define E_HEX(var) E(#var " = 0x%x.", var) + +/** + * 使用 D(), 以å六进制的形å¼, + * æ‰“å°æŒ‡é’ˆç±»åž‹å˜é‡ 'ptr' çš„ value. + */ +#define D_PTR(ptr) D(#ptr " = %p.", ptr) + +#define E_PTR(ptr) E(#ptr " = %p.", ptr) + +/** 使用 D(), æ‰“å° char 字串. */ +#define D_STR(p_str) \ +do { \ + if (!p_str) { \ + D(#p_str " = NULL."); \ + else \ + D(#p_str " = '%s'.", p_str); \ +} while (0) + +#define E_STR(p_str) \ +do { \ + if (!p_str) \ + E(#p_str " = NULL."); \ + else \ + E(#p_str " = '%s'.", p_str); \ +} while (0) + +#ifdef ENABLE_DEBUG_LOG +/** + * log 从 'p_start' 地å€å¼€å§‹çš„ 'len' 个字节的数æ®. + */ +#define D_MEM(p_start, len) \ +do { \ + int i = 0; \ + char *p = (char *)(p_start); \ + D("dump memory from addr of '" #p_start "', from %p, length %d' : ", \ + (p_start), \ + (len)); \ + pr_debug("\t\t"); \ + for (i = 0; i < (len); i++) \ + pr_debug("0x%02x, ", p[i]); \ + pr_debug("\n"); \ +} while (0) +#else +#define D_MEM(...) ((void)0) +#endif + +/*-------------------------------------------------------*/ + +/** + * 在特定æ¡ä»¶ä¸‹, 判定 error å‘生, + * å°†å˜é‡ 'ret_var' 设置 'err_code', + * log 输出对应的 Error Caution, + * ç„¶åŽè·³è½¬ 'label' 指定的代ç å¤„执行. + * @param msg + * 纯字串形å¼çš„æç¤ºä¿¡æ¯. + * @param ret_var + * æ ‡è¯†å‡½æ•°æ‰§è¡ŒçŠ¶æ€æˆ–者结果的å˜é‡, + * 将被设置具体的 Error Code. + * 通常是 'ret' or 'result'. + * @param err_code + * 表å¾ç‰¹å®š error 的常数标识, + * 通常是 å®çš„å½¢æ€. + * @param label + * 程åºå°†è¦è·³è½¬åˆ°çš„错误处ç†ä»£ç çš„æ ‡å·, + * 通常就是 'EXIT'. + * @param args... + * 对应 'msg_fmt' 实å‚中, + * '%s', '%d', ... 等转æ¢è¯´æ˜Žç¬¦çš„具体å¯å˜é•¿å®žå‚. + */ +#define SET_ERROR_AND_JUMP(msg_fmt, ret_var, err_code, label, args...) \ +do { \ + E("To set '" #ret_var "' to %d('" #err_code "'), because : " msg_fmt, \ + (err_code), \ + ## args); \ + (ret_var) = (err_code); \ + goto label; \ +} while (0) + +/* ----------------------------------------------------------------------------- + * Types and Structures Definition + * ----------------------------------------------------------------------------- + */ + +/* ----------------------------------------------------------------------------- + * Global Functions' Prototype + * ----------------------------------------------------------------------------- + */ + +/* ----------------------------------------------------------------------------- + * Inline Functions Implementation + * ----------------------------------------------------------------------------- + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CUSTOM_LOG_H__ */ diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_platform.h new file mode 100755 index 000000000000..07c5b6f8a760 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_platform.h @@ -0,0 +1,88 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + */ + +/** + * @file mali_kbase_config_platform.h + * 声明 platform_config_of_rk (platform_rk çš„ platform_config). + */ + +/** + * Maximum frequency GPU will be clocked at. + * Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX (5000) + +/** + * Minimum frequency GPU will be clocked at. + * Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN (5000) + +/** + * CPU_SPEED_FUNC + * - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz + * - see kbase_cpu_clk_speed_func for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (NULL) + +/** + * GPU_SPEED_FUNC + * - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz + * - see kbase_gpu_clk_speed_func for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: + * pointer to @ref kbase_pm_callback_conf + * Default value: + * See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) +extern struct kbase_pm_callback_conf pm_callbacks; + +/** + * Platform specific configuration functions + * + * Attached value: + * pointer to @ref kbase_platform_funcs_conf + * Default value: + * See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (&platform_funcs) +extern struct kbase_platform_funcs_conf platform_funcs; + +/** + * Secure mode switch + * + * Attached value: pointer to @ref kbase_secure_ops + */ +#define SECURE_CALLBACKS (NULL) + diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c new file mode 100755 index 000000000000..34fd896c6489 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -0,0 +1,721 @@ +/* + * (C) COPYRIGHT RockChip Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + */ + +/* #define ENABLE_DEBUG_LOG */ +#include "custom_log.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mali_kbase_rk.h" + +#define MAX_PROP_NAME_LEN 3 +#define LEAKAGE_TABLE_END ~1 +#define LEAKAGE_INVALID 0xff + +struct pvtm_config { + unsigned int freq; + unsigned int volt; + unsigned int ch[2]; + unsigned int sample_time; + unsigned int num; + unsigned int err; + unsigned int ref_temp; + int temp_prop[2]; + const char *tz_name; + struct thermal_zone_device *tz; +}; + +struct volt_sel_table { + int min; + int max; + int sel; +}; + +/** + * @file mali_kbase_config_rk.c + * 对 platform_config_of_rk 的具体实现. + * + * mali_device_driver 包å«ä¸¤éƒ¨åˆ† : + * .DP : platform_dependent_part_in_mdd : + * ä¾èµ– platform 部分, + * æºç åœ¨ /platform// + * 在 mali_device_driver 内部, + * 记为 platform_dependent_part, + * 也被记为 platform_specific_code. + * .DP : common_parts_in_mdd : + * arm 实现的通用的部分, + * æºç åœ¨ / 下. + * 在 mali_device_driver 内部, 记为 common_parts. + */ + +/*---------------------------------------------------------------------------*/ + +#ifdef CONFIG_REGULATOR +static int rk_pm_enable_regulator(struct kbase_device *kbdev); +static void rk_pm_disable_regulator(struct kbase_device *kbdev); +#else +static inline int rk_pm_enable_regulator(struct kbase_device *kbdev) +{ + return 0; +} + +static inline void rk_pm_disable_regulator(struct kbase_device *kbdev) +{ +} +#endif + +static int rk_pm_enable_clk(struct kbase_device *kbdev); + +static void rk_pm_disable_clk(struct kbase_device *kbdev); + +static int kbase_platform_rk_create_sysfs_files(struct device *dev); + +static void kbase_platform_rk_remove_sysfs_files(struct device *dev); + +/*---------------------------------------------------------------------------*/ + +static void rk_pm_power_off_delay_work(struct work_struct *work) +{ + struct rk_context *platform = + container_of(to_delayed_work(work), struct rk_context, work); + struct kbase_device *kbdev = platform->kbdev; + + if (!platform->is_powered) { + D("mali_dev is already powered off."); + return; + } + + if (pm_runtime_enabled(kbdev->dev)) { + D("to put_sync_suspend mali_dev."); + pm_runtime_put_sync_suspend(kbdev->dev); + } + + rk_pm_disable_regulator(kbdev); + + platform->is_powered = false; + KBASE_TIMELINE_GPU_POWER(kbdev, 0); + wake_unlock(&platform->wake_lock); +} + +static int kbase_platform_rk_init(struct kbase_device *kbdev) +{ + int ret = 0; + struct rk_context *platform; + + platform = kzalloc(sizeof(*platform), GFP_KERNEL); + if (!platform) { + E("err."); + return -ENOMEM; + } + + platform->is_powered = false; + platform->kbdev = kbdev; + + platform->delay_ms = 200; + if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms", + &platform->delay_ms)) + W("power-off-delay-ms not available."); + + platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq"); + if (!platform->power_off_wq) { + E("couldn't create workqueue"); + ret = -ENOMEM; + goto err_wq; + } + INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work); + + wake_lock_init(&platform->wake_lock, WAKE_LOCK_SUSPEND, "gpu"); + + platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS; + + ret = kbase_platform_rk_create_sysfs_files(kbdev->dev); + if (ret) { + E("fail to create sysfs_files. ret = %d.", ret); + goto err_sysfs_files; + } + + kbdev->platform_context = (void *)platform; + pm_runtime_enable(kbdev->dev); + + return 0; + +err_sysfs_files: + wake_lock_destroy(&platform->wake_lock); + destroy_workqueue(platform->power_off_wq); +err_wq: + return ret; +} + +static void kbase_platform_rk_term(struct kbase_device *kbdev) +{ + struct rk_context *platform = + (struct rk_context *)kbdev->platform_context; + + pm_runtime_disable(kbdev->dev); + kbdev->platform_context = NULL; + + if (platform) { + wake_lock_destroy(&platform->wake_lock); + destroy_workqueue(platform->power_off_wq); + platform->is_powered = false; + platform->kbdev = NULL; + kfree(platform); + } + kbase_platform_rk_remove_sysfs_files(kbdev->dev); +} + +struct kbase_platform_funcs_conf platform_funcs = { + .platform_init_func = &kbase_platform_rk_init, + .platform_term_func = &kbase_platform_rk_term, +}; + +/*---------------------------------------------------------------------------*/ + +static int rk_pm_callback_runtime_on(struct kbase_device *kbdev) +{ + return 0; +} + +static void rk_pm_callback_runtime_off(struct kbase_device *kbdev) +{ +} + +static int rk_pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret = 1; /* Assume GPU has been powered off */ + int err = 0; + struct rk_context *platform = get_rk_context(kbdev); + + cancel_delayed_work_sync(&platform->work); + + err = rk_pm_enable_clk(kbdev); + if (err) { + E("failed to enable clk: %d", err); + return err; + } + + if (platform->is_powered) { + D("mali_device is already powered."); + return 0; + } + + /* we must enable vdd_gpu before pd_gpu_in_chip. */ + err = rk_pm_enable_regulator(kbdev); + if (err) { + E("fail to enable regulator, err : %d.", err); + return err; + } + + /* è‹¥ mali_dev çš„ runtime_pm 是 enabled çš„, 则... */ + if (pm_runtime_enabled(kbdev->dev)) { + D("to resume mali_dev syncly."); + /* 对 pd_in_chip çš„ on æ“作, + * 将在 pm_domain çš„ runtime_pm_callbacks 中完æˆ. + */ + err = pm_runtime_get_sync(kbdev->dev); + if (err < 0) { + E("failed to runtime resume device: %d.", err); + return err; + } else if (err == 1) { /* runtime_pm_status is still active */ + D("chip has NOT been powered off, no need to re-init."); + ret = 0; + } + } + + platform->is_powered = true; + KBASE_TIMELINE_GPU_POWER(kbdev, 1); + wake_lock(&platform->wake_lock); + + return ret; +} + +static void rk_pm_callback_power_off(struct kbase_device *kbdev) +{ + struct rk_context *platform = get_rk_context(kbdev); + + rk_pm_disable_clk(kbdev); + queue_delayed_work(platform->power_off_wq, &platform->work, + msecs_to_jiffies(platform->delay_ms)); +} + +int rk_kbase_device_runtime_init(struct kbase_device *kbdev) +{ + return 0; +} + +void rk_kbase_device_runtime_disable(struct kbase_device *kbdev) +{ +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = rk_pm_callback_power_on, + .power_off_callback = rk_pm_callback_power_off, +#ifdef CONFIG_PM + .power_runtime_init_callback = rk_kbase_device_runtime_init, + .power_runtime_term_callback = rk_kbase_device_runtime_disable, + .power_runtime_on_callback = rk_pm_callback_runtime_on, + .power_runtime_off_callback = rk_pm_callback_runtime_off, +#else /* CONFIG_PM */ + .power_runtime_init_callback = NULL, + .power_runtime_term_callback = NULL, + .power_runtime_on_callback = NULL, + .power_runtime_off_callback = NULL, +#endif /* CONFIG_PM */ +}; + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + +/*---------------------------------------------------------------------------*/ + +void kbase_platform_rk_shutdown(struct kbase_device *kbdev) +{ + I("to make vdd_gpu enabled for turning off pd_gpu in pm_framework."); + rk_pm_enable_regulator(kbdev); +} + +/*---------------------------------------------------------------------------*/ + +#ifdef CONFIG_REGULATOR +static int rk_pm_enable_regulator(struct kbase_device *kbdev) +{ + int ret = 0; + + if (!kbdev->regulator) { + W("no mali regulator control, no need to enable."); + goto EXIT; + } + + D("to enable regulator."); + ret = regulator_enable(kbdev->regulator); + if (ret) { + E("fail to enable regulator, ret : %d.", ret); + goto EXIT; + } + +EXIT: + return ret; +} + +static void rk_pm_disable_regulator(struct kbase_device *kbdev) +{ + if (!(kbdev->regulator)) { + W("no mali regulator control, no need to disable."); + return; + } + + D("to disable regulator."); + regulator_disable(kbdev->regulator); +} +#endif + +static int rk_pm_enable_clk(struct kbase_device *kbdev) +{ + int err = 0; + + if (!(kbdev->clock)) { + W("no mali clock control, no need to enable."); + } else { + D("to enable clk."); + err = clk_enable(kbdev->clock); + if (err) + E("failed to enable clk: %d.", err); + } + + return err; +} + +static void rk_pm_disable_clk(struct kbase_device *kbdev) +{ + if (!(kbdev->clock)) { + W("no mali clock control, no need to disable."); + } else { + D("to disable clk."); + clk_disable(kbdev->clock); + } +} + +/*---------------------------------------------------------------------------*/ + +static ssize_t utilisation_period_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct rk_context *platform = get_rk_context(kbdev); + ssize_t ret = 0; + + ret += snprintf(buf, PAGE_SIZE, "%u\n", platform->utilisation_period); + + return ret; +} + +static ssize_t utilisation_period_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct rk_context *platform = get_rk_context(kbdev); + int ret = 0; + + ret = kstrtouint(buf, 0, &platform->utilisation_period); + if (ret) { + E("invalid input period : %s.", buf); + return ret; + } + D("set utilisation_period to '%d'.", platform->utilisation_period); + + return count; +} + +static ssize_t utilisation_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct rk_context *platform = get_rk_context(kbdev); + ssize_t ret = 0; + unsigned long period_in_us = platform->utilisation_period * 1000; + unsigned long total_time; + unsigned long busy_time; + unsigned long utilisation; + + kbase_pm_reset_dvfs_utilisation(kbdev); + usleep_range(period_in_us, period_in_us + 100); + kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); + /* 'devfreq_dev_profile' instance registered to devfreq + * also uses kbase_pm_reset_dvfs_utilisation + * and kbase_pm_get_dvfs_utilisation. + * it's better to cat this file when DVFS is disabled. + */ + D("total_time : %lu, busy_time : %lu.", total_time, busy_time); + + utilisation = busy_time * 100 / total_time; + ret += snprintf(buf, PAGE_SIZE, "%ld\n", utilisation); + + return ret; +} + +static DEVICE_ATTR_RW(utilisation_period); +static DEVICE_ATTR_RO(utilisation); + +static int kbase_platform_rk_create_sysfs_files(struct device *dev) +{ + int ret = 0; + + ret = device_create_file(dev, &dev_attr_utilisation_period); + if (ret) { + E("fail to create sysfs file 'utilisation_period'."); + goto out; + } + + ret = device_create_file(dev, &dev_attr_utilisation); + if (ret) { + E("fail to create sysfs file 'utilisation'."); + goto remove_utilisation_period; + } + + return 0; + +remove_utilisation_period: + device_remove_file(dev, &dev_attr_utilisation_period); +out: + return ret; +} + +static void kbase_platform_rk_remove_sysfs_files(struct device *dev) +{ + device_remove_file(dev, &dev_attr_utilisation_period); + device_remove_file(dev, &dev_attr_utilisation); +} + +static int rockchip_get_efuse_value(struct device_node *np, char *porp_name, + int *value) +{ + struct nvmem_cell *cell; + unsigned char *buf; + size_t len; + + cell = of_nvmem_cell_get(np, porp_name); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = (unsigned char *)nvmem_cell_read(cell, &len); + + nvmem_cell_put(cell); + + if (IS_ERR(buf)) + return PTR_ERR(buf); + + if (buf[0] == LEAKAGE_INVALID) + return -EINVAL; + + *value = buf[0]; + + kfree(buf); + + return 0; +} + +static int rockchip_get_volt_sel_table(struct device_node *np, char *porp_name, + struct volt_sel_table **table) +{ + struct volt_sel_table *sel_table; + const struct property *prop; + int count, i; + + prop = of_find_property(np, porp_name, NULL); + if (!prop) + return -EINVAL; + + if (!prop->value) + return -ENODATA; + + count = of_property_count_u32_elems(np, porp_name); + if (count < 0) + return -EINVAL; + + if (count % 3) + return -EINVAL; + + sel_table = kzalloc(sizeof(*sel_table) * (count / 3 + 1), GFP_KERNEL); + if (!sel_table) + return -ENOMEM; + + for (i = 0; i < count / 3; i++) { + of_property_read_u32_index(np, porp_name, 3 * i, + &sel_table[i].min); + of_property_read_u32_index(np, porp_name, 3 * i + 1, + &sel_table[i].max); + of_property_read_u32_index(np, porp_name, 3 * i + 2, + &sel_table[i].sel); + } + sel_table[i].min = 0; + sel_table[i].max = 0; + sel_table[i].sel = LEAKAGE_TABLE_END; + + *table = sel_table; + + return 0; +} + +static int rockchip_get_volt_sel(struct device_node *np, char *name, + int value, int *sel) +{ + struct volt_sel_table *table; + int i, j = -1, ret; + + ret = rockchip_get_volt_sel_table(np, name, &table); + if (ret) + return -EINVAL; + + for (i = 0; table[i].sel != LEAKAGE_TABLE_END; i++) { + if (value >= table[i].min) + j = i; + } + if (j != -1) + *sel = table[j].sel; + else + ret = -EINVAL; + + kfree(table); + + return ret; +} + +static int rockchip_parse_pvtm_config(struct device_node *np, + struct pvtm_config *pvtm) +{ + if (!of_find_property(np, "rockchip,pvtm-voltage-sel", NULL)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-freq", &pvtm->freq)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-volt", &pvtm->volt)) + return -EINVAL; + if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-sample-time", + &pvtm->sample_time)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err)) + return -EINVAL; + if (of_property_read_u32(np, "rockchip,pvtm-ref-temp", &pvtm->ref_temp)) + return -EINVAL; + if (of_property_read_u32_array(np, "rockchip,pvtm-temp-prop", + pvtm->temp_prop, 2)) + return -EINVAL; + if (of_property_read_string(np, "rockchip,pvtm-thermal-zone", + &pvtm->tz_name)) + return -EINVAL; + pvtm->tz = thermal_zone_get_zone_by_name(pvtm->tz_name); + if (IS_ERR(pvtm->tz)) + return -EINVAL; + if (!pvtm->tz->ops->get_temp) + return -EINVAL; + + return 0; +} + +static int rockchip_get_pvtm_specific_value(struct device *dev, + struct device_node *np, + struct clk *clk, + struct regulator *reg, + int *target_value) +{ + struct pvtm_config *pvtm; + unsigned long old_freq; + unsigned int old_volt; + int cur_temp, diff_temp; + int cur_value, total_value, avg_value, diff_value; + int min_value, max_value; + int ret = 0, i = 0, retry = 2; + + pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL); + if (!pvtm) + return -ENOMEM; + + ret = rockchip_parse_pvtm_config(np, pvtm); + if (ret) + goto pvtm_value_out; + + old_freq = clk_get_rate(clk); + old_volt = regulator_get_voltage(reg); + + /* + * Set pvtm_freq to the lowest frequency in dts, + * so change frequency first. + */ + ret = clk_set_rate(clk, pvtm->freq * 1000); + if (ret) { + dev_err(dev, "Failed to set pvtm freq\n"); + goto pvtm_value_out; + } + + ret = regulator_set_voltage(reg, pvtm->volt, pvtm->volt); + if (ret) { + dev_err(dev, "Failed to set pvtm_volt\n"); + goto restore_clk; + } + + /* The first few values may be fluctuant, if error is too big, retry*/ + while (retry--) { + total_value = 0; + min_value = INT_MAX; + max_value = 0; + + for (i = 0; i < pvtm->num; i++) { + cur_value = rockchip_get_pvtm_value(pvtm->ch[0], + pvtm->ch[1], + pvtm->sample_time); + if (!cur_value) + goto resetore_volt; + if (cur_value < min_value) + min_value = cur_value; + if (cur_value > max_value) + max_value = cur_value; + total_value += cur_value; + } + if (max_value - min_value < pvtm->err) + break; + } + avg_value = total_value / pvtm->num; + + /* + * As pvtm is influenced by temperature, compute difference between + * current temperature and reference temperature + */ + pvtm->tz->ops->get_temp(pvtm->tz, &cur_temp); + diff_temp = (cur_temp / 1000 - pvtm->ref_temp); + diff_value = diff_temp * + (diff_temp < 0 ? pvtm->temp_prop[0] : pvtm->temp_prop[1]); + *target_value = avg_value + diff_value; + + dev_info(dev, "temp=%d, pvtm=%d (%d + %d)\n", + cur_temp, *target_value, avg_value, diff_value); + +resetore_volt: + regulator_set_voltage(reg, old_volt, old_volt); +restore_clk: + clk_set_rate(clk, old_freq); +pvtm_value_out: + kfree(pvtm); + + return ret; +} + +void kbase_platform_rk_set_opp_info(struct kbase_device *kbdev) +{ + struct device_node *np; + char name[MAX_PROP_NAME_LEN]; + int pvmt_value, leakage; + int lkg_volt_sel, pvtm_volt_sel, volt_sel = -1; + int err = 0; + + if (!kbdev) + return; + + if (IS_ERR_OR_NULL(kbdev->regulator)) + return; + if (IS_ERR_OR_NULL(kbdev->clock)) + return; + + np = of_parse_phandle(kbdev->dev->of_node, "operating-points-v2", 0); + if (!np) { + dev_warn(kbdev->dev, "OPP-v2 not supported\n"); + return; + } + + err = rockchip_get_efuse_value(np, "gpu_leakage", &leakage); + if (!err) { + dev_info(kbdev->dev, "leakage=%d\n", leakage); + err = rockchip_get_volt_sel(np, "rockchip,leakage-voltage-sel", + leakage, &lkg_volt_sel); + if (!err) { + dev_info(kbdev->dev, "leakage-sel=%d\n", lkg_volt_sel); + volt_sel = lkg_volt_sel; + } + } + + err = rockchip_get_pvtm_specific_value(kbdev->dev, np, kbdev->clock, + kbdev->regulator, + &pvmt_value); + if (!err) { + err = rockchip_get_volt_sel(np, "rockchip,pvtm-voltage-sel", + pvmt_value, &pvtm_volt_sel); + if (!err) { + dev_info(kbdev->dev, "pvtm-sel=%d\n", pvtm_volt_sel); + if (volt_sel < 0 || volt_sel > pvtm_volt_sel) + volt_sel = pvtm_volt_sel; + } + } + + if (volt_sel >= 0) { + snprintf(name, MAX_PROP_NAME_LEN, "L%d", volt_sel); + err = dev_pm_opp_set_prop_name(kbdev->dev, name); + if (err) + dev_err(kbdev->dev, "Failed to set prop name\n"); + } +} diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_rk.h b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_rk.h new file mode 100755 index 000000000000..6eab25014d21 --- /dev/null +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_rk.h @@ -0,0 +1,62 @@ +/* drivers/gpu/t6xx/kbase/src/platform/rk/mali_kbase_platform.h + * Rockchip SoC Mali-Midgard platform-dependent codes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software FoundatIon. + */ + +/** + * @file mali_kbase_rk.h + * + * defines work_context type of platform_dependent_part. + */ + +#ifndef _MALI_KBASE_RK_H_ +#define _MALI_KBASE_RK_H_ + +#include + +/*---------------------------------------------------------------------------*/ + +#define DEFAULT_UTILISATION_PERIOD_IN_MS (100) + +/*---------------------------------------------------------------------------*/ + +/* + * struct rk_context - work_context of platform_dependent_part_of_rk. + */ +struct rk_context { + /* + * record the status of common_parts calling 'power_on_callback' + * and 'power_off_callback'. + */ + bool is_powered; + + struct kbase_device *kbdev; + + struct workqueue_struct *power_off_wq; + /* delayed_work_to_power_off_gpu. */ + struct delayed_work work; + unsigned int delay_ms; + + /* + * WAKE_LOCK_SUSPEND for ensuring to run + * delayed_work_to_power_off_gpu before suspend. + */ + struct wake_lock wake_lock; + + /* debug only, the period in ms to count gpu_utilisation. */ + unsigned int utilisation_period; +}; + +/*---------------------------------------------------------------------------*/ + +static inline struct rk_context *get_rk_context( + const struct kbase_device *kbdev) +{ + return (struct rk_context *)(kbdev->platform_context); +} + +#endif /* _MALI_KBASE_RK_H_ */ + From 554fe49f4ae9fe2a699c6ce41690ea0d3f81381b Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Mon, 5 Feb 2018 16:11:41 +0800 Subject: [PATCH 208/427] arm64: dts: rockchip: add rk817 charger config for rk3326 Change-Id: I7bbbce5cfa934328ec2f108f079f0649ca8a66f2 Signed-off-by: shengfei Xu --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 12 ++++++++++++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 879ae083ce96..5fac5477dd41 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -435,6 +435,18 @@ regulator-name = "otg_switch"; }; }; + + charger { + compatible = "rk817,charger"; + min_input_voltage = <4500>; + max_input_current = <1500>; + max_chrg_current = <1300>; + max_chrg_voltage = <4200>; + chrg_term_mode = <1>; + chrg_finish_cur = <300>; + virtual_power = <0>; + dc_det_adc = <0>; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 583dfe71ffba..02d369bdd600 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -532,6 +532,18 @@ regulator-name = "otg_switch"; }; }; + + charger { + compatible = "rk817,charger"; + min_input_voltage = <4500>; + max_input_current = <1500>; + max_chrg_current = <1300>; + max_chrg_voltage = <4200>; + chrg_term_mode = <1>; + chrg_finish_cur = <300>; + virtual_power = <0>; + dc_det_adc = <0>; + }; }; }; From 78394789698c8484f856420809036c93fb4b945e Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Mon, 5 Feb 2018 16:20:34 +0800 Subject: [PATCH 209/427] arm64: dts: rockchip: add rk817 battery config for rk3326 Change-Id: I76c998abe9b6c6f34365c0b5aedd304af28f58e3 Signed-off-by: shengfei Xu --- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 19 +++++++++++++++++++ .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 5fac5477dd41..f35560cdd9df 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -436,6 +436,25 @@ }; }; + battery { + compatible = "rk817,battery"; + ocv_table = <3500 3625 3685 3697 3718 3735 3748 + 3760 3774 3788 3802 3816 3834 3853 + 3877 3908 3946 3975 4018 4071 4106>; + design_capacity = <2500>; + design_qmax = <2750>; + bat_res = <100>; + sleep_enter_current = <300>; + sleep_exit_current = <300>; + sleep_filter_current = <100>; + power_off_thresd = <3500>; + zero_algorithm_vol = <3850>; + max_soc_offset = <60>; + monitor_sec = <5>; + sample_res = <10>; + virtual_power = <1>; + }; + charger { compatible = "rk817,charger"; min_input_voltage = <4500>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 02d369bdd600..c7129d6e60e7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -533,6 +533,25 @@ }; }; + battery { + compatible = "rk817,battery"; + ocv_table = <3500 3625 3685 3697 3718 3735 3748 + 3760 3774 3788 3802 3816 3834 3853 + 3877 3908 3946 3975 4018 4071 4106>; + design_capacity = <2500>; + design_qmax = <2750>; + bat_res = <100>; + sleep_enter_current = <300>; + sleep_exit_current = <300>; + sleep_filter_current = <100>; + power_off_thresd = <3500>; + zero_algorithm_vol = <3850>; + max_soc_offset = <60>; + monitor_sec = <5>; + sample_res = <10>; + virtual_power = <1>; + }; + charger { compatible = "rk817,charger"; min_input_voltage = <4500>; From 74645caeb73c724394ca67349d518fa09307f975 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 2 Feb 2018 19:19:51 +0800 Subject: [PATCH 210/427] arm64: dts: rockchip: add parameters in CommandLine for px30-android Some parameters in rk-parameter are not included in gpt mode, so we need move these parameters into CommandLine. Change-Id: Ia17d7bfc8841531c0cce0d257ff12efdef9f4c64 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-android.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index 0d80981372c1..c6d37ef8cdd7 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -6,7 +6,7 @@ / { chosen { - bootargs = "earlyprintk=uart8250,mmio32,0xff160000 swiotlb=1"; + bootargs = "earlyprintk=uart8250,mmio32,0xff160000 swiotlb=1 console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.veritymode=/dev/block/by-name/metadata androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init"; }; fiq-debugger { From 52a3c97e1d489df9405a0ba56c3cf3d55373a274 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Mon, 5 Feb 2018 16:03:21 +0800 Subject: [PATCH 211/427] arm64: dts: rockchip: remove duplicate and reorder nodes for px30 Change-Id: I36bd28ad6859f19a59de627f8b81acf5dc3fd27c Signed-off-by: Weixin Zhou --- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 88 ++++++++----------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index f156d5b0c86c..73521b1ed7cf 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -235,6 +235,34 @@ }; }; +&dsi_in_vopl { + status = "disabled"; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + supports-emmc; + disable-wp; + non-removable; + num-slots = <1>; + status = "okay"; +}; + +&gmac { + phy-supply = <&vcc_phy>; + clock_in_out = "output"; + snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 50000 50000>; + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + &i2c0 { rk809: pmic@20 { compatible = "rockchip,rk809"; @@ -499,6 +527,14 @@ reprobe_en = <1>; }; + ts@40 { + status = "okay"; + compatible = "GT1X"; + reg = <0x14>; + irq_gpio_number = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; + rst_gpio_number = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + }; + sensor@4c { status = "okay"; compatible = "gs_mma7660"; @@ -521,58 +557,6 @@ vccio5-supply = <&vcc_3v0>; }; -&dsi_in_vopl { - status = "disabled"; -}; - -&emmc { - bus-width = <8>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - supports-emmc; - disable-wp; - non-removable; - num-slots = <1>; - status = "okay"; -}; - -&gmac { - phy-supply = <&vcc_phy>; - clock_in_out = "output"; - snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -}; - -&gpu { - status = "okay"; -}; - -&i2c1 { - status = "okay"; - - ts@40 { - status = "okay"; - compatible = "GT1X"; - reg = <0x14>; - irq_gpio_number = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - rst_gpio_number = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; - }; - - sensor@4c { - status = "okay"; - compatible = "gs_mma7660"; - reg = <0x4c>; - type = ; - irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>; - irq_enable = <0>; - poll_delay_ms = <30>; - layout = <6>; - reprobe_en = <1>; - }; -}; - &mipi_dphy { status = "okay"; }; From 1d3cef672cdfc7d20a7e7b8101cbecd9b6f5f4b7 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 17 Jan 2018 14:52:53 +0800 Subject: [PATCH 212/427] MALI: bifrost: rk: not to use sg_dma_len in bifrost DDK r8p0-01rel0 When CONFIG_NEED_SG_DMA_LENGTH is enabled, sg_dma_len is defined as follow : "#define sg_dma_len(sg) ((sg)->dma_length)" But, dma_length is not used by the framework indeed. Change-Id: I93b4ceed28882236dc252fcabb7c7710153804a0 Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/mali_kbase_mem.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.c b/drivers/gpu/arm/bifrost/mali_kbase_mem.c index 34222cbddc78..a105b15d641c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.c @@ -2491,6 +2491,9 @@ static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, alloc->nents = 0; } +/* to replace sg_dma_len. */ +#define MALI_SG_DMA_LEN(sg) ((sg)->length) + #ifdef CONFIG_DMA_SHARED_BUFFER static int kbase_jd_umm_map(struct kbase_context *kctx, struct kbase_va_region *reg) @@ -2520,11 +2523,12 @@ static int kbase_jd_umm_map(struct kbase_context *kctx, KBASE_DEBUG_ASSERT(pa); for_each_sg(sgt->sgl, s, sgt->nents, i) { - size_t j, pages = PFN_UP(sg_dma_len(s)); + int j; + size_t pages = PFN_UP(MALI_SG_DMA_LEN(s)); - WARN_ONCE(sg_dma_len(s) & (PAGE_SIZE-1), - "sg_dma_len(s)=%u is not a multiple of PAGE_SIZE\n", - sg_dma_len(s)); + WARN_ONCE(MALI_SG_DMA_LEN(s) & (PAGE_SIZE-1), + "MALI_SG_DMA_LEN(s)=%u is not a multiple of PAGE_SIZE\n", + MALI_SG_DMA_LEN(s)); WARN_ONCE(sg_dma_address(s) & (PAGE_SIZE-1), "sg_dma_address(s)=%llx is not aligned to PAGE_SIZE\n", From 6c17c7592ae12504374a40abf7434a92be8e427f Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Thu, 25 Jan 2018 11:03:24 +0800 Subject: [PATCH 213/427] ARM64: dts: rockchip: rk3328-android: Enable tve uboot logo Change-Id: If2855f3fc8215c7b4ab9edc2d97dbac5b1c086ef Signed-off-by: Algea Cao --- arch/arm64/boot/dts/rockchip/rk3328-android.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-android.dtsi index 53691b4902db..44dd4b0ba7fc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328-android.dtsi @@ -82,6 +82,14 @@ charge_logo,mode = "fullscreen"; connect = <&vop_out_hdmi>; }; + route_tve: route-tve { + status = "okay"; + logo,uboot = "logo.bmp"; + logo,kernel = "logo_kernel.bmp"; + logo,mode = "fullscreen"; + charge_logo,mode = "fullscreen"; + connect = <&vop_out_tve>; + }; }; }; From 07210d909f9d6489899141309b4543368816a9c9 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 17 Jan 2018 17:12:02 +0800 Subject: [PATCH 214/427] MALI: bifrost: rk: ipa/: to fit current 'struct devfreq_cooling_power' Need CONFIG_MALI_PWRSOFT_765 enabled Change-Id: I96476f6b884bf48e46643685aa6d77dadcd80edb Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c index e7e22991f2a7..d6332b55e970 100644 --- a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.c @@ -576,8 +576,5 @@ struct devfreq_cooling_power kbase_ipa_power_model_ops = { #endif .get_static_power = &kbase_get_static_power, .get_dynamic_power = &kbase_get_dynamic_power, -#ifdef CONFIG_MALI_PWRSOFT_765 - .get_real_power = &kbase_get_real_power, -#endif }; KBASE_EXPORT_TEST_API(kbase_ipa_power_model_ops); From 24b77886e393f0f4765e48d273c7d570ab3269fd Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 17 Jan 2018 14:50:00 +0800 Subject: [PATCH 215/427] bifrost: make it possible to build midgard and bifrost as module in one make including : modifications for changing patch from drivers/gpu/arm/midgard to drivers/gpu/arm/bifrost; rename output mali_kbase.ko to bifrost_kbase.ko; rename configs, which have duplicated names in midgard, in Kconfig, Kbuild and source files. Change-Id: I127d8c8043db9010398946b3f4a90640ab1f13fe Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/Kbuild | 20 ++--- drivers/gpu/arm/bifrost/Kconfig | 72 +++++++-------- drivers/gpu/arm/bifrost/backend/gpu/Kbuild | 4 +- .../backend/gpu/mali_kbase_device_hw.c | 4 +- .../arm/bifrost/backend/gpu/mali_kbase_gpu.c | 16 ++-- .../backend/gpu/mali_kbase_instr_backend.c | 2 +- .../backend/gpu/mali_kbase_irq_linux.c | 20 ++--- .../bifrost/backend/gpu/mali_kbase_jm_hw.c | 10 +-- .../backend/gpu/mali_kbase_js_backend.c | 4 +- .../backend/gpu/mali_kbase_pm_backend.c | 6 +- .../bifrost/backend/gpu/mali_kbase_pm_ca.c | 2 +- .../bifrost/backend/gpu/mali_kbase_pm_defs.h | 6 +- .../backend/gpu/mali_kbase_pm_driver.c | 8 +- .../backend/gpu/mali_kbase_pm_internal.h | 6 +- .../backend/gpu/mali_kbase_pm_metrics.c | 22 ++--- .../backend/gpu/mali_kbase_pm_policy.c | 12 +-- .../arm/bifrost/backend/gpu/mali_kbase_time.c | 4 +- .../arm/bifrost/backend/gpu/mali_kbase_time.h | 2 +- drivers/gpu/arm/bifrost/ipa/Kbuild | 6 +- drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h | 6 +- .../arm/bifrost/ipa/mali_kbase_ipa_simple.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase.h | 22 ++--- .../arm/bifrost/mali_kbase_as_fault_debugfs.c | 8 +- .../arm/bifrost/mali_kbase_as_fault_debugfs.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_context.c | 4 +- .../gpu/arm/bifrost/mali_kbase_core_linux.c | 90 +++++++++---------- drivers/gpu/arm/bifrost/mali_kbase_debug.h | 10 +-- drivers/gpu/arm/bifrost/mali_kbase_defs.h | 42 ++++----- drivers/gpu/arm/bifrost/mali_kbase_device.c | 8 +- .../gpu/arm/bifrost/mali_kbase_dma_fence.c | 2 +- .../gpu/arm/bifrost/mali_kbase_dma_fence.h | 6 +- drivers/gpu/arm/bifrost/mali_kbase_fence.h | 6 +- .../gpu/arm/bifrost/mali_kbase_fence_defs.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_gator.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c | 4 +- .../arm/bifrost/mali_kbase_hwaccess_time.h | 2 +- drivers/gpu/arm/bifrost/mali_kbase_jd.c | 56 ++++++------ .../gpu/arm/bifrost/mali_kbase_jd_debugfs.c | 4 +- drivers/gpu/arm/bifrost/mali_kbase_js.c | 12 +-- drivers/gpu/arm/bifrost/mali_kbase_js_defs.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_mem.h | 6 +- drivers/gpu/arm/bifrost/mali_kbase_mmu.c | 16 ++-- .../bifrost/mali_kbase_regs_history_debugfs.c | 2 +- .../bifrost/mali_kbase_regs_history_debugfs.h | 2 +- drivers/gpu/arm/bifrost/mali_kbase_replay.c | 12 +-- drivers/gpu/arm/bifrost/mali_kbase_softjobs.c | 14 +-- drivers/gpu/arm/bifrost/mali_kbase_sync.h | 2 +- .../gpu/arm/bifrost/mali_kbase_sync_android.c | 6 +- .../gpu/arm/bifrost/mali_kbase_sync_file.c | 2 +- .../arm/bifrost/mali_kbase_trace_timeline.c | 4 +- .../arm/bifrost/mali_kbase_trace_timeline.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_uku.h | 10 +-- drivers/gpu/arm/bifrost/mali_kbase_vinstr.c | 12 +-- drivers/gpu/arm/bifrost/platform/rk/Kbuild | 12 +-- .../bifrost/tests/mali_kutf_irq_test/Kconfig | 2 +- .../bifrost/tests/mali_kutf_irq_test/Makefile | 4 +- .../tests/mali_kutf_irq_test/sconscript | 2 +- 57 files changed, 315 insertions(+), 325 deletions(-) diff --git a/drivers/gpu/arm/bifrost/Kbuild b/drivers/gpu/arm/bifrost/Kbuild index 49d016ef2582..531b92126b98 100644 --- a/drivers/gpu/arm/bifrost/Kbuild +++ b/drivers/gpu/arm/bifrost/Kbuild @@ -12,8 +12,6 @@ # # - - # Driver version string which is returned to userspace via an ioctl MALI_RELEASE_NAME ?= "r8p0-01rel0" @@ -22,7 +20,7 @@ KBASE_PATH = $(src) KBASE_PLATFORM_PATH = $(KBASE_PATH)/platform_dummy UMP_PATH = $(src)/../../../base -ifeq ($(CONFIG_MALI_ERROR_INJECT),y) +ifeq ($(CONFIG_MALI_BIFROST_ERROR_INJECT),y) MALI_ERROR_INJECT_ON = 1 endif @@ -130,10 +128,10 @@ endif ccflags-y += -I$(KBASE_PATH) # Tell the Linux build system from which .o file to create the kernel module -obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o +obj-$(CONFIG_MALI_BIFROST) += bifrost_kbase.o # Tell the Linux build system to enable building of our .c files -mali_kbase-y := $(SRC:.c=.o) +bifrost_kbase-y := $(SRC:.c=.o) # Kconfig passes in the name with quotes for in-tree builds - remove them. platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_NAME)) @@ -141,30 +139,30 @@ MALI_PLATFORM_DIR := platform/$(platform_name) ccflags-y += -I$(src)/$(MALI_PLATFORM_DIR) include $(src)/$(MALI_PLATFORM_DIR)/Kbuild -ifeq ($(CONFIG_MALI_DEVFREQ),y) +ifeq ($(CONFIG_MALI_BIFROST_DEVFREQ),y) ifeq ($(CONFIG_DEVFREQ_THERMAL),y) include $(src)/ipa/Kbuild endif endif -mali_kbase-$(CONFIG_MALI_DMA_FENCE) += \ +bifrost_kbase-$(CONFIG_MALI_BIFROST_DMA_FENCE) += \ mali_kbase_dma_fence.o \ mali_kbase_fence.o -mali_kbase-$(CONFIG_SYNC) += \ +bifrost_kbase-$(CONFIG_SYNC) += \ mali_kbase_sync_android.o \ mali_kbase_sync_common.o -mali_kbase-$(CONFIG_SYNC_FILE) += \ +bifrost_kbase-$(CONFIG_SYNC_FILE) += \ mali_kbase_sync_file.o \ mali_kbase_sync_common.o \ mali_kbase_fence.o ifeq ($(MALI_MOCK_TEST),1) # Test functionality -mali_kbase-y += tests/internal/src/mock/mali_kbase_pm_driver_mock.o +bifrost_kbase-y += tests/internal/src/mock/mali_kbase_pm_driver_mock.o endif include $(src)/backend/gpu/Kbuild -mali_kbase-y += $(BACKEND:.c=.o) +bifrost_kbase-y += $(BACKEND:.c=.o) ccflags-y += -I$(src)/backend/gpu diff --git a/drivers/gpu/arm/bifrost/Kconfig b/drivers/gpu/arm/bifrost/Kconfig index dc78f84b1eb5..7c70914e3900 100644 --- a/drivers/gpu/arm/bifrost/Kconfig +++ b/drivers/gpu/arm/bifrost/Kconfig @@ -14,19 +14,19 @@ -menuconfig MALI_MIDGARD - tristate "Mali Midgard series support" +menuconfig MALI_BIFROST + tristate "Mali Bifrost series support" select GPU_TRACEPOINTS if ANDROID default n help - Enable this option to build support for a ARM Mali Midgard GPU. + Enable this option to build support for a ARM Mali Bifrost GPU. To compile this driver as a module, choose M here: this will generate a single module, called mali_kbase. -config MALI_GATOR_SUPPORT +config MALI_BIFROST_GATOR_SUPPORT bool "Streamline support via Gator" - depends on MALI_MIDGARD + depends on MALI_BIFROST default n help Adds diagnostic support for use with the ARM Streamline Performance Analyzer. @@ -34,24 +34,24 @@ config MALI_GATOR_SUPPORT Streamline debug support. This is a legacy interface required by older versions of Streamline. -config MALI_MIDGARD_DVFS +config MALI_BIFROST_DVFS bool "Enable legacy DVFS" - depends on MALI_MIDGARD && !MALI_DEVFREQ + depends on MALI_BIFROST && !MALI_BIFROST_DEVFREQ default n help Choose this option to enable legacy DVFS in the Mali Midgard DDK. -config MALI_MIDGARD_ENABLE_TRACE +config MALI_BIFROST_ENABLE_TRACE bool "Enable kbase tracing" - depends on MALI_MIDGARD + depends on MALI_BIFROST default n help Enables tracing in kbase. Trace log available through the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled -config MALI_DEVFREQ +config MALI_BIFROST_DEVFREQ bool "devfreq support for Mali" - depends on MALI_MIDGARD && PM_DEVFREQ + depends on MALI_BIFROST && PM_DEVFREQ help Support devfreq for Mali. @@ -59,9 +59,9 @@ config MALI_DEVFREQ governor, the frequency of Mali will be dynamically selected from the available OPPs. -config MALI_DMA_FENCE +config MALI_BIFROST_DMA_FENCE bool "DMA_BUF fence support for Mali" - depends on MALI_MIDGARD && !KDS + depends on MALI_BIFROST && !KDS default n help Support DMA_BUF fences for Mali. @@ -70,7 +70,7 @@ config MALI_DMA_FENCE the Linux Kernel has built in support for DMA_BUF fences. config MALI_PLATFORM_NAME - depends on MALI_MIDGARD + depends on MALI_BIFROST string "Platform name" default "devicetree" help @@ -78,10 +78,10 @@ config MALI_PLATFORM_NAME include in the build. 'platform/$(MALI_PLATFORM_NAME)/Kbuild' must exist. -# MALI_EXPERT configuration options +# MALI_BIFROST_EXPERT configuration options -menuconfig MALI_EXPERT - depends on MALI_MIDGARD +menuconfig MALI_BIFROST_EXPERT + depends on MALI_BIFROST bool "Enable Expert Settings" default n help @@ -90,7 +90,7 @@ menuconfig MALI_EXPERT config MALI_CORESTACK bool "Support controlling power to the GPU core stack" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Enabling this feature on supported GPUs will let the driver powering @@ -101,9 +101,9 @@ config MALI_CORESTACK If unsure, say N. -config MALI_PRFCNT_SET_SECONDARY +config MALI_BIFROST_PRFCNT_SET_SECONDARY bool "Use secondary set of performance counters" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Select this option to use secondary set of performance counters. Kernel @@ -114,17 +114,17 @@ config MALI_PRFCNT_SET_SECONDARY If unsure, say N. -config MALI_DEBUG +config MALI_BIFROST_DEBUG bool "Debug build" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Select this option for increased checking and reporting of errors. -config MALI_FENCE_DEBUG +config MALI_BIFROST_FENCE_DEBUG bool "Debug sync fence usage" - depends on MALI_MIDGARD && MALI_EXPERT && (SYNC || SYNC_FILE) - default y if MALI_DEBUG + depends on MALI_BIFROST && MALI_BIFROST_EXPERT && (SYNC || SYNC_FILE) + default y if MALI_BIFROST_DEBUG help Select this option to enable additional checking and reporting on the use of sync fences in the Mali driver. @@ -138,9 +138,9 @@ config MALI_FENCE_DEBUG The timeout can be changed at runtime through the js_soft_timeout device attribute, where the timeout is specified in milliseconds. -config MALI_NO_MALI +config MALI_BIFROST_NO_MALI bool "No Mali" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help This can be used to test the driver in a simulated environment @@ -150,23 +150,23 @@ config MALI_NO_MALI All calls to the simulated hardware will complete immediately as if the hardware completed the task. -config MALI_ERROR_INJECT +config MALI_BIFROST_ERROR_INJECT bool "Error injection" - depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI + depends on MALI_BIFROST && MALI_BIFROST_EXPERT && MALI_BIFROST_NO_MALI default n help Enables insertion of errors to test module failure and recovery mechanisms. -config MALI_TRACE_TIMELINE +config MALI_BIFROST_TRACE_TIMELINE bool "Timeline tracing" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Enables timeline tracing through the kernel tracepoint system. -config MALI_SYSTEM_TRACE +config MALI_BIFROST_SYSTEM_TRACE bool "Enable system event tracing support" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Choose this option to enable system trace events for each @@ -176,7 +176,7 @@ config MALI_SYSTEM_TRACE config MALI_2MB_ALLOC bool "Attempt to allocate 2MB pages" - depends on MALI_MIDGARD && MALI_EXPERT + depends on MALI_BIFROST && MALI_BIFROST_EXPERT default n help Rather than allocating all GPU memory page-by-page, attempt to @@ -193,5 +193,5 @@ config MALI_PWRSOFT_765 not merged in mainline kernel yet. So this define helps to guard those parts of the code. -source "drivers/gpu/arm/midgard/platform/Kconfig" -source "drivers/gpu/arm/midgard/tests/Kconfig" +source "drivers/gpu/arm/bifrost/platform/Kconfig" +# source "drivers/gpu/arm/bifrost/tests/Kconfig" diff --git a/drivers/gpu/arm/bifrost/backend/gpu/Kbuild b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild index 5f700e9b6b44..5eeba1b14710 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/Kbuild +++ b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild @@ -45,13 +45,13 @@ BACKEND += \ backend/gpu/mali_kbase_pm_fast_start.c endif -ifeq ($(CONFIG_MALI_DEVFREQ),y) +ifeq ($(CONFIG_MALI_BIFROST_DEVFREQ),y) BACKEND += \ backend/gpu/mali_kbase_devfreq.c \ backend/gpu/mali_kbase_pm_ca_devfreq.c endif -ifeq ($(CONFIG_MALI_NO_MALI),y) +ifeq ($(CONFIG_MALI_BIFROST_NO_MALI),y) # Dummy model BACKEND += backend/gpu/mali_kbase_model_dummy.c BACKEND += backend/gpu/mali_kbase_model_linux.c diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c index dcdf15cdc3e8..17f253308ffc 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_device_hw.c @@ -25,7 +25,7 @@ #include -#if !defined(CONFIG_MALI_NO_MALI) +#if !defined(CONFIG_MALI_BIFROST_NO_MALI) #ifdef CONFIG_DEBUG_FS @@ -195,7 +195,7 @@ u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, } KBASE_EXPORT_TEST_API(kbase_reg_read); -#endif /* !defined(CONFIG_MALI_NO_MALI) */ +#endif /* !defined(CONFIG_MALI_BIFROST_NO_MALI) */ /** * kbase_report_gpu_fault - Report a GPU fault. diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c index 3b78100ec6df..a7c3a77d8ac8 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpu.c @@ -80,15 +80,15 @@ int kbase_backend_late_init(struct kbase_device *kbdev) if (err) goto fail_timer; -#ifdef CONFIG_MALI_DEBUG -#ifndef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_DEBUG +#ifndef CONFIG_MALI_BIFROST_NO_MALI if (kbasep_common_test_interrupt_handlers(kbdev) != 0) { dev_err(kbdev->dev, "Interrupt assigment check failed.\n"); err = -EINVAL; goto fail_interrupt_test; } -#endif /* !CONFIG_MALI_NO_MALI */ -#endif /* CONFIG_MALI_DEBUG */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ err = kbase_job_slot_init(kbdev); if (err) @@ -100,11 +100,11 @@ int kbase_backend_late_init(struct kbase_device *kbdev) fail_job_slot: -#ifdef CONFIG_MALI_DEBUG -#ifndef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_DEBUG +#ifndef CONFIG_MALI_BIFROST_NO_MALI fail_interrupt_test: -#endif /* !CONFIG_MALI_NO_MALI */ -#endif /* CONFIG_MALI_DEBUG */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ kbase_backend_timer_term(kbdev); fail_timer: diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c index 7ad309e8d7f4..8084d054cc5b 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_backend.c @@ -129,7 +129,7 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, /* Configure */ prfcnt_config = kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT; -#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY +#ifdef CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY { u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; u32 product_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c index 8416b80e8b77..d0666c86cf59 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c @@ -21,7 +21,7 @@ #include -#if !defined(CONFIG_MALI_NO_MALI) +#if !defined(CONFIG_MALI_BIFROST_NO_MALI) /* GPU IRQ Tags */ #define JOB_IRQ_TAG 0 @@ -55,11 +55,11 @@ static irqreturn_t kbase_job_irq_handler(int irq, void *data) val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG if (!kbdev->pm.backend.driver_ready_for_irqs) dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", __func__, irq, val); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); if (!val) @@ -93,11 +93,11 @@ static irqreturn_t kbase_mmu_irq_handler(int irq, void *data) val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG if (!kbdev->pm.backend.driver_ready_for_irqs) dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", __func__, irq, val); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); if (!val) { @@ -131,11 +131,11 @@ static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS), NULL); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG if (!kbdev->pm.backend.driver_ready_for_irqs) dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", __func__, irq, val); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, flags); if (!val) @@ -156,7 +156,7 @@ static irq_handler_t kbase_handler_table[] = { [GPU_IRQ_TAG] = kbase_gpu_irq_handler, }; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define JOB_IRQ_HANDLER JOB_IRQ_TAG #define MMU_IRQ_HANDLER MMU_IRQ_TAG #define GPU_IRQ_HANDLER GPU_IRQ_TAG @@ -412,7 +412,7 @@ int kbasep_common_test_interrupt_handlers( return err; } -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ int kbase_install_interrupts(struct kbase_device *kbdev) { @@ -466,4 +466,4 @@ void kbase_synchronize_irqs(struct kbase_device *kbdev) } } -#endif /* !defined(CONFIG_MALI_NO_MALI) */ +#endif /* !defined(CONFIG_MALI_BIFROST_NO_MALI) */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c index be88ec8eb0d7..cbca5eac82f1 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c @@ -22,7 +22,7 @@ #include #include #include -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) #include #endif #include @@ -140,7 +140,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev, KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, (u32) katom->affinity); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_job_slots_event( GATOR_MAKE_EVENT(GATOR_JOB_SLOT_START, js), kctx, kbase_jd_atom_id(kctx, katom)); @@ -273,7 +273,7 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done) switch (completion_code) { case BASE_JD_EVENT_STOPPED: -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_job_slots_event( GATOR_MAKE_EVENT( GATOR_JOB_SLOT_SOFT_STOPPED, i), @@ -507,11 +507,11 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, target_katom); if (!soft_stop_allowed) { -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(kbdev->dev, "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%X", (unsigned int)core_reqs); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ return; } diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c index a8c1af23a369..d392fa2a85d9 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c @@ -52,12 +52,12 @@ static inline bool timer_callback_should_run(struct kbase_device *kbdev) * nr_contexts_pullable is up-to-date for reading */ nr_running_ctxs = atomic_read(&kbdev->js_data.nr_contexts_runnable); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG if (kbdev->js_data.softstop_always) { /* Debug support for allowing soft-stop on a single context */ return true; } -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9435)) { /* Timeouts would have to be 4x longer (due to micro- diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c index c88b80a325dd..cd8932650ed5 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c @@ -75,9 +75,9 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) kbdev->pm.backend.gpu_powered = false; kbdev->pm.suspending = false; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG kbdev->pm.backend.driver_ready_for_irqs = false; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ kbdev->pm.backend.gpu_in_desired_state = true; init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait); @@ -348,7 +348,7 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, /* We are ready to receive IRQ's now as power policy is set up, so * enable them now. */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock, irq_flags); kbdev->pm.backend.driver_ready_for_irqs = true; spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock, irq_flags); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c index 85890f1e85f5..c17db8be8877 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c @@ -25,7 +25,7 @@ static const struct kbase_pm_ca_policy *const policy_list[] = { &kbase_pm_ca_fixed_policy_ops, -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ &kbase_pm_ca_devfreq_policy_ops, #endif #if !MALI_CUSTOMER_RELEASE diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h index 352744ee6d73..564fbda1116a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h @@ -111,7 +111,7 @@ struct kbasep_pm_metrics_data { u32 active_gl_ctx[2]; /* GL jobs can only run on 2 of the 3 job slots */ spinlock_t lock; -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS struct hrtimer timer; bool timer_active; #endif @@ -279,9 +279,9 @@ struct kbase_pm_backend_data { bool cg1_disabled; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG bool driver_ready_for_irqs; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ spinlock_t gpu_powered_lock; diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c index cbc258cb361b..707f71a79a77 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c @@ -24,7 +24,7 @@ #include #include #include -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) #include #endif #include @@ -173,7 +173,7 @@ static void kbase_pm_invoke(struct kbase_device *kbdev, reg = core_type_to_reg(core_type, action); KBASE_DEBUG_ASSERT(reg); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) if (cores) { if (action == ACTION_PWRON) kbase_trace_mali_pm_power_on(core_type, cores); @@ -783,7 +783,7 @@ MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev) if (in_desired_state) { KBASE_DEBUG_ASSERT(cores_are_available); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_pm_status(KBASE_PM_CORE_L2, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2)); @@ -1197,7 +1197,7 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev) if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10327)) kbdev->hw_quirks_sc |= SC_SDC_DISABLE_OQ_DISCARD; -#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY +#ifdef CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY /* Enable alternative hardware counter selection if configured. */ if (!GPU_ID_IS_NEW_FORMAT(prod_id)) kbdev->hw_quirks_sc |= SC_ALT_COUNTERS; diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h index 6804f45ac27b..9fbe094541c5 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h @@ -486,13 +486,13 @@ void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume); */ void kbase_pm_do_poweroff(struct kbase_device *kbdev, bool is_suspend); -#if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) || defined(CONFIG_MALI_BIFROST_DVFS) void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, unsigned long *total, unsigned long *busy); void kbase_pm_reset_dvfs_utilisation(struct kbase_device *kbdev); -#endif /* defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) */ +#endif /* defined(CONFIG_MALI_BIFROST_DEVFREQ) || defined(CONFIG_MALI_BIFROST_DVFS) */ -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS /** * kbase_platform_dvfs_event - Report utilisation to DVFS code diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c index 024248ca7123..ba13bcd8b291 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c @@ -42,7 +42,7 @@ * counters. */ #define MALI_UTILIZATION_MAX_PERIOD 100000 /* ns = 100ms */ -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) { unsigned long flags; @@ -64,7 +64,7 @@ static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) return HRTIMER_NORESTART; } -#endif /* CONFIG_MALI_MIDGARD_DVFS */ +#endif /* CONFIG_MALI_BIFROST_DVFS */ int kbasep_pm_metrics_init(struct kbase_device *kbdev) { @@ -88,7 +88,7 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev) spin_lock_init(&kbdev->pm.backend.metrics.lock); -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS kbdev->pm.backend.metrics.timer_active = true; hrtimer_init(&kbdev->pm.backend.metrics.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); @@ -97,7 +97,7 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev) hrtimer_start(&kbdev->pm.backend.metrics.timer, HR_TIMER_DELAY_MSEC(kbdev->pm.dvfs_period), HRTIMER_MODE_REL); -#endif /* CONFIG_MALI_MIDGARD_DVFS */ +#endif /* CONFIG_MALI_BIFROST_DVFS */ return 0; } @@ -106,7 +106,7 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init); void kbasep_pm_metrics_term(struct kbase_device *kbdev) { -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS unsigned long flags; KBASE_DEBUG_ASSERT(kbdev != NULL); @@ -116,7 +116,7 @@ void kbasep_pm_metrics_term(struct kbase_device *kbdev) spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); hrtimer_cancel(&kbdev->pm.backend.metrics.timer); -#endif /* CONFIG_MALI_MIDGARD_DVFS */ +#endif /* CONFIG_MALI_BIFROST_DVFS */ } KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term); @@ -155,7 +155,7 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev, kbdev->pm.backend.metrics.time_period_start = now; } -#if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) || defined(CONFIG_MALI_BIFROST_DVFS) /* Caller needs to hold kbdev->pm.backend.metrics.lock before calling this * function. */ @@ -214,7 +214,7 @@ void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, } #endif -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS /* caller needs to hold kbdev->pm.backend.metrics.lock before calling this * function @@ -302,10 +302,10 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) } out: -#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifdef CONFIG_MALI_BIFROST_DVFS kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share); -#endif /*CONFIG_MALI_MIDGARD_DVFS */ +#endif /*CONFIG_MALI_BIFROST_DVFS */ kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, now); @@ -327,7 +327,7 @@ bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active); -#endif /* CONFIG_MALI_MIDGARD_DVFS */ +#endif /* CONFIG_MALI_BIFROST_DVFS */ /** * kbase_pm_metrics_active_calc - Update PM active counts based on currently diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c index 075f020c66e6..b98c68d9a42a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c @@ -26,7 +26,7 @@ #include static const struct kbase_pm_policy *const policy_list[] = { -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI &kbase_pm_always_on_policy_ops, &kbase_pm_demand_policy_ops, &kbase_pm_coarse_demand_policy_ops, @@ -34,7 +34,7 @@ static const struct kbase_pm_policy *const policy_list[] = { &kbase_pm_demand_always_powered_policy_ops, &kbase_pm_fast_start_policy_ops, #endif -#else /* CONFIG_MALI_NO_MALI */ +#else /* CONFIG_MALI_BIFROST_NO_MALI */ #if !PLATFORM_POWER_DOWN_ONLY &kbase_pm_demand_policy_ops, #endif /* !PLATFORM_POWER_DOWN_ONLY */ @@ -46,7 +46,7 @@ static const struct kbase_pm_policy *const policy_list[] = { &kbase_pm_fast_start_policy_ops, #endif /* !PLATFORM_POWER_DOWN_ONLY */ #endif -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ }; /* The number of policies available in the system. @@ -85,7 +85,7 @@ enum { typedef u32 kbase_pm_change_state; -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE /* Timeline Trace code lookups for each function */ static u32 kbase_pm_change_state_trace_code[KBASE_PM_FUNC_ID_COUNT] [KBASE_PM_CHANGE_STATE_COUNT] = { @@ -142,13 +142,13 @@ static inline void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code); } -#else /* CONFIG_MALI_TRACE_TIMELINE */ +#else /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ static inline void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, enum kbase_pm_func_id func_id, kbase_pm_change_state state) { } -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ /** * kbasep_pm_do_poweroff_cores - Process a poweroff request and power down any diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c index d992989123e8..0068e1091f4c 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c @@ -69,7 +69,7 @@ void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, * Note : If GPU resets occur then the counters are reset to zero, the delay may * not be as expected. */ -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI void kbase_wait_write_flush(struct kbase_context *kctx) { u32 base_count = 0; @@ -100,4 +100,4 @@ void kbase_wait_write_flush(struct kbase_context *kctx) kbase_pm_release_gpu_cycle_counter(kctx->kbdev); kbase_pm_context_idle(kctx->kbdev); } -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h index 35088abc8fe5..0559b2f7097d 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.h @@ -41,7 +41,7 @@ void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, * * This function is only in use for BASE_HW_ISSUE_6367 */ -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI static inline void kbase_wait_write_flush(struct kbase_context *kctx) { } diff --git a/drivers/gpu/arm/bifrost/ipa/Kbuild b/drivers/gpu/arm/bifrost/ipa/Kbuild index 8e37f406433e..831fa83c6a8e 100644 --- a/drivers/gpu/arm/bifrost/ipa/Kbuild +++ b/drivers/gpu/arm/bifrost/ipa/Kbuild @@ -13,14 +13,14 @@ # -mali_kbase-y += \ +bifrost_kbase-y += \ ipa/mali_kbase_ipa_simple.o \ ipa/mali_kbase_ipa.o -mali_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o +bifrost_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o ifneq ($(wildcard $(src)/ipa/mali_kbase_ipa_vinstr_g71.c),) - mali_kbase-y += \ + bifrost_kbase-y += \ ipa/mali_kbase_ipa_vinstr_g71.o \ ipa/mali_kbase_ipa_vinstr_common.o diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h index 469f33cbdcc6..67478fe911ea 100644 --- a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h @@ -18,7 +18,7 @@ #ifndef _KBASE_IPA_H_ #define _KBASE_IPA_H_ -#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) struct devfreq; @@ -152,7 +152,7 @@ extern struct devfreq_cooling_ops kbase_ipa_power_model_ops; extern struct devfreq_cooling_power kbase_ipa_power_model_ops; #endif -#else /* !(defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ +#else /* !(defined(CONFIG_MALI_BIFROST_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ static inline void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev) { } @@ -160,6 +160,6 @@ static inline void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbde static inline void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev) { } -#endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ +#endif /* (defined(CONFIG_MALI_BIFROST_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ #endif diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h index e78d6173300b..23cd55f5867d 100644 --- a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.h @@ -18,7 +18,7 @@ #ifndef _KBASE_IPA_SIMPLE_H_ #define _KBASE_IPA_SIMPLE_H_ -#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) extern struct kbase_ipa_model_ops kbase_simple_ipa_model_ops; @@ -35,6 +35,6 @@ extern struct kbase_ipa_model_ops kbase_simple_ipa_model_ops; void kbase_simple_power_model_set_dummy_temp(int temp); #endif /* MALI_UNIT_TEST */ -#endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ +#endif /* (defined(CONFIG_MALI_BIFROST_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ #endif /* _KBASE_IPA_SIMPLE_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase.h b/drivers/gpu/arm/bifrost/mali_kbase.h index 56b364e505d1..369a2d4706fe 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase.h +++ b/drivers/gpu/arm/bifrost/mali_kbase.h @@ -374,11 +374,11 @@ void kbase_disjoint_state_down(struct kbase_device *kbdev); #if KBASE_TRACE_ENABLE void kbasep_trace_debugfs_init(struct kbase_device *kbdev); -#ifndef CONFIG_MALI_SYSTEM_TRACE +#ifndef CONFIG_MALI_BIFROST_SYSTEM_TRACE /** Add trace values about a job-slot * * @note Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * Release builds (CONFIG_MALI_BIFROST_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any * functions called to get the parameters supplied to this macro must: * - be static or static inline * - must just return 0 and have no other statements present in the body. @@ -390,7 +390,7 @@ void kbasep_trace_debugfs_init(struct kbase_device *kbdev); /** Add trace values about a job-slot, with info * * @note Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * Release builds (CONFIG_MALI_BIFROST_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any * functions called to get the parameters supplied to this macro must: * - be static or static inline * - must just return 0 and have no other statements present in the body. @@ -402,7 +402,7 @@ void kbasep_trace_debugfs_init(struct kbase_device *kbdev); /** Add trace values about a ctx refcount * * @note Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * Release builds (CONFIG_MALI_BIFROST_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any * functions called to get the parameters supplied to this macro must: * - be static or static inline * - must just return 0 and have no other statements present in the body. @@ -413,7 +413,7 @@ void kbasep_trace_debugfs_init(struct kbase_device *kbdev); /** Add trace values about a ctx refcount, and info * * @note Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * Release builds (CONFIG_MALI_BIFROST_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any * functions called to get the parameters supplied to this macro must: * - be static or static inline * - must just return 0 and have no other statements present in the body. @@ -425,7 +425,7 @@ void kbasep_trace_debugfs_init(struct kbase_device *kbdev); /** Add trace values (no slot or refcount) * * @note Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * Release builds (CONFIG_MALI_BIFROST_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any * functions called to get the parameters supplied to this macro must: * - be static or static inline * - must just return 0 and have no other statements present in the body. @@ -446,7 +446,7 @@ void kbasep_trace_debugfs_init(struct kbase_device *kbdev); void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val); /** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */ void kbasep_trace_clear(struct kbase_device *kbdev); -#else /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +#else /* #ifndef CONFIG_MALI_BIFROST_SYSTEM_TRACE */ /* Dispatch kbase trace events as system trace events */ #include #define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ @@ -475,7 +475,7 @@ void kbasep_trace_clear(struct kbase_device *kbdev); CSTD_NOP(0);\ } while (0) -#endif /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +#endif /* #ifndef CONFIG_MALI_BIFROST_SYSTEM_TRACE */ #else #define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ do {\ @@ -546,7 +546,7 @@ void kbasep_trace_clear(struct kbase_device *kbdev); /** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */ void kbasep_trace_dump(struct kbase_device *kbdev); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG /** * kbase_set_driver_inactive - Force driver to go inactive * @kbdev: Device pointer @@ -557,10 +557,10 @@ void kbasep_trace_dump(struct kbase_device *kbdev); * which require that no jobs are running while the test executes. */ void kbase_set_driver_inactive(struct kbase_device *kbdev, bool inactive); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ -#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_BIFROST_NO_MALI) /* kbase_io_history_init - initialize data struct for register access history * diff --git a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c index f910fe970feb..cc729d416858 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.c @@ -21,7 +21,7 @@ #include #ifdef CONFIG_DEBUG_FS -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG static int kbase_as_fault_read(struct seq_file *sfile, void *data) { @@ -64,7 +64,7 @@ static const struct file_operations as_fault_fops = { .release = single_release, }; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ #endif /* CONFIG_DEBUG_FS */ /* @@ -73,7 +73,7 @@ static const struct file_operations as_fault_fops = { void kbase_as_fault_debugfs_init(struct kbase_device *kbdev) { #ifdef CONFIG_DEBUG_FS -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG uint i; char as_name[64]; struct dentry *debugfs_directory; @@ -96,7 +96,7 @@ void kbase_as_fault_debugfs_init(struct kbase_device *kbdev) else dev_warn(kbdev->dev, "unable to create address_spaces debugfs directory"); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ #endif /* CONFIG_DEBUG_FS */ return; } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h index 3ed2248897fc..66387e1c3f6a 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_as_fault_debugfs.h @@ -35,10 +35,10 @@ static inline void kbase_as_fault_debugfs_new(struct kbase_device *kbdev, int as_no) { #ifdef CONFIG_DEBUG_FS -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG kbdev->debugfs_as_read_bitmap |= (1ULL << as_no); #endif /* CONFIG_DEBUG_FS */ -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ return; } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_context.c b/drivers/gpu/arm/bifrost/mali_kbase_context.c index ad20e6135ba5..17821fee6cba 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_context.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_context.c @@ -59,7 +59,7 @@ kbase_create_context(struct kbase_device *kbdev, bool is_compat) atomic_set(&kctx->refcount, 0); if (is_compat) kbase_ctx_flag_set(kctx, KCTX_COMPAT); -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE kctx->timeline.owner_tgid = task_tgid_nr(current); #endif atomic_set(&kctx->setup_complete, 0); @@ -160,7 +160,7 @@ kbase_create_context(struct kbase_device *kbdev, bool is_compat) #ifdef CONFIG_GPU_TRACEPOINTS atomic_set(&kctx->jctx.work_id, 0); #endif -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE atomic_set(&kctx->timeline.jd_atoms_in_flight, 0); #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 3da2b6c4e7dc..3b46c7761148 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -21,16 +21,16 @@ #include #include #include -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ #include #include #ifdef CONFIG_DEVFREQ_THERMAL #include #endif /* CONFIG_DEVFREQ_THERMAL */ -#endif /* CONFIG_MALI_DEVFREQ */ -#ifdef CONFIG_MALI_NO_MALI +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ +#ifdef CONFIG_MALI_BIFROST_NO_MALI #include "mali_kbase_model_linux.h" -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ #include "mali_kbase_mem_profile_debugfs_buf_size.h" #include "mali_kbase_debug_mem_view.h" #include "mali_kbase_mem.h" @@ -153,9 +153,9 @@ enum { inited_mem = (1u << 0), inited_js = (1u << 1), inited_pm_runtime_init = (1u << 2), -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ inited_devfreq = (1u << 3), -#endif /* CONFIG_MALI_DEVFREQ */ +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ inited_tlstream = (1u << 4), inited_backend_early = (1u << 5), inited_backend_late = (1u << 6), @@ -178,7 +178,7 @@ enum { }; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define INACTIVE_WAIT_MS (5000) void kbase_set_driver_inactive(struct kbase_device *kbdev, bool inactive) @@ -191,7 +191,7 @@ void kbase_set_driver_inactive(struct kbase_device *kbdev, bool inactive) msleep(INACTIVE_WAIT_MS); } KBASE_EXPORT_TEST_API(kbase_set_driver_inactive); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ /** * kbase_legacy_dispatch - UKK dispatch function @@ -217,10 +217,10 @@ static int kbase_legacy_dispatch(struct kbase_context *kctx, id = ukh->id; ukh->ret = MALI_ERROR_NONE; /* Be optimistic */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG wait_event(kbdev->driver_inactive_wait, kbdev->driver_inactive == false); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ if (UKP_FUNC_ID_CHECK_VERSION == id) { struct uku_version_check_args *version_check; @@ -674,7 +674,7 @@ copy_failed: case KBASE_FUNC_INJECT_ERROR: { -#ifdef CONFIG_MALI_ERROR_INJECT +#ifdef CONFIG_MALI_BIFROST_ERROR_INJECT unsigned long flags; struct kbase_error_params params = ((struct kbase_uk_error_params *)args)->params; @@ -686,13 +686,13 @@ copy_failed: ukh->ret = MALI_ERROR_NONE; spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); /*mutex unlock */ -#endif /* CONFIG_MALI_ERROR_INJECT */ +#endif /* CONFIG_MALI_BIFROST_ERROR_INJECT */ break; } case KBASE_FUNC_MODEL_CONTROL: { -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI unsigned long flags; struct kbase_model_control_params params = ((struct kbase_uk_model_control_params *)args)->params; @@ -705,7 +705,7 @@ copy_failed: ukh->ret = MALI_ERROR_NONE; spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); /*mutex unlock */ -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ break; } @@ -782,7 +782,7 @@ copy_failed: break; } -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI case KBASE_FUNC_SET_PRFCNT_VALUES: { @@ -793,7 +793,7 @@ copy_failed: break; } -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ #ifdef BASE_LEGACY_UK10_4_SUPPORT case KBASE_FUNC_TLSTREAM_ACQUIRE_V10_4: { @@ -2139,7 +2139,7 @@ static const struct file_operations kbase_fops = { .get_unmapped_area = kbase_get_unmapped_area, }; -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value) { writel(value, kbdev->reg + offset); @@ -2149,7 +2149,7 @@ u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset) { return readl(kbdev->reg + offset); } -#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ /** * show_policy - Show callback for the power_policy sysfs file. @@ -2974,7 +2974,7 @@ static DEVICE_ATTR(force_replay, S_IRUGO | S_IWUSR, show_force_replay, set_force_replay); #endif /* !MALI_CUSTOMER_RELEASE */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG static ssize_t set_js_softstop_always(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -3028,9 +3028,9 @@ static ssize_t show_js_softstop_always(struct device *dev, * (see CL t6xx_stress_1 unit-test as an example whereby this feature is used.) */ static DEVICE_ATTR(js_softstop_always, S_IRUGO | S_IWUSR, show_js_softstop_always, set_js_softstop_always); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG typedef void (kbasep_debug_command_func) (struct kbase_device *); enum kbasep_debug_command_code { @@ -3132,7 +3132,7 @@ static ssize_t issue_debug(struct device *dev, struct device_attribute *attr, co * Writing to it with one of those commands will issue said command. */ static DEVICE_ATTR(debug_command, S_IRUGO | S_IWUSR, show_debug, issue_debug); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ /** * kbase_show_gpuinfo - Show callback for the gpuinfo sysfs entry. @@ -3804,7 +3804,7 @@ static void kbasep_protected_mode_term(struct kbase_device *kbdev) kfree(kbdev->protected_dev); } -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI static int kbase_common_reg_map(struct kbase_device *kbdev) { return 0; @@ -3812,7 +3812,7 @@ static int kbase_common_reg_map(struct kbase_device *kbdev) static void kbase_common_reg_unmap(struct kbase_device * const kbdev) { } -#else /* CONFIG_MALI_NO_MALI */ +#else /* CONFIG_MALI_BIFROST_NO_MALI */ static int kbase_common_reg_map(struct kbase_device *kbdev) { int err = 0; @@ -3848,7 +3848,7 @@ static void kbase_common_reg_unmap(struct kbase_device * const kbdev) kbdev->reg_size = 0; } } -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ static int registers_map(struct kbase_device * const kbdev) { @@ -4137,16 +4137,16 @@ static int kbase_device_debugfs_init(struct kbase_device *kbdev) kbasep_trace_debugfs_init(kbdev); #endif /* KBASE_TRACE_ENABLE */ -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE kbasep_trace_timeline_debugfs_init(kbdev); -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ #ifdef CONFIG_DEVFREQ_THERMAL if (kbdev->inited_subsys & inited_devfreq) kbase_ipa_debugfs_init(kbdev); #endif /* CONFIG_DEVFREQ_THERMAL */ -#endif /* CONFIG_MALI_DEVFREQ */ +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ #ifdef CONFIG_DEBUG_FS debugfs_create_file("serialize_jobs", S_IRUGO | S_IWUSR, @@ -4247,7 +4247,7 @@ static void kbase_logging_started_cb(void *data) #endif static struct attribute *kbase_attrs[] = { -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG &dev_attr_debug_command.attr, &dev_attr_js_softstop_always.attr, #endif @@ -4329,7 +4329,7 @@ static int kbase_platform_device_remove(struct platform_device *pdev) kbdev->inited_subsys &= ~inited_vinstr; } -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ if (kbdev->inited_subsys & inited_devfreq) { kbase_devfreq_term(kbdev); kbdev->inited_subsys &= ~inited_devfreq; @@ -4404,12 +4404,12 @@ static int kbase_platform_device_remove(struct platform_device *pdev) kbdev->inited_subsys &= ~inited_registers_map; } -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI if (kbdev->inited_subsys & inited_gpu_device) { gpu_device_destroy(kbdev); kbdev->inited_subsys &= ~inited_gpu_device; } -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ if (kbdev->inited_subsys != 0) dev_err(kbdev->dev, "Missing sub system termination\n"); @@ -4451,7 +4451,7 @@ static int kbase_platform_device_probe(struct platform_device *pdev) kbdev->dev = &pdev->dev; dev_set_drvdata(kbdev->dev, kbdev); -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI err = gpu_device_create(kbdev); if (err) { dev_err(&pdev->dev, "Dummy model initialization failed\n"); @@ -4459,7 +4459,7 @@ static int kbase_platform_device_probe(struct platform_device *pdev) return err; } kbdev->inited_subsys |= inited_gpu_device; -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ err = assign_irqs(pdev); if (err) { @@ -4603,14 +4603,14 @@ static int kbase_platform_device_probe(struct platform_device *pdev) } kbdev->inited_subsys |= inited_vinstr; -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ /* Devfreq uses vinstr, so must be initialized after it. */ err = kbase_devfreq_init(kbdev); if (!err) kbdev->inited_subsys |= inited_devfreq; else dev_err(kbdev->dev, "Continuing without devfreq\n"); -#endif /* CONFIG_MALI_DEVFREQ */ +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ err = kbase_debug_job_fault_dev_init(kbdev); if (err) { @@ -4711,7 +4711,7 @@ static int kbase_device_suspend(struct device *dev) if (!kbdev) return -ENODEV; -#if defined(CONFIG_MALI_DEVFREQ) && \ +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) if (kbdev->inited_subsys & inited_devfreq) devfreq_suspend_device(kbdev->devfreq); @@ -4739,7 +4739,7 @@ static int kbase_device_resume(struct device *dev) kbase_pm_resume(kbdev); -#if defined(CONFIG_MALI_DEVFREQ) && \ +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) if (kbdev->inited_subsys & inited_devfreq) devfreq_resume_device(kbdev->devfreq); @@ -4766,7 +4766,7 @@ static int kbase_device_runtime_suspend(struct device *dev) if (!kbdev) return -ENODEV; -#if defined(CONFIG_MALI_DEVFREQ) && \ +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) if (kbdev->inited_subsys & inited_devfreq) devfreq_suspend_device(kbdev->devfreq); @@ -4804,7 +4804,7 @@ static int kbase_device_runtime_resume(struct device *dev) dev_dbg(dev, "runtime resume\n"); } -#if defined(CONFIG_MALI_DEVFREQ) && \ +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) if (kbdev->inited_subsys & inited_devfreq) devfreq_resume_device(kbdev->devfreq); @@ -4917,11 +4917,11 @@ MODULE_VERSION(MALI_RELEASE_NAME " (UK version " \ __stringify(BASE_UK_VERSION_MAJOR) "." \ __stringify(BASE_UK_VERSION_MINOR) ")"); -#if defined(CONFIG_MALI_GATOR_SUPPORT) || defined(CONFIG_MALI_SYSTEM_TRACE) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) || defined(CONFIG_MALI_BIFROST_SYSTEM_TRACE) #define CREATE_TRACE_POINTS #endif -#ifdef CONFIG_MALI_GATOR_SUPPORT +#ifdef CONFIG_MALI_BIFROST_GATOR_SUPPORT /* Create the trace points (otherwise we just get code to call a tracepoint) */ #include "mali_linux_trace.h" @@ -4973,7 +4973,7 @@ void kbase_trace_mali_total_alloc_pages_change(long long int event) { trace_mali_total_alloc_pages_change(event); } -#endif /* CONFIG_MALI_GATOR_SUPPORT */ -#ifdef CONFIG_MALI_SYSTEM_TRACE +#endif /* CONFIG_MALI_BIFROST_GATOR_SUPPORT */ +#ifdef CONFIG_MALI_BIFROST_SYSTEM_TRACE #include "mali_linux_kbase_trace.h" #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug.h b/drivers/gpu/arm/bifrost/mali_kbase_debug.h index d7873c5eabf9..31b754c5507b 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_debug.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug.h @@ -30,7 +30,7 @@ /** @brief Disable the asserts tests if set to 1. Default is to disable the asserts in release. */ #ifndef KBASE_DEBUG_DISABLE_ASSERTS -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define KBASE_DEBUG_DISABLE_ASSERTS 0 #else #define KBASE_DEBUG_DISABLE_ASSERTS 1 @@ -71,7 +71,7 @@ struct kbasep_debug_assert_cb { * @note function parameter cannot be concatenated with other strings */ /* Select the correct system output function*/ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)\ do { \ pr_err("Mali: %s function:%s ", trace, function);\ @@ -82,7 +82,7 @@ struct kbasep_debug_assert_cb { #define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP() #endif -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define KBASE_CALL_ASSERT_HOOK() kbasep_debug_assert_call_hook() #else #define KBASE_CALL_ASSERT_HOOK() CSTD_NOP() @@ -127,11 +127,11 @@ struct kbasep_debug_assert_cb { * * @param X Code to compile only in debug mode. */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define KBASE_DEBUG_CODE(X) X #else #define KBASE_DEBUG_CODE(X) CSTD_NOP() -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ /** @} */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index 1ab64255d1a2..d957c1461440 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -61,9 +61,9 @@ #include #endif /* CONFIG_DEBUG_FS */ -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ #include -#endif /* CONFIG_MALI_DEVFREQ */ +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ #include #include @@ -74,16 +74,16 @@ #endif /** Enable SW tracing when set */ -#ifdef CONFIG_MALI_MIDGARD_ENABLE_TRACE +#ifdef CONFIG_MALI_BIFROST_ENABLE_TRACE #define KBASE_TRACE_ENABLE 1 #endif #ifndef KBASE_TRACE_ENABLE -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG #define KBASE_TRACE_ENABLE 1 #else #define KBASE_TRACE_ENABLE 0 -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ #endif /* KBASE_TRACE_ENABLE */ /** Dump Job slot trace on error (only active if KBASE_TRACE_ENABLE != 0) */ @@ -450,7 +450,7 @@ struct kbase_jd_atom { struct sync_fence *fence; struct sync_fence_waiter sync_waiter; #endif /* CONFIG_SYNC */ -#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) struct { /* Use the functions/API defined in mali_kbase_fence.h to * when working with this sub struct */ @@ -516,7 +516,7 @@ struct kbase_jd_atom { */ atomic_t dep_count; } dma_fence; -#endif /* CONFIG_MALI_DMA_FENCE || CONFIG_SYNC_FILE*/ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || CONFIG_SYNC_FILE*/ /* Note: refer to kbasep_js_atom_retained_state, which will take a copy of some of the following members */ enum base_jd_event_code event_code; @@ -816,7 +816,7 @@ enum kbase_timeline_pm_event { KBASEP_TIMELINE_PM_EVENT_LAST = KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, }; -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE struct kbase_trace_kctx_timeline { atomic_t jd_atoms_in_flight; u32 owner_tgid; @@ -841,7 +841,7 @@ struct kbase_trace_kbdev_timeline { * Expected to be protected by hwaccess_lock */ bool l2_transitioning; }; -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ struct kbasep_kctx_list_element { @@ -997,7 +997,7 @@ struct kbase_device { #endif char devname[DEVNAME_SIZE]; -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI void *model; struct kmem_cache *irq_slab; struct workqueue_struct *irq_workq; @@ -1005,7 +1005,7 @@ struct kbase_device { atomic_t serving_gpu_irq; atomic_t serving_mmu_irq; spinlock_t reg_op_lock; -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ struct kbase_pm_device_data pm; struct kbasep_js_device_data js_data; @@ -1117,7 +1117,7 @@ struct kbase_device { struct list_head kctx_list; struct mutex kctx_list_lock; -#ifdef CONFIG_MALI_DEVFREQ +#ifdef CONFIG_MALI_BIFROST_DEVFREQ struct devfreq_dev_profile devfreq_profile; struct devfreq *devfreq; unsigned long current_freq; @@ -1141,10 +1141,10 @@ struct kbase_device { struct kbase_ipa_model *fallback_model; } ipa; #endif /* CONFIG_DEVFREQ_THERMAL */ -#endif /* CONFIG_MALI_DEVFREQ */ +#endif /* CONFIG_MALI_BIFROST_DEVFREQ */ -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE struct kbase_trace_kbdev_timeline timeline; #endif @@ -1160,10 +1160,10 @@ struct kbase_device { /* Root directory for per context entry */ struct dentry *debugfs_ctx_directory; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG /* bit for each as, set if there is new data to report */ u64 debugfs_as_read_bitmap; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ /* failed job dump, used for separate debug process */ wait_queue_head_t job_fault_wq; @@ -1263,10 +1263,10 @@ struct kbase_device { bool protected_mode_support; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG wait_queue_head_t driver_inactive_wait; bool driver_inactive; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ #ifdef CONFIG_MALI_FPGA_BUS_LOGGER /* @@ -1423,12 +1423,12 @@ struct kbase_context { #ifdef CONFIG_KDS struct list_head waiting_kds_resource; #endif -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE struct { struct list_head waiting_resource; struct workqueue_struct *wq; } dma_fence; -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ /** This is effectively part of the Run Pool, because it only has a valid * setting (!=KBASEP_AS_NR_INVALID) whilst the context is scheduled in * @@ -1460,7 +1460,7 @@ struct kbase_context { /* End of the SAME_VA zone */ u64 same_va_end; -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE struct kbase_trace_kctx_timeline timeline; #endif #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/arm/bifrost/mali_kbase_device.c b/drivers/gpu/arm/bifrost/mali_kbase_device.c index d635fccaea14..2d11f11f3be0 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_device.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_device.c @@ -221,13 +221,13 @@ int kbase_device_init(struct kbase_device * const kbdev) mutex_init(&kbdev->cacheclean_lock); -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) kbdev->timeline.slot_atoms_submitted[i] = 0; for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i) atomic_set(&kbdev->timeline.pm_event_uid[i], 0); -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ /* fbdump profiling controls set to 0 - fbdump not enabled until changed by gator */ for (i = 0; i < FBDUMP_CONTROL_MAX; i++) @@ -250,9 +250,9 @@ int kbase_device_init(struct kbase_device * const kbdev) else kbdev->mmu_mode = kbase_mmu_mode_get_lpae(); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG init_waitqueue_head(&kbdev->driver_inactive_wait); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ return 0; term_trace: diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c index 9197743c81d4..8a571266534b 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c @@ -16,7 +16,7 @@ -/* Include mali_kbase_dma_fence.h before checking for CONFIG_MALI_DMA_FENCE as +/* Include mali_kbase_dma_fence.h before checking for CONFIG_MALI_BIFROST_DMA_FENCE as * it will be set there. */ #include "mali_kbase_dma_fence.h" diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h index c9ab40350422..b02ea9774c4f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h @@ -18,7 +18,7 @@ #ifndef _KBASE_DMA_FENCE_H_ #define _KBASE_DMA_FENCE_H_ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE #include #include @@ -118,7 +118,7 @@ void kbase_dma_fence_term(struct kbase_context *kctx); int kbase_dma_fence_init(struct kbase_context *kctx); -#else /* CONFIG_MALI_DMA_FENCE */ +#else /* CONFIG_MALI_BIFROST_DMA_FENCE */ /* Dummy functions for when dma-buf fence isn't enabled. */ static inline int kbase_dma_fence_init(struct kbase_context *kctx) @@ -127,5 +127,5 @@ static inline int kbase_dma_fence_init(struct kbase_context *kctx) } static inline void kbase_dma_fence_term(struct kbase_context *kctx) {} -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_fence.h index f3ed025f7f6c..9f59d30a1e2e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.h @@ -20,11 +20,11 @@ /* * mali_kbase_fence.[hc] has common fence code used by both - * - CONFIG_MALI_DMA_FENCE - implicit DMA fences + * - CONFIG_MALI_BIFROST_DMA_FENCE - implicit DMA fences * - CONFIG_SYNC_FILE - explicit fences beginning with 4.9 kernel */ -#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) #include #include "mali_kbase_fence_defs.h" @@ -265,6 +265,6 @@ bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); #define kbase_fence_put(fence) dma_fence_put(fence) -#endif /* CONFIG_MALI_DMA_FENCE || defined(CONFIG_SYNC_FILE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || defined(CONFIG_SYNC_FILE */ #endif /* _KBASE_FENCE_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h index fa2c6dfe999e..d2d7c436918c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence_defs.h @@ -23,7 +23,7 @@ * This file hides the compatibility issues with this for the rest the driver */ -#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) #include @@ -46,6 +46,6 @@ #endif /* < 4.10.0 */ -#endif /* CONFIG_MALI_DMA_FENCE || CONFIG_SYNC_FILE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || CONFIG_SYNC_FILE */ #endif /* _KBASE_FENCE_DEFS_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gator.h b/drivers/gpu/arm/bifrost/mali_kbase_gator.h index ce65b5562a2b..87697b15d986 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_gator.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_gator.h @@ -25,7 +25,7 @@ #ifndef _KBASE_GATOR_H_ #define _KBASE_GATOR_H_ -#ifdef CONFIG_MALI_GATOR_SUPPORT +#ifdef CONFIG_MALI_BIFROST_GATOR_SUPPORT #define GATOR_MAKE_EVENT(type, number) (((type) << 24) | ((number) << 16)) #define GATOR_JOB_SLOT_START 1 #define GATOR_JOB_SLOT_STOP 2 @@ -40,6 +40,6 @@ void kbase_trace_mali_mmu_as_in_use(int event); void kbase_trace_mali_mmu_as_released(int event); void kbase_trace_mali_total_alloc_pages_change(long long int event); -#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#endif /* CONFIG_MALI_BIFROST_GATOR_SUPPORT */ #endif /* _KBASE_GATOR_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c index baf3c491c719..4130810f1038 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c @@ -59,7 +59,7 @@ int kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpup get_gpu_speed_mhz = (kbase_gpu_clk_speed_func) GPU_SPEED_FUNC; if (get_gpu_speed_mhz != NULL) { rc = get_gpu_speed_mhz(&gpu_speed_mhz); -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG /* Issue a warning message when the reported GPU speed falls outside the min/max range */ if (rc == 0) { u32 gpu_speed_khz = gpu_speed_mhz * 1000; @@ -71,7 +71,7 @@ int kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpup (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max); } -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ } if (kctx->kbdev->clock) { gpu_speed_mhz = clk_get_rate(kctx->kbdev->clock) / 1000000; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h index 89d26eaf09a4..b9fe8e669c63 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwaccess_time.h @@ -46,7 +46,7 @@ void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter, * * This function is only in use for BASE_HW_ISSUE_6367 */ -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI void kbase_wait_write_flush(struct kbase_context *kctx); #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd.c b/drivers/gpu/arm/bifrost/mali_kbase_jd.c index 9f9e0c44bcb0..144ebfcdfc59 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd.c @@ -106,7 +106,7 @@ static int jd_run_atom(struct kbase_jd_atom *katom) return kbasep_js_add_job(kctx, katom); } -#if defined(CONFIG_KDS) || defined(CONFIG_MALI_DMA_FENCE) +#if defined(CONFIG_KDS) || defined(CONFIG_MALI_BIFROST_DMA_FENCE) void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom) { struct kbase_device *kbdev; @@ -224,7 +224,7 @@ void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) } #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE /* Flush dma-fence workqueue to ensure that any callbacks that may have * been queued are done before continuing. * Any successfully completed atom would have had all it's callbacks @@ -232,7 +232,7 @@ void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) */ if (katom->event_code != BASE_JD_EVENT_DONE) flush_workqueue(katom->kctx->dma_fence.wq); -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ } static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) @@ -246,9 +246,9 @@ static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) katom->kds_dep_satisfied = true; #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE kbase_dma_fence_signal(katom); -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ kbase_gpu_vm_lock(katom->kctx); /* only roll back if extres is non-NULL */ @@ -286,7 +286,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st struct kds_resource **kds_resources = NULL; unsigned long *kds_access_bitmap = NULL; #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE struct kbase_dma_fence_resv_info info = { .dma_fence_resv_count = 0, }; @@ -301,7 +301,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st #else /* CONFIG_SYNC */ const bool implicit_sync = true; #endif /* CONFIG_SYNC */ -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ struct base_external_resource *input_extres; KBASE_DEBUG_ASSERT(katom); @@ -352,7 +352,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st } #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (implicit_sync) { info.resv_objs = kmalloc_array(katom->nr_extres, sizeof(struct reservation_object *), @@ -370,7 +370,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st goto early_err_out; } } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ /* Take the processes mmap lock */ down_read(¤t->mm->mmap_sem); @@ -412,7 +412,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st goto failed_loop; } -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (implicit_sync && reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { struct reservation_object *resv; @@ -422,7 +422,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st kbase_dma_fence_add_reservation(resv, &info, exclusive); } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ /* finish with updating out array with the data we found */ /* NOTE: It is important that this is the last thing we do (or @@ -464,7 +464,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st kfree(kds_access_bitmap); #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (implicit_sync) { if (info.dma_fence_resv_count) { int ret; @@ -477,14 +477,14 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st kfree(info.resv_objs); kfree(info.dma_fence_excl_bitmap); } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ /* all done OK */ return 0; /* error handling section */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE failed_dma_fence_setup: #ifdef CONFIG_KDS /* If we are here, dma_fence setup failed but KDS didn't. @@ -499,11 +499,11 @@ failed_dma_fence_setup: katom->kds_dep_satisfied = true; } #endif /* CONFIG_KDS */ -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ #ifdef CONFIG_KDS failed_kds_setup: #endif -#if defined(CONFIG_KDS) || defined(CONFIG_MALI_DMA_FENCE) +#if defined(CONFIG_KDS) || defined(CONFIG_MALI_BIFROST_DMA_FENCE) /* Lock the processes mmap lock */ down_read(¤t->mm->mmap_sem); @@ -530,7 +530,7 @@ failed_kds_setup: kfree(kds_resources); kfree(kds_access_bitmap); #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (implicit_sync) { kfree(info.resv_objs); kfree(info.dma_fence_excl_bitmap); @@ -568,7 +568,7 @@ static inline void jd_resolve_dep(struct list_head *out_list, } #endif -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE kbase_dma_fence_cancel_callbacks(dep_atom); #endif @@ -593,7 +593,7 @@ static inline void jd_resolve_dep(struct list_head *out_list, !dep_atom->will_fail_event_code && !other_dep_atom->will_fail_event_code))) { bool dep_satisfied = true; -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE int dep_count; dep_count = kbase_fence_dep_count_read(dep_atom); @@ -615,7 +615,7 @@ static inline void jd_resolve_dep(struct list_head *out_list, */ dep_satisfied = false; } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ #ifdef CONFIG_KDS dep_satisfied = dep_satisfied && dep_atom->kds_dep_satisfied; @@ -732,7 +732,7 @@ static void jd_try_submitting_deps(struct list_head *out_list, bool dep1_valid = is_dep_valid( dep_atom->dep[1].atom); bool dep_satisfied = true; -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE int dep_count; dep_count = kbase_fence_dep_count_read( @@ -755,7 +755,7 @@ static void jd_try_submitting_deps(struct list_head *out_list, */ dep_satisfied = false; } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ #ifdef CONFIG_KDS dep_satisfied = dep_satisfied && dep_atom->kds_dep_satisfied; @@ -1010,7 +1010,7 @@ bool jd_submit_atom(struct kbase_context *kctx, const struct base_jd_atom_v2 *us katom->kds_dep_satisfied = true; katom->kds_rset = NULL; #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE kbase_fence_dep_count_set(katom, -1); #endif @@ -1236,12 +1236,12 @@ bool jd_submit_atom(struct kbase_context *kctx, const struct base_jd_atom_v2 *us #endif /* CONFIG_KDS */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (kbase_fence_dep_count_read(katom) != -1) { ret = false; goto out; } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ if ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == BASE_JD_REQ_SOFT_REPLAY) { @@ -1750,13 +1750,13 @@ void kbase_jd_zap_context(struct kbase_context *kctx) } #endif -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE kbase_dma_fence_cancel_all_atoms(kctx); #endif mutex_unlock(&kctx->jctx.lock); -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE /* Flush dma-fence workqueue to ensure that any callbacks that may have * been queued are done before continuing. */ @@ -1795,7 +1795,7 @@ int kbase_jd_init(struct kbase_context *kctx) kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; -#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) kctx->jctx.atoms[i].dma_fence.context = dma_fence_context_alloc(1); atomic_set(&kctx->jctx.atoms[i].dma_fence.seqno, 0); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c index c8b37c4e3291..fed4ad5816ab 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c @@ -57,7 +57,7 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, } #endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { struct kbase_fence_cb *cb; @@ -100,7 +100,7 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, "signaled" : "active"); } } -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.c b/drivers/gpu/arm/bifrost/mali_kbase_js.c index 219e8c80146c..677e438aedfa 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_js.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.c @@ -22,7 +22,7 @@ */ #include #include -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) #include #endif #include @@ -425,11 +425,11 @@ int kbasep_js_devdata_init(struct kbase_device * const kbdev) jsdd = &kbdev->js_data; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG /* Soft-stop will be disabled on a single context by default unless * softstop_always is set */ jsdd->softstop_always = false; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ jsdd->nr_all_contexts_running = 0; jsdd->nr_user_contexts_running = 0; jsdd->nr_contexts_pullable = 0; @@ -1417,7 +1417,7 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal( kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, kbasep_js_is_submit_allowed(js_devdata, kctx)); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_mmu_as_released(kctx->as_nr); #endif KBASE_TLSTREAM_TL_NRET_AS_CTX(&kbdev->as[kctx->as_nr], kctx); @@ -1695,7 +1695,7 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev, kbdev->hwaccess.active_kctx = kctx; -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_mmu_as_in_use(kctx->as_nr); #endif KBASE_TLSTREAM_TL_RET_AS_CTX(&kbdev->as[kctx->as_nr], kctx); @@ -2408,7 +2408,7 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, katom->sched_priority); } -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP, katom->slot_nr), NULL, 0); #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h index ba8b6441549b..0b4890d6b50e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_js_defs.h @@ -257,10 +257,10 @@ struct kbasep_js_device_data { /** List of suspended soft jobs */ struct list_head suspended_soft_jobs_list; -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG /* Support soft-stop on a single context */ bool softstop_always; -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ /** The initalized-flag is placed at the end, to avoid cache-pollution (we should * only be using this during init/term paths). diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.h b/drivers/gpu/arm/bifrost/mali_kbase_mem.h index 820a9beeee78..9d98947390f6 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.h @@ -40,7 +40,7 @@ #include #include "mali_kbase_pm.h" #include "mali_kbase_defs.h" -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) #include "mali_kbase_gator.h" #endif /* Required for kbase_mem_evictable_unmake */ @@ -449,7 +449,7 @@ static inline int kbase_reg_prepare_native(struct kbase_va_region *reg, static inline int kbase_atomic_add_pages(int num_pages, atomic_t *used_pages) { int new_val = atomic_add_return(num_pages, used_pages); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_total_alloc_pages_change((long long int)new_val); #endif return new_val; @@ -458,7 +458,7 @@ static inline int kbase_atomic_add_pages(int num_pages, atomic_t *used_pages) static inline int kbase_atomic_sub_pages(int num_pages, atomic_t *used_pages) { int new_val = atomic_sub_return(num_pages, used_pages); -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_total_alloc_pages_change((long long int)new_val); #endif return new_val; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mmu.c b/drivers/gpu/arm/bifrost/mali_kbase_mmu.c index 2dd20fc4a05b..c63269aed53c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mmu.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mmu.c @@ -27,7 +27,7 @@ #include #include #include -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) #include #endif #include @@ -341,7 +341,7 @@ void page_fault_worker(struct work_struct *data) "Page table update failure"); goto fault_done; } -#if defined(CONFIG_MALI_GATOR_SUPPORT) +#if defined(CONFIG_MALI_BIFROST_GATOR_SUPPORT) kbase_trace_mali_page_fault_insert_pages(as_no, new_pages); #endif KBASE_TLSTREAM_AUX_PAGEFAULT(kctx->id, (u64)new_pages); @@ -923,7 +923,7 @@ static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx, } #endif /* KBASE_GPU_RESET_EN */ -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI /* * As this function could be called in interrupt context the sync * request can't block. Instead log the request and the next flush @@ -932,7 +932,7 @@ static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx, if ((!err) && sync && kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) atomic_set(&kctx->drain_pending, 1); -#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ } static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, @@ -940,12 +940,12 @@ static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, { struct kbase_device *kbdev; bool ctx_is_in_runpool; -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI bool drain_pending = false; if (atomic_xchg(&kctx->drain_pending, 0)) drain_pending = true; -#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ /* Early out if there is nothing to do */ if (nr == 0) @@ -991,7 +991,7 @@ static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, mutex_unlock(&kbdev->mmu_hw_mutex); /* AS transaction end */ -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI /* * The transaction lock must be dropped before here * as kbase_wait_write_flush could take it if @@ -1005,7 +1005,7 @@ static void kbase_mmu_flush_invalidate(struct kbase_context *kctx, /* Wait for GPU to flush write buffer */ kbase_wait_write_flush(kctx); } -#endif /* !CONFIG_MALI_NO_MALI */ +#endif /* !CONFIG_MALI_BIFROST_NO_MALI */ kbase_pm_context_idle(kbdev); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c index c970650069cd..9e73f9f4999e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.c @@ -19,7 +19,7 @@ #include "mali_kbase_regs_history_debugfs.h" -#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_BIFROST_NO_MALI) #include diff --git a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h index f10837002330..fbb36b3f22e4 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_regs_history_debugfs.h @@ -32,7 +32,7 @@ struct kbase_device; -#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI) +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_BIFROST_NO_MALI) /** * kbasep_regs_history_debugfs_init - add debugfs entries for register history diff --git a/drivers/gpu/arm/bifrost/mali_kbase_replay.c b/drivers/gpu/arm/bifrost/mali_kbase_replay.c index 2f8eccfc1757..9f4dc372770d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_replay.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_replay.c @@ -67,7 +67,7 @@ struct fragment_job { static void dump_job_head(struct kbase_context *kctx, char *head_str, struct job_descriptor_header *job) { -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(kctx->kbdev->dev, "%s\n", head_str); dev_dbg(kctx->kbdev->dev, "addr = %p\n" @@ -128,7 +128,7 @@ static int kbasep_replay_reset_sfbd(struct kbase_context *kctx, return -EINVAL; } -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(kctx->kbdev->dev, "FBD tiler:\n" "flags = %x\n" @@ -211,7 +211,7 @@ static int kbasep_replay_reset_mfbd(struct kbase_context *kctx, return -EINVAL; } -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(kctx->kbdev->dev, "FBD tiler:\n" "flags = %x\n" "heap_free_address = %llx\n", @@ -713,7 +713,7 @@ static int kbasep_replay_create_atoms(struct kbase_context *kctx, return 0; } -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG static void payload_dump(struct kbase_context *kctx, base_jd_replay_payload *payload) { u64 next; @@ -788,7 +788,7 @@ static int kbasep_replay_parse_payload(struct kbase_context *kctx, } #endif /* BASE_LEGACY_UK10_2_SUPPORT */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: payload=%p\n", payload); dev_dbg(kctx->kbdev->dev, "Payload structure:\n" "tiler_jc_list = %llx\n" @@ -1028,7 +1028,7 @@ static bool kbase_replay_fault_check(struct kbase_jd_atom *katom) return false; } -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG dev_dbg(dev, "kbase_replay_fault_check: payload=%p\n", payload); dev_dbg(dev, "\nPayload structure:\n" "fragment_jc = 0x%llx\n" diff --git a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c index cd86b983028b..cafc789ea253 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c @@ -250,7 +250,7 @@ void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt) cancel_timer = 0; } break; -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG case BASE_JD_REQ_SOFT_FENCE_WAIT: /* Keep the timer running if fence debug is enabled and * there are waiting fence jobs. @@ -266,7 +266,7 @@ void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt) spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); } -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG static void kbase_fence_debug_check_atom(struct kbase_jd_atom *katom) { struct kbase_context *kctx = katom->kctx; @@ -368,7 +368,7 @@ static void kbase_fence_debug_timeout(struct kbase_jd_atom *katom) queue_work(kctx->jctx.job_done_wq, &work->work); } } -#endif /* CONFIG_MALI_FENCE_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_FENCE_DEBUG */ void kbasep_soft_job_timeout_worker(unsigned long data) { @@ -404,7 +404,7 @@ void kbasep_soft_job_timeout_worker(unsigned long data) INIT_WORK(&katom->work, kbasep_soft_event_complete_job); queue_work(kctx->jctx.job_done_wq, &katom->work); break; -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG case BASE_JD_REQ_SOFT_FENCE_WAIT: kbase_fence_debug_timeout(katom); break; @@ -1282,7 +1282,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom) int ret = kbase_sync_fence_in_wait(katom); if (ret == 1) { -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG kbasep_add_waiting_with_timeout(katom); #else kbasep_add_waiting_soft_job(katom); @@ -1390,7 +1390,7 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) if (ret < 0) return ret; -#ifdef CONFIG_MALI_DMA_FENCE +#ifdef CONFIG_MALI_BIFROST_DMA_FENCE /* * Set KCTX_NO_IMPLICIT_FENCE in the context the first * time a soft fence wait job is observed. This will @@ -1399,7 +1399,7 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) */ if (!kbase_ctx_flag(katom->kctx, KCTX_NO_IMPLICIT_SYNC)) kbase_ctx_flag_set(katom->kctx, KCTX_NO_IMPLICIT_SYNC); -#endif /* CONFIG_MALI_DMA_FENCE */ +#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ } break; #endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync.h b/drivers/gpu/arm/bifrost/mali_kbase_sync.h index de72147d67ad..ca855b8d1b53 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync.h @@ -192,7 +192,7 @@ const char *kbase_sync_status_string(int status); */ void kbase_sync_fence_wait_worker(struct work_struct *data); -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG /** * kbase_sync_fence_in_dump() Trigger a debug dump of atoms input fence state * @katom: Atom to trigger fence debug dump for diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c index d7349dcae69a..e4528e2b9f25 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c @@ -353,9 +353,9 @@ static void kbase_sync_signal_pt(struct sync_pt *pt, int result) * The warning is only in debug builds to prevent * a malicious user being able to spam dmesg. */ -#ifdef CONFIG_MALI_DEBUG +#ifdef CONFIG_MALI_BIFROST_DEBUG pr_err("Fences were triggered in a different order to allocation!"); -#endif /* CONFIG_MALI_DEBUG */ +#endif /* CONFIG_MALI_BIFROST_DEBUG */ return; } } while (atomic_cmpxchg(&mtl->signaled, @@ -524,7 +524,7 @@ int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, return 0; } -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) { /* Dump out the full state of all the Android sync fences. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c index ef5b7ce478b4..509c0666f10f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c @@ -340,7 +340,7 @@ int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, } -#ifdef CONFIG_MALI_FENCE_DEBUG +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) { /* Not implemented */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c index 5830e87f0818..d9854749f45b 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.c @@ -23,7 +23,7 @@ #define CREATE_TRACE_POINTS -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE #include "mali_timeline.h" #include @@ -233,4 +233,4 @@ void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) } } -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h index 619072f3215c..4b517f396f8c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_trace_timeline.h @@ -20,7 +20,7 @@ #if !defined(_KBASE_TRACE_TIMELINE_H) #define _KBASE_TRACE_TIMELINE_H -#ifdef CONFIG_MALI_TRACE_TIMELINE +#ifdef CONFIG_MALI_BIFROST_TRACE_TIMELINE enum kbase_trace_timeline_code { #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) enum_val @@ -357,7 +357,7 @@ static inline void kbase_timeline_pm_l2_transition_start(struct kbase_device *kb static inline void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) { } -#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#endif /* CONFIG_MALI_BIFROST_TRACE_TIMELINE */ #endif /* _KBASE_TRACE_TIMELINE_H */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_uku.h b/drivers/gpu/arm/bifrost/mali_kbase_uku.h index 2a69da7394ba..cf8ee0572dc5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_uku.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_uku.h @@ -24,13 +24,13 @@ #include "mali_base_kernel.h" /* This file needs to support being included from kernel and userside (which use different defines) */ -#if defined(CONFIG_MALI_ERROR_INJECT) || MALI_ERROR_INJECT_ON +#if defined(CONFIG_MALI_BIFROST_ERROR_INJECT) || MALI_ERROR_INJECT_ON #define SUPPORT_MALI_ERROR_INJECT -#endif /* defined(CONFIG_MALI_ERROR_INJECT) || MALI_ERROR_INJECT_ON */ -#if defined(CONFIG_MALI_NO_MALI) +#endif /* defined(CONFIG_MALI_BIFROST_ERROR_INJECT) || MALI_ERROR_INJECT_ON */ +#if defined(CONFIG_MALI_BIFROST_NO_MALI) #define SUPPORT_MALI_NO_MALI -#elif defined(MALI_NO_MALI) -#if MALI_NO_MALI +#elif defined(MALI_BIFROST_NO_MALI) +#if MALI_BIFROST_NO_MALI #define SUPPORT_MALI_NO_MALI #endif #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c index ed12945d81f1..9c5b2e46c0e5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c @@ -295,7 +295,7 @@ size_t kbase_vinstr_dump_size(struct kbase_device *kbdev) { size_t dump_size; -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_V4)) { u32 nr_cg; @@ -304,7 +304,7 @@ size_t kbase_vinstr_dump_size(struct kbase_device *kbdev) NR_CNT_PER_BLOCK * NR_BYTES_PER_CNT; } else -#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_BIFROST_NO_MALI */ { /* assume v5 for now */ base_gpu_props *props = &kbdev->gpu_props.props; @@ -853,7 +853,7 @@ static void accum_clients(struct kbase_vinstr_context *vinstr_ctx) struct kbase_vinstr_client *iter; int v4 = 0; -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI v4 = kbase_hw_has_feature(vinstr_ctx->kbdev, BASE_HW_FEATURE_V4); #endif @@ -944,7 +944,7 @@ static int kbasep_vinstr_collect_and_accumulate( unsigned long flags; int rcode; -#ifdef CONFIG_MALI_NO_MALI +#ifdef CONFIG_MALI_BIFROST_NO_MALI /* The dummy model needs the CPU mapping. */ gpu_model_set_dummy_prfcnt_base_cpu(vinstr_ctx->cpu_va); #endif @@ -1524,13 +1524,13 @@ static long kbasep_vinstr_hwcnt_reader_ioctl_disable_event( static long kbasep_vinstr_hwcnt_reader_ioctl_get_hwver( struct kbase_vinstr_client *cli, u32 __user *hwver) { -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI struct kbase_vinstr_context *vinstr_ctx = cli->vinstr_ctx; #endif u32 ver = 5; -#ifndef CONFIG_MALI_NO_MALI +#ifndef CONFIG_MALI_BIFROST_NO_MALI KBASE_DEBUG_ASSERT(vinstr_ctx); if (kbase_hw_has_feature(vinstr_ctx->kbdev, BASE_HW_FEATURE_V4)) ver = 4; diff --git a/drivers/gpu/arm/bifrost/platform/rk/Kbuild b/drivers/gpu/arm/bifrost/platform/rk/Kbuild index 700fd4341da5..7cc6c59d969f 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/Kbuild +++ b/drivers/gpu/arm/bifrost/platform/rk/Kbuild @@ -12,14 +12,6 @@ # # -ccflags-y += -I$(srctree)/drivers/staging/android +bifrost_kbase-y += \ + $(MALI_PLATFORM_DIR)/mali_kbase_config_rk.o \ -ifeq ($(CONFIG_MALI_MIDGARD),y) -obj-y += mali_kbase_config_rk.o -# obj-y += mali_kbase_dvfs.o -# obj-y += mali_kbase_platform.o -else ifeq ($(CONFIG_MALI_MIDGARD),m) -SRC += platform/rk/mali_kbase_config_rk.c -# SRC += platform/rk/mali_kbase_dvfs.c -# SRC += platform/rk/mali_kbase_platform.c -endif diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig index f4553d3aa08a..4caa8ec8a0e2 100644 --- a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Kconfig @@ -15,7 +15,7 @@ config MALI_IRQ_LATENCY tristate "Mali GPU IRQ latency measurement" - depends on MALI_MIDGARD && MALI_DEBUG && MALI_KUTF + depends on MALI_BIFROST && MALI_BIFROST_DEBUG && MALI_KUTF default m help This option will build a test module mali_kutf_irq_test that diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile index 2ac4f97aa397..ced37b08e532 100644 --- a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/Makefile @@ -23,9 +23,9 @@ $(error Must specify KDIR to point to the kernel to target)) endif TEST_CCFLAGS := \ - -DMALI_DEBUG=$(MALI_DEBUG) \ + -DMALI_DEBUG=$(MALI_BIFROST_DEBUG) \ -DMALI_BACKEND_KERNEL=$(MALI_BACKEND_KERNEL) \ - -DMALI_NO_MALI=$(MALI_NO_MALI) \ + -DMALI_NO_MALI=$(MALI_BIFROST_NO_MALI) \ -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ -DMALI_USE_UMP=$(MALI_USE_UMP) \ -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \ diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript index 280fa9866957..b06d9ea32924 100644 --- a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/sconscript @@ -23,7 +23,7 @@ if env.GetOption('clean') : cmd = env.Command('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', src, []) env.KernelObjTarget('mali_kutf_irq_test', cmd) else: - makeAction=Action("cd ${SOURCE.dir} && make MALI_DEBUG=${debug} MALI_BACKEND_KERNEL=1 MALI_ERROR_INJECT_ON=${error_inject} MALI_NO_MALI=${no_mali} MALI_UNIT_TEST=${unit} MALI_USE_UMP=${ump} MALI_CUSTOMER_RELEASE=${release} %s && ( ( [ -f mali_kutf_irq_test.ko ] && cp mali_kutf_irq_test.ko $STATIC_LIB_PATH/ ) || touch $STATIC_LIB_PATH/mali_kutf_irq_test.ko)" % env.kernel_get_config_defines(), '$MAKECOMSTR') + makeAction=Action("cd ${SOURCE.dir} && make MALI_BIFROST_DEBUG=${debug} MALI_BACKEND_KERNEL=1 MALI_ERROR_INJECT_ON=${error_inject} MALI_BIFROST_NO_MALI=${no_mali} MALI_UNIT_TEST=${unit} MALI_USE_UMP=${ump} MALI_CUSTOMER_RELEASE=${release} %s && ( ( [ -f mali_kutf_irq_test.ko ] && cp mali_kutf_irq_test.ko $STATIC_LIB_PATH/ ) || touch $STATIC_LIB_PATH/mali_kutf_irq_test.ko)" % env.kernel_get_config_defines(), '$MAKECOMSTR') cmd = env.Command('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', src, [makeAction]) env.Depends('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', '$STATIC_LIB_PATH/kutf.ko') env.Depends('$STATIC_LIB_PATH/mali_kutf_irq_test.ko', '$STATIC_LIB_PATH/mali_kbase.ko') From a58d4bfdbba7b599da897ed8fe4bd4f05ef7cdfe Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Fri, 2 Feb 2018 09:35:53 +0800 Subject: [PATCH 216/427] drivers/gpu/arm: add bifrost/ into kernel build system Change-Id: Ia5728750e6a98d3c366e116013fbd43bff1a1459 Signed-off-by: Zhen Chen --- drivers/gpu/arm/Kbuild | 2 ++ drivers/gpu/arm/Kconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/arm/Kbuild b/drivers/gpu/arm/Kbuild index 3f1675ca0dfb..f14f1c824f87 100755 --- a/drivers/gpu/arm/Kbuild +++ b/drivers/gpu/arm/Kbuild @@ -19,3 +19,5 @@ obj-$(CONFIG_MALI_MIDGARD_FOR_LINUX) += midgard_for_linux/ obj-$(CONFIG_MALI_MIDGARD_FOR_ANDROID) += midgard/ obj-$(CONFIG_MALI400) += mali400/ + +obj-$(CONFIG_MALI_BIFROST) += bifrost/ diff --git a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig index 10a71c6a3c23..8a16646f89de 100755 --- a/drivers/gpu/arm/Kconfig +++ b/drivers/gpu/arm/Kconfig @@ -26,3 +26,5 @@ config MALI_MIDGARD_FOR_LINUX endchoice source "drivers/gpu/arm/midgard/Kconfig" + +source "drivers/gpu/arm/bifrost/Kconfig" From b1ac6cb0f1650449a5d8bd6ed8c5c3a008fc6796 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Fri, 2 Feb 2018 18:21:40 +0800 Subject: [PATCH 217/427] arm64: rockchip_defconfig: add MALI_BIFROST as m and relative configs Change-Id: Iafd93df4a19ad6c1aa317817154d0aed0005f65d Signed-off-by: Zhen Chen --- arch/arm64/configs/rockchip_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 3cecc1487ebd..3453000ed803 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -500,6 +500,12 @@ CONFIG_MALI_EXPERT=y CONFIG_MALI_PLATFORM_THIRDPARTY=y CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk" CONFIG_MALI_DEBUG=y +CONFIG_MALI_BIFROST=m +CONFIG_MALI_BIFROST_DEVFREQ=y +CONFIG_MALI_PLATFORM_NAME="rk" +CONFIG_MALI_BIFROST_EXPERT=y +CONFIG_MALI_BIFROST_DEBUG=y +CONFIG_MALI_PWRSOFT_765=y CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y From be5e47668ce7936181795a4b57eb6a66087e6c90 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Mon, 5 Feb 2018 16:33:33 +0800 Subject: [PATCH 218/427] arm64: dts: rockchip: enable tsadc for px30/3326 Change-Id: I93797773a49d2167c5d9d15d7ac7ab5a0f807240 Signed-off-by: Weixin Zhou --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 ++++ .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 ++++ .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 4 ++++ .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 22 +++++++++++-------- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 86d831e73f97..85112f71641a 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -625,6 +625,10 @@ status = "okay"; }; +&tsadc { + status = "okay"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_xfer &uart1_cts>; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 73521b1ed7cf..2892b0b9650a 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -625,6 +625,10 @@ status = "okay"; }; +&tsadc { + status = "okay"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_xfer &uart1_cts>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index f35560cdd9df..68e45778cf68 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -571,6 +571,10 @@ status = "okay"; }; +&tsadc { + status = "okay"; +}; + &u2phy { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index c7129d6e60e7..dc14f2e70bfa 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -666,6 +666,18 @@ status = "okay"; }; +&route_dsi { + status = "okay"; +}; + +&rk_rga { + status = "okay"; +}; + +&route_lvds { + status = "disabled"; +}; + &saradc { status = "okay"; }; @@ -692,18 +704,10 @@ status = "okay"; }; -&route_dsi { +&tsadc { status = "okay"; }; -&rk_rga { - status = "okay"; -}; - -&route_lvds { - status = "disabled"; -}; - &u2phy { status = "okay"; From af2b840cfe59ae9cf92dbe4ca68220f38e5e2e19 Mon Sep 17 00:00:00 2001 From: Huang jianzhi Date: Mon, 5 Feb 2018 19:45:59 +0800 Subject: [PATCH 219/427] ARM: dts: rockchip: fixed vdd_log max and min value for rk3288-evb-android-rk808-edp Change-Id: I21f4a06bcf30ff39bcbdf8b9bd60f4ad53e4c24d Signed-off-by: Huang jianzhi --- .../arm/boot/dts/rk3288-evb-android-rk808-edp.dts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-android-rk808-edp.dts b/arch/arm/boot/dts/rk3288-evb-android-rk808-edp.dts index 086312069e19..ad913531c56b 100644 --- a/arch/arm/boot/dts/rk3288-evb-android-rk808-edp.dts +++ b/arch/arm/boot/dts/rk3288-evb-android-rk808-edp.dts @@ -68,14 +68,14 @@ /delete-node/ sdmmc-regulator; - vdd_log: vdd-center { + vdd_log: vdd-logic { compatible = "pwm-regulator"; rockchip,pwm_id = <1>; rockchip,pwm_voltage = <1100000>; pwms = <&pwm1 0 25000 1>; regulator-name = "vcc_log"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1400000>; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1360000>; regulator-always-on; regulator-boot-on; }; @@ -144,6 +144,10 @@ mali-supply = <&vdd_gpu>; }; +&gmac { + max-speed = <1000>; +}; + &hdmi_analog_sound { status = "okay"; }; @@ -407,6 +411,11 @@ &rockchip_suspend { status = "okay"; + rockchip,pwm-regulator-config = < + (0 + | PWM1_REGULATOR_EN + ) + >; }; &pwm1 { From f2427362588f6b9e23422966c3944fead18f3aeb Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 26 Jan 2018 10:02:17 +0800 Subject: [PATCH 220/427] drm/rockchip: lvds: Add a better description for rockchip_lvds_soc_data Change-Id: I0750074515fd131abb17d7636b1183842199a9f5 Signed-off-by: Wyon Bi --- drivers/gpu/drm/rockchip/rockchip_lvds.c | 706 ++++++++++++----------- drivers/gpu/drm/rockchip/rockchip_lvds.h | 10 +- 2 files changed, 361 insertions(+), 355 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index be84f48a17dd..76d2a0b8a29b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -44,19 +44,22 @@ #define encoder_to_lvds(c) \ container_of(c, struct rockchip_lvds, encoder) -#define LVDS_CHIP(lvds) ((lvds)->soc_data->chip_type) -/* - * @grf_offset: offset inside the grf regmap for setting the rockchip lvds - */ +enum chip_type { + PX30, + RK3126, + RK3288, + RK3366, + RK3368, +}; + +struct rockchip_lvds; + struct rockchip_lvds_soc_data { - int chip_type; - int grf_soc_con5; - int grf_soc_con6; - int grf_soc_con7; - int grf_soc_con15; - - bool has_vop_sel; + enum chip_type chip_type; + int (*probe)(struct rockchip_lvds *lvds); + int (*power_on)(struct rockchip_lvds *lvds); + void (*power_off)(struct rockchip_lvds *lvds); }; struct rockchip_lvds { @@ -87,7 +90,7 @@ static inline void lvds_writel(struct rockchip_lvds *lvds, u32 offset, u32 val) { writel_relaxed(val, lvds->regs + offset); if ((lvds->output != DISPLAY_OUTPUT_LVDS) && - (LVDS_CHIP(lvds) == RK3288_LVDS)) + (lvds->soc_data->chip_type == RK3288)) writel_relaxed(val, lvds->regs + offset + RK3288_LVDS_CH1_OFFSET); } @@ -143,7 +146,7 @@ static inline int lvds_name_to_output(const char *s) return -EINVAL; } -static int rk3288_lvds_poweron(struct rockchip_lvds *lvds) +static int innov2_lvds_power_on(struct rockchip_lvds *lvds) { if (lvds->output == DISPLAY_OUTPUT_RGB) { lvds_writel(lvds, RK3288_LVDS_CH0_REG0, @@ -220,27 +223,20 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds) return 0; } -static int rk336x_lvds_poweron(struct rockchip_lvds *lvds) +static void innov2_lvds_power_off(struct rockchip_lvds *lvds) +{ + writel(RK3288_LVDS_CFG_REG21_TX_DISABLE, + lvds->regs + RK3288_LVDS_CFG_REG21); + writel(RK3288_LVDS_CFG_REGC_PLL_DISABLE, + lvds->regs + RK3288_LVDS_CFG_REGC); +} + +static int innov1_lvds_power_on(struct rockchip_lvds *lvds) { u32 delay_times = 20; u32 val; if (lvds->output == DISPLAY_OUTPUT_RGB) { - if (LVDS_CHIP(lvds) == PX30_LVDS) { - if (lvds->pins_m0) { - pinctrl_select_state(lvds->pinctrl, - lvds->pins_m0); - return 0; - } else if (lvds->pins_m1) { - pinctrl_select_state(lvds->pinctrl, - lvds->pins_m1); - } else { - dev_err(lvds->dev, - "Can't find pinctrl state m0/m1\n"); - WARN_ON(1); - } - } - /* enable lane */ lvds_writel(lvds, MIPIPHY_REG0, 0x7f); val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | @@ -310,56 +306,21 @@ static int rk336x_lvds_poweron(struct rockchip_lvds *lvds) return 0; } -static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) +static void innov1_lvds_power_off(struct rockchip_lvds *lvds) { - if (LVDS_CHIP(lvds) == RK3288_LVDS) - rk3288_lvds_poweron(lvds); - else - rk336x_lvds_poweron(lvds); + /* disable lvds lane and power off pll */ + lvds_writel(lvds, MIPIPHY_REGEB, + v_LANE0_EN(0) | v_LANE1_EN(0) | v_LANE2_EN(0) | + v_LANE3_EN(0) | v_LANECLK_EN(0) | v_PLL_PWR_OFF(1)); - return 0; -} + /* power down lvds pll and bandgap */ + lvds_msk_reg(lvds, MIPIPHY_REG1, + m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN, + v_SYNC_RST(1) | v_LDO_PWR_DOWN(1) | v_PLL_PWR_DOWN(1)); -static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) -{ - int ret; - u32 val; - - if (LVDS_CHIP(lvds) == RK3288_LVDS) { - writel(RK3288_LVDS_CFG_REG21_TX_DISABLE, - lvds->regs + RK3288_LVDS_CFG_REG21); - writel(RK3288_LVDS_CFG_REGC_PLL_DISABLE, - lvds->regs + RK3288_LVDS_CFG_REGC); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con7, 0xffff8000); - if (ret != 0) - dev_err(lvds->dev, "Could not write to GRF: %d\n", ret); - } else if ((LVDS_CHIP(lvds) == RK336X_LVDS) || - (LVDS_CHIP(lvds) == RK3126_LVDS)) { - if (LVDS_CHIP(lvds) == RK336X_LVDS) - val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(0); - else - val = v_RK3126_LVDSMODE_EN(0) | v_RK3126_MIPIPHY_TTL_EN(0); - ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, "Could not write to GRF: %d\n", ret); - return; - } - - /* disable lvds lane and power off pll */ - lvds_writel(lvds, MIPIPHY_REGEB, - v_LANE0_EN(0) | v_LANE1_EN(0) | v_LANE2_EN(0) | - v_LANE3_EN(0) | v_LANECLK_EN(0) | v_PLL_PWR_OFF(1)); - - /* power down lvds pll and bandgap */ - lvds_msk_reg(lvds, MIPIPHY_REG1, - m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN, - v_SYNC_RST(1) | v_LDO_PWR_DOWN(1) | v_PLL_PWR_DOWN(1)); - - /* disable lvds */ - lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN, - v_LVDS_EN(0) | v_TTL_EN(0)); - } + /* disable lvds */ + lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN, + v_LVDS_EN(0) | v_TTL_EN(0)); } static enum drm_connector_status @@ -426,180 +387,6 @@ static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, drm_mode_copy(&lvds->mode, adjusted); } -static void rockchip_lvds_grf_config(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - struct rockchip_lvds *lvds = encoder_to_lvds(encoder); - u32 h_bp = mode->htotal - mode->hsync_start; - u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; - u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; - u32 val; - int ret; - - if (LVDS_CHIP(lvds) == RK3288_LVDS) { - val = lvds->format; - if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) - val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN; - else if (lvds->output == DISPLAY_OUTPUT_LVDS) - val |= LVDS_CH0_EN; - else if (lvds->output == DISPLAY_OUTPUT_RGB) - val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN; - - if (h_bp & 0x01) - val |= LVDS_START_PHASE_RST_1; - - val |= (pin_dclk << 8) | (pin_hsync << 9); - val |= (0xffff << 16); - ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con7, ret); - return; - } - } else if (LVDS_CHIP(lvds) == RK336X_LVDS) { - if (lvds->output == DISPLAY_OUTPUT_RGB) { - /* enable lvds mode */ - val = v_RK336X_LVDSMODE_EN(0) | - v_RK336X_MIPIPHY_TTL_EN(1) | - v_RK336X_MIPIPHY_LANE0_EN(1) | - v_RK336X_MIPIDPI_FORCEX_EN(1); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con7, ret); - return; - } - val = v_RK336X_FORCE_JETAG(0); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con15, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con15, ret); - return; - } - } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { - /* enable lvds mode */ - val = v_RK336X_LVDSMODE_EN(1) | - v_RK336X_MIPIPHY_TTL_EN(0); - /* config lvds_format */ - val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format); - /* LSB receive mode */ - val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7); - val |= v_RK336X_MIPIPHY_LANE0_EN(1) | - v_RK336X_MIPIDPI_FORCEX_EN(1); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con7, ret); - return; - } - } - } else if (LVDS_CHIP(lvds) == RK3126_LVDS) { - if (lvds->output == DISPLAY_OUTPUT_RGB) { - /* enable lvds mode */ - val = v_RK3126_LVDSMODE_EN(0) | - v_RK3126_MIPIPHY_TTL_EN(1) | - v_RK3126_MIPIPHY_LANE0_EN(1) | - v_RK3126_MIPIDPI_FORCEX_EN(1); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con7, ret); - return; - } - val = v_RK3126_MIPITTL_CLK_EN(1) | - v_RK3126_MIPITTL_LANE0_EN(1) | - v_RK3126_MIPITTL_LANE1_EN(1) | - v_RK3126_MIPITTL_LANE2_EN(1) | - v_RK3126_MIPITTL_LANE3_EN(1); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con15, val); - - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con15, ret); - return; - } - } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { - /* enable lvds mode */ - val = v_RK3126_LVDSMODE_EN(1) | - v_RK3126_MIPIPHY_TTL_EN(0); - /* config lvds_format */ - val |= v_RK3126_LVDS_OUTPUT_FORMAT(lvds->format); - /* LSB receive mode */ - val |= v_RK3126_LVDS_MSBSEL(LVDS_MSB_D7); - val |= v_RK3126_MIPIPHY_LANE0_EN(1) | - v_RK3126_MIPIDPI_FORCEX_EN(1); - ret = regmap_write(lvds->grf, - lvds->soc_data->grf_soc_con7, val); - if (ret != 0) { - dev_err(lvds->dev, - "Could not write to GRF:0x%x: %d\n", - lvds->soc_data->grf_soc_con7, ret); - return; - } - } - } else if (LVDS_CHIP(lvds) == PX30_LVDS) { - val = 0; - if (lvds->output == DISPLAY_OUTPUT_RGB && lvds->pins_m1) - val |= PX30_DPHY_FORCERXMODE(1); - else if (lvds->output == DISPLAY_OUTPUT_LVDS) - val |= PX30_LVDS_OUTPUT_FORMAT(lvds->format) | - PX30_LVDS_MSBSEL(LVDS_MSB_D7); - regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, val); - } -} - -static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds, - struct drm_encoder *encoder) -{ - u32 val; - int ret; - - if (!lvds->soc_data->has_vop_sel) - return 0; - - ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder); - if (ret < 0) - return ret; - - if (LVDS_CHIP(lvds) == RK3288_LVDS) { - if (ret) - val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT | - (RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16); - else - val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; - - ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val); - if (ret < 0) - return ret; - } else if (LVDS_CHIP(lvds) == PX30_LVDS) { - val = 0; - if (lvds->output == DISPLAY_OUTPUT_RGB) - val |= PX30_RGB_VOP_SEL(ret); - else if (lvds->output == DISPLAY_OUTPUT_LVDS) - val |= PX30_LVDS_VOP_SEL(ret); - regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, val); - } else { - if (ret) - val = RK3366_LVDS_VOP_SEL_LIT; - else - val = RK3366_LVDS_VOP_SEL_BIG; - regmap_write(lvds->grf, RK3366_GRF_SOC_CON0, val); - } - - return 0; -} - static int rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -642,13 +429,11 @@ static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) if (lvds->panel) drm_panel_prepare(lvds->panel); - rockchip_lvds_poweron(lvds); + if (lvds->soc_data->power_on) + lvds->soc_data->power_on(lvds); if (lvds->panel) drm_panel_enable(lvds->panel); - - rockchip_lvds_grf_config(encoder, &lvds->mode); - rockchip_lvds_set_vop_source(lvds, encoder); } static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) @@ -658,7 +443,8 @@ static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) if (lvds->panel) drm_panel_disable(lvds->panel); - rockchip_lvds_poweroff(lvds); + if (lvds->soc_data->power_off) + lvds->soc_data->power_off(lvds); if (lvds->panel) drm_panel_unprepare(lvds->panel); @@ -700,64 +486,6 @@ static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = { .destroy = rockchip_lvds_encoder_destroy, }; -static const struct rockchip_lvds_soc_data px30_lvds_data = { - .chip_type = PX30_LVDS, - .has_vop_sel = true, -}; - -static struct rockchip_lvds_soc_data rk3126_lvds_data = { - .chip_type = RK3126_LVDS, - .grf_soc_con7 = RK3126_GRF_LVDS_CON0, - .grf_soc_con15 = RK3126_GRF_CON1, - .has_vop_sel = false, -}; - -static struct rockchip_lvds_soc_data rk3288_lvds_data = { - .chip_type = RK3288_LVDS, - .grf_soc_con6 = 0x025c, - .grf_soc_con7 = 0x0260, - .has_vop_sel = true, -}; - -static struct rockchip_lvds_soc_data rk3366_lvds_data = { - .chip_type = RK336X_LVDS, - .grf_soc_con7 = RK3366_GRF_SOC_CON5, - .grf_soc_con15 = RK3366_GRF_SOC_CON6, - .has_vop_sel = true, -}; - -static struct rockchip_lvds_soc_data rk3368_lvds_data = { - .chip_type = RK336X_LVDS, - .grf_soc_con7 = RK3368_GRF_SOC_CON7, - .grf_soc_con15 = RK3368_GRF_SOC_CON15, - .has_vop_sel = false, -}; - -static const struct of_device_id rockchip_lvds_dt_ids[] = { - { - .compatible = "rockchip,px30-lvds", - .data = &px30_lvds_data - }, - { - .compatible = "rockchip,rk3126-lvds", - .data = &rk3126_lvds_data - }, - { - .compatible = "rockchip,rk3288-lvds", - .data = &rk3288_lvds_data - }, - { - .compatible = "rockchip,rk3366-lvds", - .data = &rk3366_lvds_data - }, - { - .compatible = "rockchip,rk3368-lvds", - .data = &rk3368_lvds_data - }, - {} -}; -MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids); - static int rockchip_lvds_bind(struct device *dev, struct device *master, void *data) { @@ -936,6 +664,7 @@ static int rockchip_lvds_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rockchip_lvds *lvds; struct resource *res; + int ret; lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL); if (!lvds) @@ -950,34 +679,67 @@ static int rockchip_lvds_probe(struct platform_device *pdev) if (IS_ERR(lvds->regs)) return PTR_ERR(lvds->regs); - if (!(LVDS_CHIP(lvds) == RK3288_LVDS)) { - /* pll lock on status reg that is MIPICTRL Register */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "mipi_lvds_ctl"); - lvds->regs_ctrl = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(lvds->regs_ctrl)) { - dev_err(&pdev->dev, "ioremap lvds ctl reg failed\n"); - return PTR_ERR(lvds->regs_ctrl); - } - /* mipi ctrl clk for read lvds phy lock state */ - lvds->pclk_ctrl = devm_clk_get(&pdev->dev, "pclk_lvds_ctl"); - if (IS_ERR(lvds->pclk_ctrl)) { - dev_err(dev, "could not get pclk_ctrl\n"); - lvds->pclk_ctrl = NULL; - } - lvds->hclk_ctrl = devm_clk_get(&pdev->dev, "hclk_vio_h2p"); - if (IS_ERR(lvds->hclk_ctrl)) { - dev_err(dev, "could not get hclk_vio_h2p\n"); - lvds->hclk_ctrl = NULL; - } - } - lvds->pclk = devm_clk_get(dev, "pclk_lvds"); if (IS_ERR(lvds->pclk)) { dev_err(dev, "could not get pclk_lvds\n"); return PTR_ERR(lvds->pclk); } + lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(lvds->grf)) { + dev_err(dev, "missing rockchip,grf property\n"); + return PTR_ERR(lvds->grf); + } + + if (lvds->soc_data->probe) { + ret = lvds->soc_data->probe(lvds); + if (ret) + return ret; + } + + return component_add(dev, &rockchip_lvds_component_ops); +} + +static int rockchip_lvds_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &rockchip_lvds_component_ops); + + return 0; +} + +static int innov1_lvds_probe(struct rockchip_lvds *lvds) +{ + struct device *dev = lvds->dev; + struct resource *res; + + /* pll lock on status reg that is MIPICTRL Register */ + res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 1); + lvds->regs_ctrl = devm_ioremap_resource(dev, res); + if (IS_ERR(lvds->regs_ctrl)) { + dev_err(dev, "ioremap lvds ctl reg failed\n"); + return PTR_ERR(lvds->regs_ctrl); + } + + /* mipi ctrl clk for read lvds phy lock state */ + lvds->pclk_ctrl = devm_clk_get(dev, "pclk_lvds_ctl"); + if (IS_ERR(lvds->pclk_ctrl)) { + dev_err(dev, "could not get pclk_ctrl\n"); + return PTR_ERR(lvds->pclk_ctrl); + } + + return 0; +} + +static int px30_lvds_probe(struct rockchip_lvds *lvds) +{ + struct device *dev = lvds->dev; + int ret; + + ret = innov1_lvds_probe(lvds); + if (ret) + return ret; + lvds->pinctrl = devm_pinctrl_get(dev); if (IS_ERR_OR_NULL(lvds->pinctrl)) { dev_info(dev, "no pinctrl handle\n"); @@ -996,29 +758,277 @@ static int rockchip_lvds_probe(struct platform_device *pdev) } } - lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node, - "rockchip,grf"); - if (IS_ERR(lvds->grf)) { - dev_err(dev, "missing rockchip,grf property\n"); - return PTR_ERR(lvds->grf); - } - - return component_add(dev, &rockchip_lvds_component_ops); + return 0; } -static int rockchip_lvds_remove(struct platform_device *pdev) +static int px30_lvds_power_on(struct rockchip_lvds *lvds) { - component_del(&pdev->dev, &rockchip_lvds_component_ops); + int pipe; + + pipe = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, + &lvds->encoder); + + if (lvds->output == DISPLAY_OUTPUT_RGB) { + regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, + PX30_RGB_VOP_SEL(pipe)); + if (lvds->pins_m0) { + pinctrl_select_state(lvds->pinctrl, lvds->pins_m0); + return 0; + } else if (lvds->pins_m1) { + pinctrl_select_state(lvds->pinctrl, lvds->pins_m1); + regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, + PX30_DPHY_FORCERXMODE(1)); + } else { + dev_err(lvds->dev, "Can't find pinctrl state m0/m1\n"); + WARN_ON(1); + } + } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { + regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, + PX30_LVDS_VOP_SEL(pipe)); + regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, + PX30_LVDS_PHY_MODE(1) | + PX30_LVDS_OUTPUT_FORMAT(lvds->format) | + PX30_LVDS_MSBSEL(LVDS_MSB_D7)); + } + + return innov1_lvds_power_on(lvds); +} + +static void px30_lvds_power_off(struct rockchip_lvds *lvds) +{ + regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, PX30_LVDS_PHY_MODE(0)); + + innov1_lvds_power_off(lvds); +} + +static const struct rockchip_lvds_soc_data px30_lvds_soc_data = { + .chip_type = PX30, + .probe = px30_lvds_probe, + .power_on = px30_lvds_power_on, + .power_off = px30_lvds_power_off, +}; + +static int rk3126_lvds_probe(struct rockchip_lvds *lvds) +{ + int ret; + + ret = innov1_lvds_probe(lvds); + if (ret) + return ret; + + lvds->hclk_ctrl = devm_clk_get(lvds->dev, "hclk_vio_h2p"); + if (IS_ERR(lvds->hclk_ctrl)) { + dev_err(lvds->dev, "could not get hclk_vio_h2p\n"); + return PTR_ERR(lvds->hclk_ctrl); + } return 0; } -struct platform_driver rockchip_lvds_driver = { +static int rk3126_lvds_power_on(struct rockchip_lvds *lvds) +{ + u32 val; + + if (lvds->output == DISPLAY_OUTPUT_RGB) { + /* enable lvds mode */ + val = v_RK3126_LVDSMODE_EN(0) | v_RK3126_MIPIPHY_TTL_EN(1) | + v_RK3126_MIPIPHY_LANE0_EN(1) | + v_RK3126_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0, val); + val = v_RK3126_MIPITTL_CLK_EN(1) | + v_RK3126_MIPITTL_LANE0_EN(1) | + v_RK3126_MIPITTL_LANE1_EN(1) | + v_RK3126_MIPITTL_LANE2_EN(1) | + v_RK3126_MIPITTL_LANE3_EN(1); + regmap_write(lvds->grf, RK3126_GRF_CON1, val); + } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { + /* enable lvds mode */ + val = v_RK3126_LVDSMODE_EN(1) | v_RK3126_MIPIPHY_TTL_EN(0); + /* config lvds_format */ + val |= v_RK3126_LVDS_OUTPUT_FORMAT(lvds->format); + /* LSB receive mode */ + val |= v_RK3126_LVDS_MSBSEL(LVDS_MSB_D7); + val |= v_RK3126_MIPIPHY_LANE0_EN(1) | + v_RK3126_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0, val); + } + + return innov1_lvds_power_on(lvds); +} + +static void rk3126_lvds_power_off(struct rockchip_lvds *lvds) +{ + regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0, + v_RK3126_LVDSMODE_EN(0) | v_RK3126_MIPIPHY_TTL_EN(0)); + + innov1_lvds_power_off(lvds); +} + +static const struct rockchip_lvds_soc_data rk3126_lvds_soc_data = { + .chip_type = RK3126, + .probe = rk3126_lvds_probe, + .power_on = rk3126_lvds_power_on, + .power_off = rk3126_lvds_power_off, +}; + +static int rk3288_lvds_power_on(struct rockchip_lvds *lvds) +{ + struct drm_display_mode *mode = &lvds->mode; + u32 h_bp = mode->htotal - mode->hsync_start; + u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; + u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; + u32 val; + int pipe; + + pipe = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, + &lvds->encoder); + if (pipe) + val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT | + (RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16); + else + val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; + regmap_write(lvds->grf, RK3288_GRF_SOC_CON6, val); + + val = lvds->format; + if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) + val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN; + else if (lvds->output == DISPLAY_OUTPUT_LVDS) + val |= LVDS_CH0_EN; + else if (lvds->output == DISPLAY_OUTPUT_RGB) + val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN; + + if (h_bp & 0x01) + val |= LVDS_START_PHASE_RST_1; + + val |= (pin_dclk << 8) | (pin_hsync << 9); + val |= (0xffff << 16); + regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, val); + + return innov2_lvds_power_on(lvds); +} + +static void rk3288_lvds_power_off(struct rockchip_lvds *lvds) +{ + regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, 0xffff8000); + + innov2_lvds_power_off(lvds); +} + +static const struct rockchip_lvds_soc_data rk3288_lvds_soc_data = { + .chip_type = RK3288, + .power_on = rk3288_lvds_power_on, + .power_off = rk3288_lvds_power_off, +}; + +static int rk3366_lvds_power_on(struct rockchip_lvds *lvds) +{ + u32 val; + int pipe; + + pipe = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, + &lvds->encoder); + if (pipe) + val = RK3366_LVDS_VOP_SEL_LIT; + else + val = RK3366_LVDS_VOP_SEL_BIG; + regmap_write(lvds->grf, RK3366_GRF_SOC_CON0, val); + + if (lvds->output == DISPLAY_OUTPUT_RGB) { + /* enable lvds mode */ + val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(1) | + v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3366_GRF_SOC_CON5, val); + val = v_RK336X_FORCE_JETAG(0); + regmap_write(lvds->grf, RK3366_GRF_SOC_CON6, val); + } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { + /* enable lvds mode */ + val = v_RK336X_LVDSMODE_EN(1) | v_RK336X_MIPIPHY_TTL_EN(0); + /* config lvds_format */ + val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format); + /* LSB receive mode */ + val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7); + val |= v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3366_GRF_SOC_CON5, val); + } + + return innov1_lvds_power_on(lvds); +} + +static void rk3366_lvds_power_off(struct rockchip_lvds *lvds) +{ + regmap_write(lvds->grf, RK3366_GRF_SOC_CON5, + v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(0)); + + innov1_lvds_power_off(lvds); +} + +static const struct rockchip_lvds_soc_data rk3366_lvds_soc_data = { + .chip_type = RK3366, + .probe = innov1_lvds_probe, + .power_on = rk3366_lvds_power_on, + .power_off = rk3366_lvds_power_off, +}; + +static int rk3368_lvds_power_on(struct rockchip_lvds *lvds) +{ + u32 val; + + if (lvds->output == DISPLAY_OUTPUT_RGB) { + /* enable lvds mode */ + val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(1) | + v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3368_GRF_SOC_CON7, val); + val = v_RK336X_FORCE_JETAG(0); + regmap_write(lvds->grf, RK3368_GRF_SOC_CON15, val); + } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { + /* enable lvds mode */ + val = v_RK336X_LVDSMODE_EN(1) | v_RK336X_MIPIPHY_TTL_EN(0); + /* config lvds_format */ + val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format); + /* LSB receive mode */ + val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7); + val |= v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); + regmap_write(lvds->grf, RK3368_GRF_SOC_CON7, val); + } + + return innov1_lvds_power_on(lvds); +} + +static void rk3368_lvds_power_off(struct rockchip_lvds *lvds) +{ + regmap_write(lvds->grf, RK3368_GRF_SOC_CON7, + v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(0)); + + innov1_lvds_power_off(lvds); +} + +static const struct rockchip_lvds_soc_data rk3368_lvds_soc_data = { + .chip_type = RK3368, + .probe = innov1_lvds_probe, + .power_on = rk3368_lvds_power_on, + .power_off = rk3368_lvds_power_off, +}; + +static const struct of_device_id rockchip_lvds_dt_ids[] = { + { .compatible = "rockchip,px30-lvds", .data = &px30_lvds_soc_data }, + { .compatible = "rockchip,rk3126-lvds", .data = &rk3126_lvds_soc_data }, + { .compatible = "rockchip,rk3288-lvds", .data = &rk3288_lvds_soc_data }, + { .compatible = "rockchip,rk3366-lvds", .data = &rk3366_lvds_soc_data }, + { .compatible = "rockchip,rk3368-lvds", .data = &rk3368_lvds_soc_data }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids); + +static struct platform_driver rockchip_lvds_driver = { .probe = rockchip_lvds_probe, .remove = rockchip_lvds_remove, .driver = { - .name = "rockchip-lvds", - .of_match_table = of_match_ptr(rockchip_lvds_dt_ids), + .name = "rockchip-lvds", + .of_match_table = of_match_ptr(rockchip_lvds_dt_ids), }, }; module_platform_driver(rockchip_lvds_driver); diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.h b/drivers/gpu/drm/rockchip/rockchip_lvds.h index 7f1c7dd96119..06319d27dd2c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.h +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.h @@ -88,6 +88,9 @@ #define RK3288_LVDS_PLL_PREDIV_REGD(_pd) \ (_pd & RK3288_LVDS_CH0_REGD_PLL_PREDIV_MASK) +#define RK3288_GRF_SOC_CON6 0x025c +#define RK3288_GRF_SOC_CON7 0x0260 + #define RK3288_LVDS_SOC_CON6_SEL_VOP_LIT BIT(3) #define RK3366_GRF_SOC_CON0 0x0400 @@ -223,11 +226,4 @@ enum { LVDS_MSB_D7, }; -enum rockchip_lvds_sub_devtype { - PX30_LVDS, - RK3126_LVDS, - RK3288_LVDS, - RK336X_LVDS, -}; - #endif /* _ROCKCHIP_LVDS_ */ From 2a37a264e98358ed2611940b0255e86b44614543 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 31 Jan 2018 17:19:03 +0800 Subject: [PATCH 221/427] clk: rockchip: px30: Fix softrst register number Change-Id: Ieefc9cedb56fbe7dc6810135e87592c6f65b7124 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 7b9c3f68d7b6..7a2ee7047dc8 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -1083,7 +1083,7 @@ static void __init px30_clk_init(struct device_node *np) &px30_cpuclk_data, px30_cpuclk_rates, ARRAY_SIZE(px30_cpuclk_rates)); - rockchip_register_softrst(np, 11, reg_base + PX30_SOFTRST_CON(0), + rockchip_register_softrst(np, 12, reg_base + PX30_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); rockchip_register_restart_notifier(ctx, PX30_GLB_SRST_FST, NULL); From 36726233ea34231aeba690434ffadf2d677c504b Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 31 Jan 2018 21:32:17 +0800 Subject: [PATCH 222/427] clk: rockchip: px30: Fix some clock div_width Fix uart, tsadc and saradc div_width. Fix saradc clksel_con. Change-Id: Iafc4e4436e7d273a1cfc80d1d8ada3fce8239912 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 7a2ee7047dc8..0fd2356a4a96 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -682,7 +682,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(10), 7, GFLAGS), COMPOSITE(0, "clk_uart1_src", mux_uart_src_p, 0, - PX30_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_CLKGATE_CON(10), 12, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(36), 0, @@ -695,7 +695,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(10), 15, GFLAGS), COMPOSITE(SCLK_UART2_SRC, "clk_uart2_src", mux_uart_src_p, 0, - PX30_CLKSEL_CON(37), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_CLKSEL_CON(37), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_CLKGATE_CON(11), 0, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(39), 0, @@ -708,7 +708,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(11), 3, GFLAGS), COMPOSITE(0, "clk_uart3_src", mux_uart_src_p, 0, - PX30_CLKSEL_CON(40), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_CLKSEL_CON(40), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_CLKGATE_CON(11), 4, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(42), 0, @@ -721,7 +721,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(11), 7, GFLAGS), COMPOSITE(0, "clk_uart4_src", mux_uart_src_p, 0, - PX30_CLKSEL_CON(43), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_CLKSEL_CON(43), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_CLKGATE_CON(11), 8, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(45), 0, @@ -734,7 +734,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(11), 11, GFLAGS), COMPOSITE(0, "clk_uart5_src", mux_uart_src_p, 0, - PX30_CLKSEL_CON(46), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_CLKSEL_CON(46), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_CLKGATE_CON(11), 12, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(48), 0, @@ -785,10 +785,10 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(13), 5, GFLAGS), COMPOSITE_NOMUX(SCLK_TSADC, "clk_tsadc", "xin24m", 0, - PX30_CLKSEL_CON(54), 0, 10, DFLAGS, + PX30_CLKSEL_CON(54), 0, 11, DFLAGS, PX30_CLKGATE_CON(12), 9, GFLAGS), COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0, - PX30_CLKSEL_CON(54), 0, 10, DFLAGS, + PX30_CLKSEL_CON(55), 0, 11, DFLAGS, PX30_CLKGATE_CON(12), 10, GFLAGS), COMPOSITE_NOMUX(SCLK_OTP, "clk_otp", "xin24m", 0, PX30_CLKSEL_CON(56), 0, 3, DFLAGS, @@ -953,7 +953,7 @@ static struct rockchip_clk_branch px30_clk_pmu_branches[] __initdata = { PX30_PMU_CLKGATE_CON(0), 15, GFLAGS), COMPOSITE(0, "clk_uart0_pmu_src", mux_uart_src_p, 0, - PX30_PMU_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + PX30_PMU_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 5, DFLAGS, PX30_PMU_CLKGATE_CON(1), 0, GFLAGS), COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_pmu_src", CLK_SET_RATE_PARENT, PX30_PMU_CLKSEL_CON(5), 0, From 263f468566fff5ba0a5c0b69bb75070c9cd07497 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 1 Feb 2018 14:22:55 +0800 Subject: [PATCH 223/427] clk: rockchip: px30: Add clk_ddrmon_timer Change-Id: I41cd72bb89b06e7239582f35a1e5455745b764d9 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 0fd2356a4a96..842050b59e26 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -391,6 +391,9 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { GATE(0, "clk_ddrmon", "clk_ddrphy1x", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(1), 11, GFLAGS), + GATE(0, "clk_ddrmon_timer", "xin24m", CLK_IGNORE_UNUSED, + PX30_CLKGATE_CON(0), 15, GFLAGS), + COMPOSITE_NOMUX(PCLK_DDR, "pclk_ddr", "gpll", CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(2), 8, 5, DFLAGS, PX30_CLKGATE_CON(1), 1, GFLAGS), From 2bb022aa283ee9d80645f9c04258a632612e0452 Mon Sep 17 00:00:00 2001 From: Tony Xie Date: Tue, 6 Feb 2018 11:57:15 +0800 Subject: [PATCH 224/427] arm64: dts: rockchip: enable i20 status and replace vccsys and vcc5v0_sys for px30/rk3326 board Change-Id: I8ad097dbd3f82d8b5b9d456a37a3be8ed14ae144 Signed-off-by: Tony Xie --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 20 ++++++++++--------- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 20 ++++++++++--------- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 20 ++++++++++--------- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 20 ++++++++++--------- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 85112f71641a..199b8279660f 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -116,6 +116,15 @@ regulator-boot-on; }; + vcc5v0_sys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + wireless-wlan { compatible = "wlan-platdata"; wifi_chip_type = "AP6210"; @@ -264,6 +273,8 @@ }; &i2c0 { + status = "okay"; + rk809: pmic@20 { compatible = "rockchip,rk809"; reg = <0x20>; @@ -286,15 +297,6 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; - vcc5v0_sys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - rk817_pin0_ts: rk817_pin0_ts { pins = "gpio0"; function = "pin_fun0"; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 2892b0b9650a..60cb556f9099 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -116,6 +116,15 @@ regulator-boot-on; }; + vcc5v0_sys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + wireless-wlan { compatible = "wlan-platdata"; wifi_chip_type = "AP6210"; @@ -264,6 +273,8 @@ }; &i2c0 { + status = "okay"; + rk809: pmic@20 { compatible = "rockchip,rk809"; reg = <0x20>; @@ -286,15 +297,6 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; - vcc5v0_sys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - rk817_pin0_ts: rk817_pin0_ts { pins = "gpio0"; function = "pin_fun0"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 68e45778cf68..5c20808e43f4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -92,6 +92,15 @@ reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ }; + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + wireless-wlan { compatible = "wlan-platdata"; wifi_chip_type = "rtl8723cs"; @@ -200,6 +209,8 @@ }; &i2c0 { + status = "okay"; + rk817: pmic@20 { compatible = "rockchip,rk817"; reg = <0x20>; @@ -222,15 +233,6 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; - vccsys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc3v8_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3800000>; - regulator-max-microvolt = <3800000>; - }; - rk817_pin0_ts: rk817_pin0_ts { pins = "gpio0"; function = "pin_fun0"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index dc14f2e70bfa..ac85ad3d589d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -150,6 +150,15 @@ reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ }; + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v8_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3800000>; + regulator-max-microvolt = <3800000>; + }; + wireless-wlan { compatible = "wlan-platdata"; wifi_chip_type = "AP6210"; @@ -297,6 +306,8 @@ }; &i2c0 { + status = "okay"; + rk817: pmic@20 { compatible = "rockchip,rk817"; reg = <0x20>; @@ -319,15 +330,6 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; - vccsys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc3v8_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3800000>; - regulator-max-microvolt = <3800000>; - }; - rk817_pin0_ts: rk817_pin0_ts { pins = "gpio0"; function = "pin_fun0"; From 1fa81ca9bf61b6201a872ff7a65075e40f6ec6b1 Mon Sep 17 00:00:00 2001 From: Zhaoyifeng Date: Tue, 6 Feb 2018 10:24:51 +0800 Subject: [PATCH 225/427] drivers: rk_nand: fix nand driver shutdown issue bug: if nand driver initialize fail, shutdown function will will access undefined address and kernel will abnormal reset. [ 2.793278] [] __wake_up_common+0x28/0x90 [ 2.793775] [] __wake_up+0x3c/0x54 [ 2.794231] [] rknand_dev_shutdown+0x40/0x64 [ 2.794753] [] rknand_shutdown+0x24/0x2c [ 2.795252] [] platform_drv_shutdown+0x20/0x28 [ 2.795796] [] device_shutdown+0x15c/0x1b0 [ 2.796308] [] kernel_restart_prepare+0x34/0x3c [ 2.796850] [] kernel_restart+0x14/0x5c [ 2.797337] [] SyS_reboot+0x198/0x1f0 [ 2.797812] [] el0_svc_naked+0x24/0x28 [ 2.798290] Code: 2a0103f6 2a0203f5 f8408e80 2a0303f7 (f85e8413) [ 2.798856] ---[ end trace dac58c6cbecdc881 ]--- [ 2.645282] init: Reboot ending, jumping to kernel [ 2.647526] rknand_shutdown... Change-Id: I21b946f9ed790170be8024c2d39ed18bc2835994 Signed-off-by: Zhaoyifeng --- drivers/rk_nand/rk_nand_blk.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/rk_nand/rk_nand_blk.c b/drivers/rk_nand/rk_nand_blk.c index b4bd08f39d7c..df0d6f0e2d34 100644 --- a/drivers/rk_nand/rk_nand_blk.c +++ b/drivers/rk_nand/rk_nand_blk.c @@ -729,6 +729,8 @@ static void nand_blk_unregister(struct nand_blk_ops *nandr) { struct list_head *this, *next; + if (!rk_nand_dev_initialised) + return; nandr->quit = 1; wake_up(&nandr->thread_wq); wait_for_completion(&nandr->thread_exit); @@ -744,6 +746,8 @@ static void nand_blk_unregister(struct nand_blk_ops *nandr) void rknand_dev_flush(void) { + if (!rk_nand_dev_initialised) + return; rknand_device_lock(); rk_ftl_cache_write_back(); rknand_device_unlock(); @@ -778,21 +782,23 @@ int __init rknand_dev_init(void) int rknand_dev_exit(void) { - if (rk_nand_dev_initialised) { - rk_nand_dev_initialised = 0; - if (rknand_device_trylock()) { - rk_ftl_cache_write_back(); - rknand_device_unlock(); - } - nand_blk_unregister(&mytr); - rk_ftl_de_init(); - pr_info("nand_blk_dev_exit:OK\n"); + if (!rk_nand_dev_initialised) + return -1; + rk_nand_dev_initialised = 0; + if (rknand_device_trylock()) { + rk_ftl_cache_write_back(); + rknand_device_unlock(); } + nand_blk_unregister(&mytr); + rk_ftl_de_init(); + pr_info("nand_blk_dev_exit:OK\n"); return 0; } void rknand_dev_suspend(void) { + if (!rk_nand_dev_initialised) + return; pr_info("rk_nand_suspend\n"); rk_nand_schedule_enable_config(0); rknand_device_lock(); @@ -801,6 +807,8 @@ void rknand_dev_suspend(void) void rknand_dev_resume(void) { + if (!rk_nand_dev_initialised) + return; pr_info("rk_nand_resume\n"); rk_nand_resume(); rknand_device_unlock(); @@ -810,6 +818,8 @@ void rknand_dev_resume(void) void rknand_dev_shutdown(void) { pr_info("rknand_shutdown...\n"); + if (!rk_nand_dev_initialised) + return; if (mytr.quit == 0) { mytr.quit = 1; wake_up(&mytr.thread_wq); @@ -818,4 +828,3 @@ void rknand_dev_shutdown(void) } pr_info("rknand_shutdown:OK\n"); } - From 781b2a44f1cca7d3796797c988ead300142ea86c Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 6 Feb 2018 12:38:12 +0800 Subject: [PATCH 226/427] arm64: dts: rockchip: px30: add VOP PD control Change-Id: Id9a7d2f5eb4bd69f9c02f2105591699a8a3b88cc Signed-off-by: Sandy Huang --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 2c88d7d1102c..3e655a0d58b4 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -974,6 +974,7 @@ clocks = <&cru ACLK_VOPB>, <&cru DCLK_VOPB>, <&cru HCLK_VOPB>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + power-domains = <&power PX30_PD_VO>; iommus = <&vopb_mmu>; status = "disabled"; @@ -1012,6 +1013,7 @@ clocks = <&cru ACLK_VOPL>, <&cru DCLK_VOPL>, <&cru HCLK_VOPL>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + power-domains = <&power PX30_PD_VO>; iommus = <&vopl_mmu>; status = "disabled"; From f580090ea22f2d214e0b85aeda8572342fc9495d Mon Sep 17 00:00:00 2001 From: Jung Zhao Date: Tue, 6 Feb 2018 14:28:56 +0800 Subject: [PATCH 227/427] video: rockchip: vpu: fix crash bug when translate failed when translate failed, driver will print the regs. but kernel must use kernel memory, if we print user memory, it will crash. Change-Id: Icfe30e4b70485e2d20d0d75dca7d51d3b904e7cc Signed-off-by: Jung Zhao --- drivers/video/rockchip/vcodec/vcodec_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c index 4b2eb9093d35..f30777925b03 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c @@ -1235,7 +1235,7 @@ static struct vpu_reg *reg_init(struct vpu_subdev_data *data, vpu_err("error: translate reg address failed, dumping regs\n"); for (i = 0; i < size >> 2; i++) dev_err(pservice->dev, "reg[%02d]: %08x\n", - i, *((u32 *)src + i)); + i, reg->reg[i]); kfree(reg); return NULL; From c2e122487dc3b4d14a82ef9307ab44e055ff0bd4 Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 6 Feb 2018 14:59:21 +0800 Subject: [PATCH 228/427] pinctrl: rockchip: Fix the uart2 & uart3 route bit of px30 Uart2 and uart3 both have routed bit, use their rx pin to switch m0 or m1. Change-Id: I4d5251f88484b1d98ab29071d34e4f14819520d6 Signed-off-by: David Wu --- drivers/pinctrl/pinctrl-rockchip.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index a76248afba1f..0073fa7e7c20 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -732,31 +732,31 @@ static struct rockchip_mux_route_data px30_mux_route_data[] = { }, { /* uart2-rxm0 */ .bank_num = 1, - .pin = 26, + .pin = 27, .func = 2, .route_offset = 0x184, - .route_val = BIT(16 + 9), + .route_val = BIT(16 + 10), }, { /* uart2-rxm1 */ .bank_num = 2, .pin = 14, .func = 2, .route_offset = 0x184, - .route_val = BIT(16 + 9) | BIT(9), + .route_val = BIT(16 + 10) | BIT(10), }, { /* uart3-rxm0 */ .bank_num = 0, .pin = 17, .func = 2, .route_offset = 0x184, - .route_val = BIT(16 + 10), + .route_val = BIT(16 + 9), }, { /* uart3-rxm1 */ .bank_num = 1, - .pin = 13, + .pin = 15, .func = 2, .route_offset = 0x184, - .route_val = BIT(16 + 10) | BIT(10), + .route_val = BIT(16 + 9) | BIT(9), }, }; From a36a41bf39306ea88a22fc3487809dcc41c8b27d Mon Sep 17 00:00:00 2001 From: Tony Xie Date: Tue, 6 Feb 2018 15:50:03 +0800 Subject: [PATCH 229/427] arm64: dts: rockchip: change the vdd_arm and vdd_logic node of px30/rk3326 board change the vdd_arm and vdd_logic dts node for rk3326 and px30. delete the pinctrl define for rk818 and rk809. Change-Id: I4fcc10ac48b4b91f4225efc2efdb78227de005ba Signed-off-by: Tony Xie --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 50 ++++++------------- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 50 ++++++------------- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 50 ++++++------------- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 50 ++++++------------- 4 files changed, 60 insertions(+), 140 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 199b8279660f..4e2cfb54d601 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -297,42 +297,8 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; - - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; - - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; - - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; - }; - regulators { - vdd_arm: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x1>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; - }; - }; - - vdd_logic: DCDC_REG2 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; @@ -340,6 +306,20 @@ regulator-ramp-delay = <6001>; regulator-initial-mode = <0x1>; regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <800000>; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 60cb556f9099..7ad17d7371eb 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -297,42 +297,8 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; - - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; - - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; - - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; - }; - regulators { - vdd_arm: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x1>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; - }; - }; - - vdd_logic: DCDC_REG2 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; @@ -340,6 +306,20 @@ regulator-ramp-delay = <6001>; regulator-initial-mode = <0x1>; regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <800000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 5c20808e43f4..1724570e54f8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -233,42 +233,8 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; - - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; - - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; - - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; - }; - regulators { - vdd_arm: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x1>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; - }; - }; - - vdd_logic: DCDC_REG2 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; @@ -276,6 +242,20 @@ regulator-ramp-delay = <6001>; regulator-initial-mode = <0x1>; regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <800000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index ac85ad3d589d..3fd623be9c07 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -330,42 +330,8 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; - - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; - - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; - - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; - }; - regulators { - vdd_arm: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x1>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; - }; - }; - - vdd_logic: DCDC_REG2 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; @@ -373,6 +339,20 @@ regulator-ramp-delay = <6001>; regulator-initial-mode = <0x1>; regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <700000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <800000>; From ac8d6f24a8614ce622b62b921c2daac5ef71034c Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 6 Feb 2018 09:12:56 +0800 Subject: [PATCH 230/427] arm64: dts: rockchip: add cpu opp-table for px30/rk3326 Change-Id: I7b70e534302a66d168a7902ca0759e7535767948 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30.dtsi | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 3e655a0d58b4..0295264e9efd 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -40,6 +40,8 @@ compatible = "arm,cortex-a35", "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; + clocks = <&cru ARMCLK>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu1: cpu@1 { @@ -47,18 +49,59 @@ compatible = "arm,cortex-a35", "arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; }; cpu2: cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a35", "arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; }; cpu3: cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a35", "arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; + }; + + cpu0_opp_table: cpu0-opp-table { + compatible = "operating-points-v2"; + opp-shared; + + opp-408000000 { + opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <1075000>; + clock-latency-ns = <40000>; + opp-suspend; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1075000>; + clock-latency-ns = <40000>; + }; + opp-816000000 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <1125000>; + clock-latency-ns = <40000>; + }; + opp-1008000000 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <1225000>; + clock-latency-ns = <40000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1350000>; + clock-latency-ns = <40000>; + }; + opp-1296000000 { + opp-hz = /bits/ 64 <1296000000>; + opp-microvolt = <1425000>; + clock-latency-ns = <40000>; + status = "disabled"; }; }; From 08097c03ee8a33f578811dbfdcd654301b46514b Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 6 Feb 2018 08:58:38 +0800 Subject: [PATCH 231/427] arm64: dts: rockchip: add gpu opp-table for px30/rk3326 Change-Id: Ib169c4f15d2f0844b39b80554247675a29c1d356 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 0295264e9efd..43b6fa836e0e 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -908,10 +908,32 @@ clocks = <&cru ACLK_GPU>; clock-names = "clk_mali"; + operating-points-v2 = <&gpu_opp_table>; status = "disabled"; }; + gpu_opp_table: gpu-opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <1025000>; + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <1075000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1150000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <1225000>; + }; + }; + hevc: hevc_service@ff440000 { compatible = "rockchip,hevc_sub"; iommu_enabled = <1>; From a869e09080476d302cdf15bd1a51c6e3f4d3440f Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 6 Feb 2018 09:14:19 +0800 Subject: [PATCH 232/427] arm64: dts: rockchip: add cpu regulator supply for px30/rk3326 board Change-Id: I961d5fa4dee43eb78b79357dca95b10c9753cec0 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 4e2cfb54d601..52952cb69883 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -244,6 +244,10 @@ }; }; +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + &dsi_in_vopl { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 7ad17d7371eb..056904fdc92e 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -244,6 +244,10 @@ }; }; +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + &dsi_in_vopl { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 1724570e54f8..f78acee282d8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -189,6 +189,10 @@ }; }; +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + &dsi_in_vopl { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 3fd623be9c07..a05e1fec35d8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -189,6 +189,10 @@ status = "okay"; }; +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + &display_subsystem { status = "okay"; }; From 66cbf767cc4019a16b8d00f8a47304d346a8e754 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 6 Feb 2018 09:01:07 +0800 Subject: [PATCH 233/427] arm64: dts: rockchip: add gpu regulator supply for px30/rk3326 board Change-Id: I6fe2c5168dd9637f53bfd2647f65d55fe008b339 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 1 + arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 1 + arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 1 + arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 52952cb69883..7d63ec9fd4f7 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -273,6 +273,7 @@ }; &gpu { + mali-supply = <&vdd_logic>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 056904fdc92e..414ebeeea82d 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -273,6 +273,7 @@ }; &gpu { + mali-supply = <&vdd_logic>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index f78acee282d8..593579192e38 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -209,6 +209,7 @@ }; &gpu { + mali-supply = <&vdd_logic>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index a05e1fec35d8..cd90c119aeb5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -306,6 +306,7 @@ }; &gpu { + mali-supply = <&vdd_logic>; status = "okay"; }; From 78335d6eb76a1c33c59dacbcdbcb9ed2cab953f8 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 6 Feb 2018 16:08:03 +0800 Subject: [PATCH 234/427] arm64: dts: rockchip: px30-android: add pinctrl for fiq-debugger Change-Id: I7845d43a9e6e90e75e10adb50cf59cc6bb527b14 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-android.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index c6d37ef8cdd7..919b94bc3132 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -17,6 +17,8 @@ rockchip,irq-mode-enable = <0>; rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer>; status = "okay"; }; From 1a185964d4d0ebcdc62652b1657a3904d29a885f Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Tue, 23 Jan 2018 20:17:17 +0800 Subject: [PATCH 235/427] arm64: rockchip_defconfig: enable CONFIG_INPUT_RK8XX_PWRKEY Change-Id: I25ee47671ad9a65d8cffd2958f21f6d433cde20d Signed-off-by: Joseph Chen --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 3453000ed803..f33938b387bb 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -397,6 +397,7 @@ CONFIG_HALL_DEVICE=y CONFIG_HS_MH248=y CONFIG_INPUT_MISC=y CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_RK8XX_PWRKEY=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y # CONFIG_SERIO is not set From 990d5872ed4b966238e1ba16a704312f578378f6 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 6 Feb 2018 14:12:47 +0800 Subject: [PATCH 236/427] drm/rockchip: alloc object with limit to 32bit when LPAE enabled Change-Id: I049c52b1fcee2d14e9db477f4cb58d352d456da3 Signed-off-by: Jianqun Xu --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 212d9fbc6595..273a52b5eb66 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -581,6 +581,11 @@ rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) struct address_space *mapping; struct rockchip_gem_object *rk_obj; struct drm_gem_object *obj; +#ifdef CONFIG_ARM_LPAE + gfp_t gfp_mask = GFP_HIGHUSER | __GFP_RECLAIMABLE | __GFP_DMA32; +#else + gfp_t gfp_mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; +#endif size = round_up(size, PAGE_SIZE); @@ -593,8 +598,7 @@ rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) drm_gem_object_init(drm, obj, size); mapping = file_inode(obj->filp)->i_mapping; - mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE - | __GFP_DMA32); + mapping_set_gfp_mask(mapping, gfp_mask); return rk_obj; } From c1e9d2d5af33a6491aea9608753c41aaf5f08d47 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 6 Feb 2018 23:24:32 +0800 Subject: [PATCH 237/427] arm64: dts: rockchip: px30: Fix clocks reference error Change-Id: Iabf143473893e32905055350e91b3b9f3b631718 Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 43b6fa836e0e..17c280b00dff 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -270,7 +270,7 @@ compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; reg = <0x0 0xff030000 0x0 0x100>; interrupts = ; - clocks = <&cru SCLK_UART0_PMU>, <&cru PCLK_UART0_PMU>; + clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>; clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; @@ -715,7 +715,7 @@ compatible = "rockchip,px30-usb2phy", "rockchip,rk3328-usb2phy"; reg = <0x100 0x10>; - clocks = <&cru SCLK_USBPHY_REF>; + clocks = <&pmucru SCLK_USBPHY_REF>; clock-names = "phyclk"; #clock-cells = <0>; assigned-clocks = <&cru USB480M>; @@ -745,7 +745,7 @@ mipi_dphy: mipi-dphy@ff2e0000 { compatible = "rockchip,px30-mipi-dphy"; reg = <0x0 0xff2e0000 0x0 0x10000>; - clocks = <&cru SCLK_MIPIDSIPHY_REF>, <&cru PCLK_MIPIDSIPHY>; + clocks = <&pmucru SCLK_MIPIDSIPHY_REF>, <&cru PCLK_MIPIDSIPHY>; clock-names = "ref", "pclk"; clock-output-names = "mipi_dphy_pll"; #clock-cells = <0>; @@ -1290,7 +1290,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff040000 0x0 0x100>; interrupts = ; - clocks = <&cru PCLK_GPIO0_PMU>; + clocks = <&pmucru PCLK_GPIO0_PMU>; gpio-controller; #gpio-cells = <2>; From 83ff2ccac7370f944e847b25d31b367a3db15cd4 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 7 Feb 2018 00:22:13 +0800 Subject: [PATCH 238/427] soc: rockchip: power-domain: Fix wrong value when power up pd Change-Id: I430db30743d7bf7b6fb5c3adc21591c5d22c0974 Signed-off-by: Finley Xiao --- drivers/soc/rockchip/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 67407076dc80..6dafbf6d428c 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -345,7 +345,7 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, return; else if (pd->info->pwr_w_mask) regmap_write(pmu->regmap, pmu->info->pwr_offset, - on ? pd->info->pwr_mask : + on ? pd->info->pwr_w_mask : (pd->info->pwr_mask | pd->info->pwr_w_mask)); else regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, From 50dc19e1d977f42215ecdfedc0b85f616d835994 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 6 Feb 2018 14:38:45 +0800 Subject: [PATCH 239/427] arm64: dts: rockchip: px30: Enable power controller Change-Id: Ib6ea75b967b7f54b0b7d7e3cc839abfd37590150 Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 17c280b00dff..e3e175c8c155 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -156,7 +156,6 @@ #power-domain-cells = <1>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; /* These power domains are grouped by VD_LOGIC */ pd_usb@PX30_PD_USB { @@ -796,6 +795,7 @@ interrupts = ; clocks = <&cru HCLK_OTG>; clock-names = "otg"; + power-domains = <&power PX30_PD_USB>; dr_mode = "otg"; g-np-tx-fifo-size = <16>; g-rx-fifo-size = <275>; @@ -813,6 +813,7 @@ clocks = <&cru HCLK_HOST>, <&cru HCLK_HOST_ARB>, <&u2phy>; clock-names = "usbhost", "arbiter", "utmi"; + power-domains = <&power PX30_PD_USB>; phys = <&u2phy_host>; phy-names = "usb"; status = "disabled"; @@ -825,6 +826,7 @@ clocks = <&cru HCLK_HOST>, <&cru HCLK_HOST_ARB>, <&u2phy>; clock-names = "usbhost", "arbiter", "utmi"; + power-domains = <&power PX30_PD_USB>; phys = <&u2phy_host>; phy-names = "usb"; }; @@ -858,6 +860,7 @@ max-frequency = <150000000>; clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; clock-names = "biu", "ciu"; + power-domains = <&power PX30_PD_SDCARD>; fifo-depth = <0x100>; interrupts = ; status = "disabled"; @@ -870,6 +873,7 @@ clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; + power-domains = <&power PX30_PD_MMC_NAND>; fifo-depth = <0x100>; interrupts = ; status = "disabled"; @@ -882,6 +886,7 @@ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; + power-domains = <&power PX30_PD_MMC_NAND>; fifo-depth = <0x100>; interrupts = ; status = "disabled"; @@ -894,6 +899,7 @@ nandc_id = <0>; clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; clock-names = "clk_nandc", "hclk_nandc"; + power-domains = <&power PX30_PD_MMC_NAND>; status = "disabled"; }; @@ -908,6 +914,7 @@ clocks = <&cru ACLK_GPU>; clock-names = "clk_mali"; + power-domains = <&power PX30_PD_GPU>; operating-points-v2 = <&gpu_opp_table>; status = "disabled"; @@ -971,6 +978,7 @@ <&cru SRST_VPU_CORE>; reset-names = "video_a", "video_h", "niu_a", "niu_h", "video_core"; + power-domains = <&power PX30_PD_VPU>; mode_bit = <15>; mode_ctrl = <0x410>; name = "vpu_combo"; @@ -984,6 +992,7 @@ interrupt-names = "hevc_mmu"; clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VPU>; #iommu-cells = <0>; }; @@ -994,6 +1003,7 @@ interrupt-names = "vpu_mmu"; clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VPU>; #iommu-cells = <0>; }; @@ -1066,6 +1076,7 @@ interrupt-names = "vopb_mmu"; clocks = <&cru ACLK_VOPB>, <&cru HCLK_VOPB>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VO>; #iommu-cells = <0>; status = "disabled"; }; @@ -1105,6 +1116,7 @@ interrupt-names = "vopl_mmu"; clocks = <&cru ACLK_VOPL>, <&cru HCLK_VOPL>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VO>; #iommu-cells = <0>; status = "disabled"; }; @@ -1116,6 +1128,7 @@ interrupts = ; clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>; clock-names = "aclk_rga", "hclk_rga"; + power-domains = <&power PX30_PD_VO>; dma-coherent; status = "disabled"; }; @@ -1128,6 +1141,7 @@ clock-names = "aclk_cif0", "hclk_cif0", "pclk_cif", "cif0_out"; resets = <&cru SRST_CIF_A>, <&cru SRST_CIF_H>, <&cru SRST_CIF_PCLKIN>; reset-names = "rst_cif_a", "rst_cif_h", "rst_cif_pclkin"; + power-domains = <&power PX30_PD_VI>; pinctrl-names = "cif_pin_all"; pinctrl-0 = <&dvp_d2d9_m0>; status = "disabled"; @@ -1140,6 +1154,7 @@ interrupt-names = "vip_mmu"; clocks = <&cru ACLK_CIF>, <&cru HCLK_CIF>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VI>; rk_iommu,disable_reset_quirk; #iommu-cells = <0>; status = "disabled"; @@ -1155,6 +1170,7 @@ "pclkin_isp", "clk_cif_pll", "clk_cif_out", "pclk_dphyrx"; resets = <&cru SRST_ISP>, <&cru SRST_MIPICSIPHY_P>; reset-names = "rst_isp", "rst_mipicsiphy"; + power-domains = <&power PX30_PD_VI>; pinctrl-names = "default"; pinctrl-0 = <&cif_clkout_m0>; rockchip,isp,mipiphy = <0>; @@ -1173,6 +1189,7 @@ interrupt-names = "isp_mmu"; clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>; clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VI>; rk_iommu,disable_reset_quirk; #iommu-cells = <0>; status = "disabled"; From 21ac5604d31d5927cb6369d2be8a22734610918e Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 7 Feb 2018 09:55:20 +0800 Subject: [PATCH 240/427] soc: rockchip: fiq debugger: clear busy interrupt before ATF fiq init If uart has busy interrupt before ATF fiq init, although IER is 0, it would cause interrupt. Thus after enable uart fiq of gic during init, it may cause infinite interrupt because there is no uart handler to clear the interrupts. Change-Id: If530d266068e25132206519e5bf41762f6a7c9bd Signed-off-by: Huibin Hong --- drivers/soc/rockchip/rk_fiq_debugger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/rockchip/rk_fiq_debugger.c b/drivers/soc/rockchip/rk_fiq_debugger.c index 964d26f0dea1..1986e6373c50 100755 --- a/drivers/soc/rockchip/rk_fiq_debugger.c +++ b/drivers/soc/rockchip/rk_fiq_debugger.c @@ -466,6 +466,8 @@ void rk_serial_debug_init(void __iomem *base, phys_addr_t phy_base, goto out3; } + /* clear busy interrupt, make sure all interrupts are disabled */ + rk_fiq_read(t, UART_USR); #ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE if ((signal_irq > 0) && (serial_hwirq > 0)) { ret = fiq_debugger_bind_sip_smc(t, phy_base, serial_hwirq, From 2e4d140fe496b17c4feeb6ff815b6cff81ae0d3a Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 08:58:16 +0800 Subject: [PATCH 241/427] arm64: dts: rockchip: px30: update lvds and dsi node Fixes: d79a94292536 ("arm64: dts: rockchip: px30: update lvds and dsi node") Change-Id: I767744e2c0aa9d9df184077ddc5ea69c2c11e8f1 Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/px30.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index e3e175c8c155..b40a7d3dd96f 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -775,14 +775,14 @@ #address-cells = <1>; #size-cells = <0>; - lvds_in_vopl: endpoint@0 { + lvds_in_vopb: endpoint@0 { reg = <0>; - remote-endpoint = <&vopl_out_lvds>; + remote-endpoint = <&vopb_out_lvds>; }; - lvds_in_vopb: endpoint@1 { + lvds_in_vopl: endpoint@1 { reg = <1>; - remote-endpoint = <&vopb_out_lvds>; + remote-endpoint = <&vopl_out_lvds>; }; }; }; @@ -1028,14 +1028,14 @@ #address-cells = <1>; #size-cells = <0>; - dsi_in_vopl: endpoint@0 { + dsi_in_vopb: endpoint@0 { reg = <0>; - remote-endpoint = <&vopl_out_dsi>; + remote-endpoint = <&vopb_out_dsi>; }; - dsi_in_vopb: endpoint@1 { + dsi_in_vopl: endpoint@1 { reg = <1>; - remote-endpoint = <&vopb_out_dsi>; + remote-endpoint = <&vopl_out_dsi>; }; }; }; From 04f66170c1c99da6d3c189eabdc28e90834288c6 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 09:01:09 +0800 Subject: [PATCH 242/427] arm64: dts: rockchip: rk3326-evb-lp3-v10: correct enable-gpios for panel Change-Id: I5d8e10b0edc6a577b6e6c2836546b4c27d9386d0 Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index cd90c119aeb5..21039345c414 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -97,7 +97,7 @@ panel { compatible = "auo,b101ew05", "simple-panel"; backlight = <&backlight>; - enable-gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; disable-delay-ms = <10>; bus-format = ; width-mm = <217>; @@ -204,7 +204,7 @@ compatible = "sitronix,st7703", "simple-panel-dsi"; reg = <0>; backlight = <&backlight>; - enable-gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; prepare-delay-ms = <2>; reset-delay-ms = <1>; init-delay-ms = <20>; @@ -272,7 +272,7 @@ native-mode = <&st7703_timing>; st7703_timing: timing0 { - clock-frequency = <64000000>; + clock-frequency = <66000000>; hactive = <720>; vactive = <1280>; hfront-porch = <40>; @@ -654,7 +654,7 @@ }; &route_dsi { - status = "okay"; + status = "disabled"; }; &rk_rga { From 15e470ac6bd74e703ab0ed7a4b95095befb66cf2 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Tue, 6 Feb 2018 22:39:32 +0800 Subject: [PATCH 243/427] arm64: dts: rockchip: add gt1x config for px30/rk3326 evb board Change-Id: Ic13cf5d07ee6d5f42f02b801252a8aa0d26246b4 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 11 +++++------ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 11 +++++------ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 11 +++++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 7d63ec9fd4f7..97e65dbe75d7 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -513,12 +513,11 @@ reprobe_en = <1>; }; - ts@40 { - status = "okay"; - compatible = "GT1X"; - reg = <0x14>; - irq_gpio_number = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - rst_gpio_number = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; }; sensor@4c { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 414ebeeea82d..9f51bef0ac96 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -514,12 +514,11 @@ reprobe_en = <1>; }; - ts@40 { - status = "okay"; - compatible = "GT1X"; - reg = <0x14>; - irq_gpio_number = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - rst_gpio_number = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; }; sensor@4c { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 21039345c414..8dfaf01aec71 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -567,12 +567,11 @@ reprobe_en = <1>; }; - ts@40 { - status = "okay"; - compatible = "GT1X"; - reg = <0x14>; - irq_gpio_number = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - rst_gpio_number = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; }; sensor@4c { From 6837f6f0d6742ca44f197ea24acce1a71b46fb6e Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Wed, 7 Feb 2018 11:20:40 +0800 Subject: [PATCH 244/427] arm64: dts: rockchip: fix panel for rk3326 863 tablet board Change-Id: I8e5314fd606e135bfea1334d5c677b17cdae9c7f Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 593579192e38..5e095f7f972b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -140,7 +140,7 @@ compatible = "aoly,sl008pa21y1285-b00", "simple-panel-dsi"; reg = <0>; backlight = <&backlight>; - enable-gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; prepare-delay-ms = <20>; reset-delay-ms = <20>; @@ -171,7 +171,7 @@ native-mode = <&timing0>; timing0: timing0 { - clock-frequency = <65000000>; + clock-frequency = <66000000>; hactive = <800>; vactive = <1280>; hfront-porch = <2>; @@ -529,7 +529,7 @@ }; &route_dsi { - status = "okay"; + status = "disabled"; }; &saradc { From 1aa2618e86a4cbdcf5dc4496cec5ab193c9dfc87 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Thu, 18 Jan 2018 09:29:43 +0800 Subject: [PATCH 245/427] drm/rockchip: dsi: support dual-link mode Display Pipeline: 1) dual-channel mode --> dsi0 --> dphy_tx0 --> / ! \ vopl/vopb --> dphy_pll --> panel \ ! / --> dsi1 --> dphy_tx1 --> 2) dual-link mode vopb/vopl --> dsi0 --> dphy_tx0 --> panel0 ! dphy_pll ! vopl/vopb --> dsi1 --> dphy_tx1 --> panel1 Change-Id: Iddbea22f121959e4afa969d74549d8fb66ab09f1 Signed-off-by: Wyon Bi --- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 34 +++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 959f273f381a..b4d2173a90e3 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -33,6 +33,9 @@ #define DRIVER_NAME "dw-mipi-dsi" +#define IS_DSI0(dsi) ((dsi)->id == 0) +#define IS_DSI1(dsi) ((dsi)->id == 1) + #define DSI_VERSION 0x00 #define DSI_PWR_UP 0x04 #define RESET 0 @@ -534,8 +537,6 @@ static void mipi_dphy_power_off(struct dw_mipi_dsi *dsi) { if (dsi->dphy.phy) phy_power_off(dsi->dphy.phy); - - regmap_write(dsi->regmap, DSI_PHY_RSTZ, PHY_RSTZ); } static void dw_mipi_dsi_host_power_on(struct dw_mipi_dsi *dsi) @@ -549,9 +550,22 @@ static void dw_mipi_dsi_host_power_off(struct dw_mipi_dsi *dsi) regmap_write(dsi->regmap, DSI_PWR_UP, RESET); } +static void dw_mipi_dsi_phy_pll_init(struct dw_mipi_dsi *dsi) +{ + dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->dphy.input_div)); + dw_mipi_dsi_phy_write(dsi, 0x18, + LOOP_DIV_LOW_SEL(dsi->dphy.feedback_div) | + LOW_PROGRAM_EN); + dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); + dw_mipi_dsi_phy_write(dsi, 0x18, + LOOP_DIV_HIGH_SEL(dsi->dphy.feedback_div) | + HIGH_PROGRAM_EN); + dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); +} + static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) { - int testdin, vco, val; + int testdin, vco; vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200; @@ -574,13 +588,8 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin)); - dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->dphy.input_div)); - val = LOOP_DIV_LOW_SEL(dsi->dphy.feedback_div) | LOW_PROGRAM_EN; - dw_mipi_dsi_phy_write(dsi, 0x18, val); - dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); - val = LOOP_DIV_HIGH_SEL(dsi->dphy.feedback_div) | HIGH_PROGRAM_EN; - dw_mipi_dsi_phy_write(dsi, 0x18, val); - dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); + if (IS_DSI0(dsi)) + dw_mipi_dsi_phy_pll_init(dsi); dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT | BIAS_BLOCK_ON | BANDGAP_ON); @@ -1273,7 +1282,10 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, s->color_space = V4L2_COLORSPACE_DEFAULT; if (dsi->slave) - s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL_CHANNEL; + s->output_flags |= ROCKCHIP_OUTPUT_DSI_DUAL_CHANNEL; + + if (IS_DSI1(dsi)) + s->output_flags |= ROCKCHIP_OUTPUT_DSI_DUAL_LINK; return 0; } From 6abfe1d6177bf53f2b7029b376045408d152d2a4 Mon Sep 17 00:00:00 2001 From: huangjc Date: Tue, 6 Feb 2018 16:35:38 +0800 Subject: [PATCH 246/427] drm: bridge: synopsys: Fix hdmi can't display in android Change-Id: I2f3ee8176761b5227c30df25c569e4c34ae773e2 Signed-off-by: Jiancai Huang --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 36efc391626b..cf4b7be4fd08 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3597,7 +3597,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, hdmi->phy.name); ret = hdmi_readb(hdmi, HDMI_PHY_STAT0); - if (ret & (HDMI_PHY_TX_PHY_LOCK | HDMI_PHY_HPD)) { + if ((ret & HDMI_PHY_TX_PHY_LOCK) && (ret & HDMI_PHY_HPD)) { hdmi->mc_clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); hdmi->disabled = false; hdmi->bridge_is_on = true; From 08ec13e4d0d66733eb299718a69609573f78d8c8 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Wed, 7 Feb 2018 11:17:01 +0800 Subject: [PATCH 247/427] drm: rockchip: dw-hdmi: fix 10bit not work when booting up with uboot logo Default value of hdmi->colordepth is defined by input color mode, so there is no need to set value again when color depth property is created. Change-Id: I2e242fabdaadc0c3b41e48f806cbded5f619c455 Signed-off-by: Zheng Yang --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 9f2ee9dab8f3..bdc96cd4253d 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -947,7 +947,6 @@ dw_hdmi_rockchip_attatch_properties(struct drm_connector *connector, if (prop) { hdmi->color_depth_property = prop; drm_object_attach_property(&connector->base, prop, 0); - hdmi->colordepth = 8; } } From 1cfda2f55e4d47c6838f90e197aea5e0e75e6b41 Mon Sep 17 00:00:00 2001 From: Xinhuang Li Date: Wed, 31 Jan 2018 17:45:10 +0800 Subject: [PATCH 248/427] clk: rockchip: rk3228: Add clock id for pclk_acodecphy Change-Id: I289f2c2681e187eaed0cda1561544581409ffd07 Signed-off-by: Xinhuang Li Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3228.c | 2 +- include/dt-bindings/clock/rk3228-cru.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index fb3f34fb449f..ba278f4ebdfc 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -608,7 +608,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { GATE(0, "pclk_sim", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), - GATE(0, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), + GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 8, GFLAGS), GATE(0, "pclk_phy_noc", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 9, GFLAGS), diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index d9544a90b94a..9b2aaa3110cc 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -124,6 +124,7 @@ #define PCLK_HDMI_CTRL 364 #define PCLK_HDMI_PHY 365 #define PCLK_GMAC 367 +#define PCLK_ACODECPHY 368 /* hclk gates */ #define HCLK_I2S0_8CH 442 From 712e48b64a5a6026ebfa151fbaf90dd6319cabc6 Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Tue, 6 Feb 2018 14:14:39 +0800 Subject: [PATCH 249/427] arm64: dts: rockchip: rk3368-r88: enable dmc and dfi Change-Id: I87f9c30778d4b58d4447abb89e01bc59b00b6ad0 Signed-off-by: Zhangbin Tong --- arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index 2d8254f30408..ccc09e7cf30c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -173,6 +173,35 @@ }; }; +&dfi { + status = "okay"; +}; + +&dmc { + system-status-freq = < + /*system status freq(KHz)*/ + SYS_STATUS_NORMAL 528000 + SYS_STATUS_REBOOT 600000 + SYS_STATUS_SUSPEND 192000 + SYS_STATUS_VIDEO_1080P 400000 + SYS_STATUS_VIDEO_4K 800000 + SYS_STATUS_PERFORMANCE 800000 + SYS_STATUS_BOOST 400000 + SYS_STATUS_DUALVIEW 400000 + SYS_STATUS_ISP 400000 + >; + center-supply = <&vdd_gpu>; + auto-freq-en = <0>; + status = "okay"; +}; + +&dmc_opp_table { + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1175000>; + }; +}; + &i2s_8ch { status = "okay"; rockchip,i2s-broken-burst-len; From b1c013a23176427e72d5a07c246ece3492688e48 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 08:32:04 +0800 Subject: [PATCH 250/427] phy/rockchip: mipi-dphy: Fix pclk handing Change-Id: I6f57995cb65bdeb0aa750387107b8c4ba2080293 Signed-off-by: Wyon Bi --- drivers/phy/rockchip/phy-rockchip-inno-mipi-dphy.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-mipi-dphy.c b/drivers/phy/rockchip/phy-rockchip-inno-mipi-dphy.c index 7654df738b23..380f370749f4 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-mipi-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-mipi-dphy.c @@ -173,6 +173,7 @@ struct inno_video_phy_socdata { struct inno_mipi_dphy { struct device *dev; struct clk *ref_clk; + struct clk *pclk; struct clk *h2p_clk; struct regmap *regmap; struct reset_control *rst; @@ -638,6 +639,7 @@ static int inno_mipi_dphy_power_on(struct phy *phy) struct inno_mipi_dphy *inno = phy_get_drvdata(phy); clk_prepare_enable(inno->h2p_clk); + clk_prepare_enable(inno->pclk); pm_runtime_get_sync(inno->dev); inno_mipi_dphy_pll_enable(inno); inno_mipi_dphy_lane_enable(inno); @@ -655,6 +657,7 @@ static int inno_mipi_dphy_power_off(struct phy *phy) inno_mipi_dphy_lane_disable(inno); inno_mipi_dphy_pll_disable(inno); pm_runtime_put(inno->dev); + clk_disable_unprepare(inno->pclk); clk_disable_unprepare(inno->h2p_clk); return 0; @@ -801,8 +804,8 @@ static int inno_mipi_dphy_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - inno->regmap = devm_regmap_init_mmio_clk(dev, "pclk", regs, - &inno_mipi_dphy_regmap_config); + inno->regmap = devm_regmap_init_mmio(dev, regs, + &inno_mipi_dphy_regmap_config); if (IS_ERR(inno->regmap)) { ret = PTR_ERR(inno->regmap); dev_err(dev, "failed to init regmap: %d\n", ret); @@ -815,6 +818,12 @@ static int inno_mipi_dphy_probe(struct platform_device *pdev) return PTR_ERR(inno->ref_clk); } + inno->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(inno->pclk)) { + dev_err(dev, "failed to get pclk\n"); + return PTR_ERR(inno->pclk); + } + if (inno->socdata->has_h2p_clk) { inno->h2p_clk = devm_clk_get(dev, "h2p"); if (IS_ERR(inno->h2p_clk)) { From 78e60f5ad512fbb353628f24c20baa3a988c0331 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 7 Feb 2018 13:11:05 +0800 Subject: [PATCH 251/427] drm/rockchip: px30 vop: correct for alpha config Change-Id: Ifc9741392e3b3fc2996917655e84535039e5ca00 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 134969cd0c5f..750551d8c486 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1247,6 +1247,7 @@ static const struct vop_win_phy rk3366_lit_win0_data = { .alpha_mode = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0x1, 0), + .global_alpha_val = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0xff, 4), .key_color = VOP_REG(RK3366_LIT_WIN0_COLOR_KEY, 0xffffff, 0), .key_en = VOP_REG(RK3366_LIT_WIN0_COLOR_KEY, 0x1, 24), }; @@ -1265,6 +1266,7 @@ static const struct vop_win_phy rk3366_lit_win1_data = { .alpha_mode = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0x1, 0), + .global_alpha_val = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0xff, 4), .key_color = VOP_REG(RK3366_LIT_WIN1_COLOR_KEY, 0xffffff, 0), .key_en = VOP_REG(RK3366_LIT_WIN1_COLOR_KEY, 0x1, 24), }; @@ -1458,13 +1460,30 @@ static const struct vop_ctrl px30_ctrl_data = { .cabc_global_dn_limit_en = VOP_REG(PX30_CABC_CTRL3, 0x1, 8), }; +static const struct vop_win_phy px30_win23_data = { + .data_formats = formats_win_lite, + .nformats = ARRAY_SIZE(formats_win_lite), + .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), + .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), + .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), + .ymirror = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15), + .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), + .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), + .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), + .alpha_mode = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 1), + .alpha_en = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 0), + .global_alpha_val = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 4), +}; + static const struct vop_win_data px30_vop_big_win_data[] = { { .base = 0x00, .phy = &rk3366_lit_win0_data, .type = DRM_PLANE_TYPE_PRIMARY }, { .base = 0x00, .phy = &rk3366_lit_win1_data, .type = DRM_PLANE_TYPE_CURSOR, .feature = WIN_FEATURE_AFBDC }, - { .base = 0xe0, .phy = &rk3368_win23_data, + { .base = 0xe0, .phy = &px30_win23_data, .type = DRM_PLANE_TYPE_OVERLAY, .area = rk3368_area_data, .area_size = ARRAY_SIZE(rk3368_area_data), }, From f283252018b4b57df444f8d68e8e8c595d358495 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 7 Feb 2018 15:06:22 +0800 Subject: [PATCH 252/427] clk: rockchip: px30: make clk_gpu_divnp5 critical If disable clk_gpu_divnp5, we will get error below: [ 3.699114] rockchip-pm-domain ff000000.power-management:power-controller: failed to get ack on domain 'pd_gpu', val=0x43c443c4 [ 3.700579] W : [File] : drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c; [Line] : 134; [Fu nc] : kbase_platform_rk_init(); power-off-delay-ms not available. [ 3.700880] Unhandled fault: synchronous external abort (0x96000010) at 0xffffff8009620000 [ 3.700897] Internal error: : 96000010 [#1] PREEMPT SMP [ 3.703090] Modules linked in: bifrost_kbase(+) [ 3.703524] CPU: 0 PID: 1 Comm: init Not tainted 4.4.112 #578 [ 3.704034] Hardware name: Rockchip rk3326 evb board (DT) [ 3.704515] task: ffffffc00a308000 task.stack: ffffffc00a310000 [ 3.705362] PC is at kbase_reg_read+0xd0/0x1c8 [bifrost_kbase] [ 3.706173] LR is at kbase_backend_gpuprops_get+0x24/0x20c [bifrost_kbase] Change-Id: I481cdaa60b5174ae6763e11fb42f79ed9208c120 Signed-off-by: Liang Chen --- drivers/clk/rockchip/clk-px30.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 842050b59e26..a6d6492821be 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -1007,6 +1007,7 @@ static const char *const px30_critical_clocks[] __initconst = { "aclk_peri_pre", "hclk_peri_pre", "aclk_gpu_niu", + "clk_gpu_divnp5", }; static const char *const px30_pmucru_critical_clocks[] __initconst = { From fb0bdec10fb54550fb63b332e65cab9319fc3f4f Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Wed, 7 Feb 2018 15:42:05 +0800 Subject: [PATCH 253/427] arm64: dts: rockchip: modify sensor layout value of rk3326-863-lp3-v10 board Change-Id: Ida4cf4b314c34a5daf7706d74913505945584b1c Signed-off-by: Zorro Liu --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 5e095f7f972b..ea000c3d9f5b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -475,7 +475,7 @@ irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>; irq_enable = <0>; poll_delay_ms = <30>; - layout = <6>; + layout = <7>; reprobe_en = <1>; }; }; From 7300f293eb2dfd87a5b3dc85baba3da3fe928137 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 16:29:26 +0800 Subject: [PATCH 254/427] arm64: dts: rockchip: px30: correct reg address for lvds node Change-Id: I40365c31fe801f29c5cb2ffa57b478d1fe63b2b0 Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/px30.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index b40a7d3dd96f..5cc2a4ed89b0 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -758,8 +758,7 @@ lvds: lvds@ff2e0000 { compatible = "rockchip,px30-lvds"; - reg = <0x0 0xff2e0000 0x0 0x100>, <0x0 0xff2e0100 0x0 0x100>; - reg-names = "mipi_lvds_phy", "mipi_lvds_ctl"; + reg = <0x0 0xff2e0000 0x0 0x10000>, <0x0 0xff450000 0x0 0x10000>; clocks = <&cru PCLK_MIPIDSIPHY>, <&cru PCLK_MIPI_DSI>; clock-names = "pclk_lvds", "pclk_lvds_ctl"; power-domains = <&power PX30_PD_VO>; From b7dc6245a72d3ac4b9259d53f439706d16ced416 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 16:33:46 +0800 Subject: [PATCH 255/427] drm/rockchip: lvds: Add support for PX30 Fixes: 35cd525521e6 ("drm/rockchip: lvds: Add support for PX30") Change-Id: Ib71efbb6a063694d755df287568e0d14d6074238 Signed-off-by: Wyon Bi --- drivers/gpu/drm/rockchip/rockchip_lvds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 76d2a0b8a29b..d6e1af78a94d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -788,7 +788,8 @@ static int px30_lvds_power_on(struct rockchip_lvds *lvds) regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, PX30_LVDS_PHY_MODE(1) | PX30_LVDS_OUTPUT_FORMAT(lvds->format) | - PX30_LVDS_MSBSEL(LVDS_MSB_D7)); + PX30_LVDS_MSBSEL(LVDS_MSB_D7) | + PX30_DPHY_FORCERXMODE(1)); } return innov1_lvds_power_on(lvds); From 8645f241e2d6545835508dd428d708a058a5fce1 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 7 Feb 2018 16:36:56 +0800 Subject: [PATCH 256/427] arm64: dts: rockchip: rk3326-evb-lp3-v10: add samsung,lsl070nl01 lvds panel Change-Id: I491f42a1f4bcef37220225de42e6b5e32d7849cd Signed-off-by: Wyon Bi --- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 8dfaf01aec71..07483ebef83b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -95,14 +95,16 @@ }; panel { - compatible = "auo,b101ew05", "simple-panel"; + compatible = "samsung,lsl070nl01", "simple-panel"; backlight = <&backlight>; enable-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; - disable-delay-ms = <10>; - bus-format = ; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; width-mm = <217>; height-mm = <136>; - rockchip,data-mapping = "jeida"; + rockchip,data-mapping = "vesa"; rockchip,data-width = <24>; rockchip,output = "lvds"; status = "disabled"; @@ -111,15 +113,15 @@ native-mode = <&b101ew05_timing>; b101ew05_timing: timing0 { - clock-frequency = <74250000>; - hactive = <1280>; - vactive = <800>; - hback-porch = <220>; - hfront-porch = <110>; - vback-porch = <20>; - vfront-porch = <5>; - hsync-len = <40>; - vsync-len = <5>; + clock-frequency = <49500000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <90>; + hfront-porch = <90>; + vback-porch = <10>; + vfront-porch = <10>; + hsync-len = <90>; + vsync-len = <10>; hsync-active = <0>; vsync-active = <0>; de-active = <0>; @@ -598,9 +600,6 @@ }; &lvds { - //pinctrl-names = "lcdc"; - //pinctrl-0 = <&lcdc_rgb_dclk_pin &lcdc_rgb_m0_den_pin &lcdc_rgb_m0_hsync_pin &lcdc_rgb_m0_vsync_pin &lcdc_rgb666_m0_data_pins>; - //pinctrl-0 = <&lcdc_rgb_dclk_pin &lcdc_rgb666_m1_data_pins>; status = "disabled"; ports { From cdf1300d505436fcbcccb221448a7d77bf3c3ad9 Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Wed, 7 Feb 2018 15:52:25 +0800 Subject: [PATCH 257/427] arm64: dts: rockchip: px30: add basic thermal config Change-Id: I4febd05098d1adb1cf26e20fa4929d6c3a65541f Signed-off-by: Rocky Hao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 5cc2a4ed89b0..1920f16ef56a 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { compatible = "rockchip,px30"; @@ -635,6 +636,23 @@ }; }; + thermal_zones: thermal-zones { + soc_thermal: soc-thermal { + polling-delay-passive = <20>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + sustainable-power = <1000>; /* milliwatts */ + + thermal-sensors = <&tsadc 0>; + }; + + gpu_thermal: gpu-thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&tsadc 1>; + }; + }; + tsadc: tsadc@ff280000 { compatible = "rockchip,px30-tsadc"; reg = <0x0 0xff280000 0x0 0x100>; @@ -644,7 +662,7 @@ clock-names = "tsadc", "apb_pclk"; assigned-clocks = <&cru SCLK_TSADC>; assigned-clock-rates = <50000>; - resets = <&cru SRST_TSADC_P>; + resets = <&cru SRST_TSADC>; reset-names = "tsadc-apb"; pinctrl-names = "init", "default", "sleep"; pinctrl-0 = <&tsadc_otp_gpio>; From d97eb29a355d98743b5a57d6d0e421959c19e62e Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 18:42:49 +0800 Subject: [PATCH 258/427] hid/hid-rkvr: fix compile warning drivers/hid/hid-rkvr.c:780:3: warning: memcpy writing 9 bytes into a region of size 1 overflows the destination [-Wstringop-overflow=] Change-Id: If4859756f19cb692bcc3584ff707c135749e73e4 Signed-off-by: Tao Huang --- drivers/hid/hid-rkvr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-rkvr.c b/drivers/hid/hid-rkvr.c index f37c03c6485c..e38d38620f10 100644 --- a/drivers/hid/hid-rkvr.c +++ b/drivers/hid/hid-rkvr.c @@ -769,8 +769,8 @@ static int hid_report_readreg(struct device *dev, u8 reg, u8 *data, int len) struct hid_device *hid = container_of(dev, struct hid_device, dev); unsigned char report_number = reg; unsigned char report_type = HID_REGR_REPORT; - char buf[1 + sizeof(data) * len]; - int readlen = 1 + sizeof(data) * len; + char buf[1 + sizeof(*data) * len]; + int readlen = 1 + sizeof(*data) * len; int ret; ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, readlen, report_type, HID_REQ_GET_REPORT); From 27ba838b5e67ef9d8a27690b55d0c37113734172 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 18:51:10 +0800 Subject: [PATCH 259/427] power/rk817_charger: fix compile warning drivers/power/rk817_charger.c:735:2: warning: this else clause does not guard... [-Wmisleading-indentation] Change-Id: Ib65d2f54463c39d7fe9fd1dfb39a76035df05172 Signed-off-by: Tao Huang --- drivers/power/rk817_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/rk817_charger.c b/drivers/power/rk817_charger.c index 01fda7531a4c..c2c426e608f0 100644 --- a/drivers/power/rk817_charger.c +++ b/drivers/power/rk817_charger.c @@ -736,7 +736,7 @@ static void rk817_charge_set_chrg_finish_condition(struct rk817_charger *charge) rk817_charge_set_term_current_digital(charge, charge->chrg_finish_cur); - rk817_charge_set_chrg_term_mod(charge, charge->chrg_term_mode); + rk817_charge_set_chrg_term_mod(charge, charge->chrg_term_mode); } static int rk817_charge_online(struct rk817_charger *charge) From 02a3e3fc5e7abda3dd44b3c89c4318c16869e873 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 18:57:17 +0800 Subject: [PATCH 260/427] media/video/generic_sensor: fix compile warning drivers/media/video/generic_sensor.c:865:5: warning: this if clause does not guard... [-Wmisleading-indentation] Change-Id: Ic34e59cb45b28864ccc15f5c641cd6aedbff4dab Signed-off-by: Tao Huang --- drivers/media/video/generic_sensor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/generic_sensor.c b/drivers/media/video/generic_sensor.c index 19ebedddaf80..767076256fe5 100644 --- a/drivers/media/video/generic_sensor.c +++ b/drivers/media/video/generic_sensor.c @@ -865,7 +865,7 @@ int generic_sensor_init(struct v4l2_subdev *sd, u32 val) if (sensor->flash_off_timer.timer.function==NULL) sensor->flash_off_timer.timer.function = generic_flash_off_func; - sensor->info_priv.funmodule_state |= SENSOR_INIT_IS_OK; + sensor->info_priv.funmodule_state |= SENSOR_INIT_IS_OK; return 0; sensor_INIT_ERR: From c763c84a6240a0dd07fd971e048d8a3914b37865 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 19:20:38 +0800 Subject: [PATCH 261/427] media/video/rk30_camera_oneframe: fix compile warning drivers/media/video/rk30_camera_oneframe.c:2212:5: warning: this if clause does not guard... [-Wmisleading-indentation] Change-Id: Ie304d39082a84b322a15b8b74f5b24d9d394b4d7 Signed-off-by: Tao Huang --- drivers/media/video/rk30_camera_oneframe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/rk30_camera_oneframe.c b/drivers/media/video/rk30_camera_oneframe.c index 337c3df97d85..d13f3c6184d7 100644 --- a/drivers/media/video/rk30_camera_oneframe.c +++ b/drivers/media/video/rk30_camera_oneframe.c @@ -2208,9 +2208,9 @@ static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx return 0; } - ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample); - if (ret < 0) - return 0; + ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample); + if (ret < 0) + return 0; switch (code) { case MEDIA_BUS_FMT_UYVY8_2X8: From 6e1a9a5ca4a4c45983ecbaec229b0dc3f33a4715 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 19:22:12 +0800 Subject: [PATCH 262/427] video/rockchip/lcdc/rk3368_lcdc: fix compile warning drivers/video/rockchip/lcdc/rk3368_lcdc.c:2198:2: warning: this if clause does not guard... [-Wmisleading-indentation] Change-Id: I0cbd3ba10b891b67782b1a105eaac3d473e52527 Signed-off-by: Tao Huang --- drivers/video/rockchip/lcdc/rk3368_lcdc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/rockchip/lcdc/rk3368_lcdc.c b/drivers/video/rockchip/lcdc/rk3368_lcdc.c index f9903f7fcf69..7ddd64da896f 100644 --- a/drivers/video/rockchip/lcdc/rk3368_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3368_lcdc.c @@ -2200,8 +2200,8 @@ static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) dev_drv->trsm_ops && dev_drv->trsm_ops->enable) dev_drv->trsm_ops->enable(); - if (screen->init) - screen->init(); + if (screen->init) + screen->init(); /*if (!lcdc_dev->standby) lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN, v_STANDBY_EN(0));*/ From dcc52ea50ddeba0c8902ee22d7f984dd01bd3b59 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 19:23:13 +0800 Subject: [PATCH 263/427] video/rockchip/rk_fb: fix compile warning drivers/video/rockchip/rk_fb.c:4002:4: warning: this else clause does not guard... [-Wmisleading-indentation] Change-Id: I4c75dea72a2ebde8f1271334f91d5fd890274017 Signed-off-by: Tao Huang --- drivers/video/rockchip/rk_fb.c | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index b0b0878d44e6..45b9569d7ed7 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -4002,27 +4002,27 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi) else fb_par->ion_hdl = dev_drv_prmry->win[win_id_prmry]->area[0].ion_hdl; - fbi->screen_base = - ion_map_kernel(rk_fb->ion_client, - fb_par->ion_hdl); - dev_drv->win[win_id]->area[0].ion_hdl = - fb_par->ion_hdl; - if (dev_drv->mmu_dev) - ret = ion_map_iommu(dev_drv->dev, - rk_fb->ion_client, - fb_par->ion_hdl, - (unsigned long *)&phy_addr, - (unsigned long *)&len); - else - ret = ion_phys(rk_fb->ion_client, - fb_par->ion_hdl, - &phy_addr, &len); - if (ret < 0) { - dev_err(fbi->dev, "ion map to get phy addr failed\n"); - return -ENOMEM; - } - fbi->fix.smem_start = phy_addr; - fbi->fix.smem_len = len; + fbi->screen_base = + ion_map_kernel(rk_fb->ion_client, + fb_par->ion_hdl); + dev_drv->win[win_id]->area[0].ion_hdl = + fb_par->ion_hdl; + if (dev_drv->mmu_dev) + ret = ion_map_iommu(dev_drv->dev, + rk_fb->ion_client, + fb_par->ion_hdl, + (unsigned long *)&phy_addr, + (unsigned long *)&len); + else + ret = ion_phys(rk_fb->ion_client, + fb_par->ion_hdl, + &phy_addr, &len); + if (ret < 0) { + dev_err(fbi->dev, "ion map to get phy addr failed\n"); + return -ENOMEM; + } + fbi->fix.smem_start = phy_addr; + fbi->fix.smem_len = len; #else fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size, From f6128506aaa966101123635e95c2b15a9bf4dd52 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 7 Feb 2018 17:42:14 +0800 Subject: [PATCH 264/427] clk: rockchip: px30: Fix i2s out mclk Change-Id: I1f90747c780c867e172168e8c877915477a66e59 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index a6d6492821be..98cd4e80a99b 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -640,9 +640,11 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_NODIV(SCLK_I2S0_TX, "clk_i2s0_tx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(28), 12, 1, MFLAGS, PX30_CLKGATE_CON(9), 14, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S0_TX_OUT, "clk_i2s0_tx_out", mux_i2s0_tx_out_p, 0, + COMPOSITE_NODIV(0, "clk_i2s0_tx_out_pre", mux_i2s0_tx_out_p, 0, PX30_CLKSEL_CON(28), 14, 2, MFLAGS, PX30_CLKGATE_CON(9), 15, GFLAGS), + GATE(SCLK_I2S0_TX_OUT, "clk_i2s0_tx_out", "clk_i2s0_tx_out_pre", CLK_SET_RATE_PARENT, + PX30_CLKGATE_CON(10), 8, CLK_GATE_HIWORD_MASK), COMPOSITE(0, "clk_i2s0_rx_src", mux_gpll_npll_p, 0, PX30_CLKSEL_CON(58), 8, 1, MFLAGS, 0, 7, DFLAGS, @@ -654,9 +656,11 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(58), 12, 1, MFLAGS, PX30_CLKGATE_CON(17), 2, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S0_RX_OUT, "clk_i2s0_rx_out", mux_i2s0_rx_out_p, 0, + COMPOSITE_NODIV(0, "clk_i2s0_rx_out_pre", mux_i2s0_rx_out_p, 0, PX30_CLKSEL_CON(58), 14, 2, MFLAGS, PX30_CLKGATE_CON(17), 3, GFLAGS), + GATE(SCLK_I2S0_RX_OUT, "clk_i2s0_rx_out", "clk_i2s0_rx_out_pre", CLK_SET_RATE_PARENT, + PX30_CLKGATE_CON(10), 11, CLK_GATE_HIWORD_MASK), COMPOSITE(0, "clk_i2s1_src", mux_gpll_npll_p, 0, PX30_CLKSEL_CON(30), 8, 1, MFLAGS, 0, 7, DFLAGS, @@ -667,9 +671,11 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { &px30_i2s1_fracmux), GATE(SCLK_I2S1, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT, PX30_CLKGATE_CON(10), 2, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S1_OUT, "clk_i2s1_out", mux_i2s1_out_p, 0, + COMPOSITE_NODIV(SCLK_I2S1_OUT, "clk_i2s1_out_pre", mux_i2s1_out_p, 0, PX30_CLKSEL_CON(30), 15, 1, MFLAGS, PX30_CLKGATE_CON(10), 3, GFLAGS), + GATE(SCLK_I2S1_OUT, "clk_i2s1_out", "clk_i2s1_out_pre", CLK_SET_RATE_PARENT, + PX30_CLKGATE_CON(10), 9, CLK_GATE_HIWORD_MASK), COMPOSITE(0, "clk_i2s2_src", mux_gpll_npll_p, 0, PX30_CLKSEL_CON(32), 8, 1, MFLAGS, 0, 7, DFLAGS, @@ -680,9 +686,11 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { &px30_i2s2_fracmux), GATE(SCLK_I2S2, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT, PX30_CLKGATE_CON(10), 6, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S2_OUT, "clk_i2s2_out", mux_i2s2_out_p, 0, + COMPOSITE_NODIV(0, "clk_i2s2_out_pre", mux_i2s2_out_p, 0, PX30_CLKSEL_CON(32), 15, 1, MFLAGS, PX30_CLKGATE_CON(10), 7, GFLAGS), + GATE(SCLK_I2S2_OUT, "clk_i2s2_out", "clk_i2s2_out_pre", CLK_SET_RATE_PARENT, + PX30_CLKGATE_CON(10), 10, CLK_GATE_HIWORD_MASK), COMPOSITE(0, "clk_uart1_src", mux_uart_src_p, 0, PX30_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 5, DFLAGS, From 8590206686cf4c953d60d9b6d8e2f1b5dbd39233 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 18:47:09 +0800 Subject: [PATCH 265/427] mfd/fusb302: fix compile warning drivers/mfd/fusb302.c:1164:3: warning: memset used with length equal to number of elements without multiplication by element size [-Wmemset-elt-size] Change-Id: I33ac6408bc4cee656c7f18948d418527619b3d6b Signed-off-by: Tao Huang --- drivers/mfd/fusb302.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/fusb302.c b/drivers/mfd/fusb302.c index f95b8851445d..4f5b1abd282b 100644 --- a/drivers/mfd/fusb302.c +++ b/drivers/mfd/fusb302.c @@ -1161,7 +1161,7 @@ static int vdm_send_discoverysvid(struct fusb30x_chip *chip, int evt) switch (chip->vdm_send_state) { case 0: set_vdm_mesg(chip, VDM_DISCOVERY_SVIDS, VDM_TYPE_INIT, 0); - memset(chip->vdm_svid, 0, 12); + memset(chip->vdm_svid, 0, sizeof(chip->vdm_svid)); chip->vdm_svid_num = 0; chip->tx_state = 0; chip->vdm_send_state++; From a442d86da800d5e82202036ba54b79e890915d5c Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 7 Feb 2018 21:21:54 +0800 Subject: [PATCH 266/427] drm/rockchip: px30 vop: not support ymirror and add channel config Change-Id: Ia89b6d5fde3b191b82e81c1399f82689267a629a Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 750551d8c486..cd90ddcb74c4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1466,7 +1466,6 @@ static const struct vop_win_phy px30_win23_data = { .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), - .ymirror = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15), .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), @@ -1475,6 +1474,7 @@ static const struct vop_win_phy px30_win23_data = { .alpha_mode = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 0), .global_alpha_val = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 4), + .channel = VOP_REG(RK3368_WIN2_CTRL1, 0xff, 8), }; static const struct vop_win_data px30_vop_big_win_data[] = { From 491f6e8e936d38c17d143a2c0be60a0b54fe492b Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 7 Feb 2018 20:58:10 +0800 Subject: [PATCH 267/427] arm64: dts: rockchip: add pstore for px30-android Change-Id: I2e12f234244eb45e24d1f38841eef7017ae8cfd4 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-android.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index 919b94bc3132..4c08d71b1fc7 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -55,6 +55,20 @@ reg = <0x0 0x0 0x0 0x0>; }; }; + + ramoops_mem: ramoops_mem { + reg = <0x0 0x110000 0x0 0xf0000>; + reg-names = "ramoops_mem"; + }; + + ramoops { + compatible = "ramoops"; + record-size = <0x0 0x20000>; + console-size = <0x0 0x80000>; + ftrace-size = <0x0 0x00000>; + pmsg-size = <0x0 0x50000>; + memory-region = <&ramoops_mem>; + }; }; &display_subsystem { From deacb7ed8d8d600c2e31bd4375d0cb2681bc184f Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Wed, 7 Feb 2018 22:32:07 +0800 Subject: [PATCH 268/427] arm64: dts: rockchip: px30: Correct sdio irq number and add iomux Change-Id: Id61aece26f7c9e612a332ed8d0342693a4cc3b6a Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30.dtsi | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 1920f16ef56a..0739bc773ae2 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -879,7 +879,7 @@ clock-names = "biu", "ciu"; power-domains = <&power PX30_PD_SDCARD>; fifo-depth = <0x100>; - interrupts = ; + interrupts = ; status = "disabled"; }; @@ -892,7 +892,9 @@ clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; power-domains = <&power PX30_PD_MMC_NAND>; fifo-depth = <0x100>; - interrupts = ; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&sdio_bus4 &sdio_cmd &sdio_clk>; status = "disabled"; }; @@ -2363,5 +2365,25 @@ rockchip,pins = <3 RK_PD1 RK_FUNC_4 &pcfg_pull_none>;/* ISP_PRELIGHTTRIG */ }; }; + + sdio { + sdio_bus4: sdio-bus4 { + rockchip,pins = + <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PC7 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PD0 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PD1 RK_FUNC_1 &pcfg_pull_up>; + }; + + sdio_cmd: sdio-cmd { + rockchip,pins = + <1 RK_PC4 RK_FUNC_1 &pcfg_pull_up>; + }; + + sdio_clk: sdio-clk { + rockchip,pins = + <1 RK_PC5 RK_FUNC_1 &pcfg_pull_none>; + }; + }; }; }; From b48da90f720f822aedcef8e6e46308c3d0bfcead Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Wed, 7 Feb 2018 22:38:30 +0800 Subject: [PATCH 269/427] arm64: dts: rockchip: add wifi power control for rk3326-863-lp3-v10 Change-Id: Ic5dd468ade0c165c14d80530f3bba43979c785a0 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index ea000c3d9f5b..85d598f5012a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -105,6 +105,7 @@ compatible = "wlan-platdata"; wifi_chip_type = "rtl8723cs"; WIFI,host_wake_irq = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; + WIFI,vbat_gpio = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>; status = "okay"; }; From adbf52abda3c6a7a1efc66a8c7412d53ce7d1717 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 5 Feb 2018 15:38:17 +0800 Subject: [PATCH 270/427] clk: rockchip: rk3228: add clk_ddrc for devfreq of ddr Change-Id: I3771e2ef68ab3fa8ad1b7d61a84c7181c693c60f Signed-off-by: Liang Chen --- drivers/clk/rockchip/clk-rk3228.c | 13 +++++-------- include/dt-bindings/clock/rk3228-cru.h | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index ba278f4ebdfc..26788c075bab 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -222,15 +222,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), /* PD_DDR */ - COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, - RK2928_CLKGATE_CON(0), 2, GFLAGS), - GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED, + COMPOSITE_DDRCLK(SCLK_DDRC, "clk_ddrc", mux_ddrphy_p, 0, + RK2928_CLKSEL_CON(26), 8, 2, 0, 2, + ROCKCHIP_DDRCLK_SIP_V2), + FACTOR(0, "clk_ddrphy", "clk_ddrc", 0, 1, 4), + GATE(0, "ddrphy4x", "clk_ddrc", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 1, GFLAGS), - FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, - RK2928_CLKGATE_CON(8), 5, GFLAGS), - FACTOR_GATE(0, "ddrphy", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, - RK2928_CLKGATE_CON(7), 0, GFLAGS), /* PD_CORE */ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index 9b2aaa3110cc..2f22a7b1538d 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -73,6 +73,7 @@ #define SCLK_WIFI 141 #define SCLK_OTGPHY0 142 #define SCLK_OTGPHY1 143 +#define SCLK_DDRC 144 /* dclk gates */ #define DCLK_VOP 190 From f06ee6308f5e6d3345ed890ac3b3ae4a5841af6a Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 5 Feb 2018 15:46:32 +0800 Subject: [PATCH 271/427] PM / devfreq: rockchip_dmc: add support for rk3228 Change-Id: I3943716a66b3c0849d815b7f69cc0bbd843d7e4e Signed-off-by: Liang Chen --- .../devicetree/bindings/devfreq/rockchip_dmc.txt | 1 + drivers/devfreq/rockchip_dmc.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt index aad0644cd7f4..23ac503752a8 100644 --- a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt +++ b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt @@ -3,6 +3,7 @@ Required properties: - compatible: Should be one of the following. - "rockchip,rk3128-dmc" - for RK3128 SoCs. + - "rockchip,rk3228-dmc" - for RK3228 SoCs. - "rockchip,rk3288-dmc" - for RK3288 SoCs. - "rockchip,rk3328-dmc" - for RK3328 SoCs. - "rockchip,rk3368-dmc" - for RK3368 SoCs. diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 8b3529e1ab64..784d1cc0b2e1 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -1337,6 +1337,17 @@ static int rk3128_dmc_init(struct platform_device *pdev, return 0; } +static int rk3228_dmc_init(struct platform_device *pdev, + struct rockchip_dmcfreq *dmcfreq) +{ + /* + * dmc_init have been done in uboot. + */ + dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh; + + return 0; +} + static int rk3288_dmc_init(struct platform_device *pdev, struct rockchip_dmcfreq *dmcfreq) { @@ -1596,6 +1607,7 @@ static int rk3399_dmc_init(struct platform_device *pdev) static const struct of_device_id rockchip_dmcfreq_of_match[] = { { .compatible = "rockchip,rk3128-dmc", .data = rk3128_dmc_init }, + { .compatible = "rockchip,rk3228-dmc", .data = rk3228_dmc_init }, { .compatible = "rockchip,rk3288-dmc", .data = rk3288_dmc_init }, { .compatible = "rockchip,rk3328-dmc", .data = rk3328_dmc_init }, { .compatible = "rockchip,rk3368-dmc", .data = rk3368_dmc_init }, From d826c69c4d33d8e3734c163e1f5a04f50b47fa84 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 5 Feb 2018 15:55:19 +0800 Subject: [PATCH 272/427] arm: dts: add dmc support for rk322x Change-Id: Ibf72cb8d2e26490386212d564309f5b85692105a Signed-off-by: Liang Chen --- .../boot/dts/rk322x-dram-default-timing.dtsi | 35 ++++++++ arch/arm/boot/dts/rk322x.dtsi | 47 ++++++++++ include/dt-bindings/dram/rockchip,rk322x.h | 90 +++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 arch/arm/boot/dts/rk322x-dram-default-timing.dtsi create mode 100644 include/dt-bindings/dram/rockchip,rk322x.h diff --git a/arch/arm/boot/dts/rk322x-dram-default-timing.dtsi b/arch/arm/boot/dts/rk322x-dram-default-timing.dtsi new file mode 100644 index 000000000000..cd5d080ed732 --- /dev/null +++ b/arch/arm/boot/dts/rk322x-dram-default-timing.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#include +#include + +/ { + dram_timing: dram_timing { + compatible = "rockchip,dram-timing"; + dram_spd_bin = ; + sr_idle = <0x18>; + pd_idle = <0x20>; + dram_dll_disb_freq = <300>; + phy_dll_disb_freq = <400>; + dram_odt_disb_freq = <333>; + phy_odt_disb_freq = <333>; + ddr3_drv = ; + ddr3_odt = ; + lpddr3_drv = ; + lpddr3_odt = ; + lpddr2_drv = ; + /* lpddr2 not supported odt */ + phy_ddr3_clk_drv = ; + phy_ddr3_cmd_drv = ; + phy_ddr3_dqs_drv = ; + phy_ddr3_odt = ; + phy_lp23_clk_drv = ; + phy_lp23_cmd_drv = ; + phy_lp23_dqs_drv = ; + phy_lp3_odt = ; + }; +}; diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 7f7fd952c415..d03bf7c656d5 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include "skeleton.dtsi" / { @@ -158,6 +160,51 @@ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; }; + dmc: dmc { + compatible = "rockchip,rk3228-dmc", "rockchip,rk322x-dram"; + clocks = <&cru SCLK_DDRC>; + clock-names = "dmc_clk"; + operating-points-v2 = <&dmc_opp_table>; + system-status-freq = < + /*system status freq(KHz)*/ + SYS_STATUS_NORMAL 400000 + SYS_STATUS_VIDEO_4K 600000 + SYS_STATUS_VIDEO_4K_10B 786000 + >; + dram_freq = <786000000>; + rockchip,dram_timing = <&dram_timing>; + status = "disabled"; + }; + + dmc_opp_table: dmc-opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <1050000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1050000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1050000>; + }; + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <1100000>; + }; + opp-786000000 { + opp-hz = /bits/ 64 <786000000>; + opp-microvolt = <1150000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1150000>; + }; + }; + timer { compatible = "arm,armv7-timer"; arm,cpu-registers-not-fw-configured; diff --git a/include/dt-bindings/dram/rockchip,rk322x.h b/include/dt-bindings/dram/rockchip,rk322x.h new file mode 100644 index 000000000000..1ab3317d700e --- /dev/null +++ b/include/dt-bindings/dram/rockchip,rk322x.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DT_BINDINGS_DRAM_ROCKCHIP_RK322X_H +#define _DT_BINDINGS_DRAM_ROCKCHIP_RK322X_H + +#define DDR3_DS_34ohm (1 << 1) +#define DDR3_DS_40ohm (0x0) + +#define LP2_DS_34ohm (0x1) +#define LP2_DS_40ohm (0x2) +#define LP2_DS_48ohm (0x3) +#define LP2_DS_60ohm (0x4) +#define LP2_DS_68_6ohm (0x5)/* optional */ +#define LP2_DS_80ohm (0x6) +#define LP2_DS_120ohm (0x7)/* optional */ + +#define LP3_DS_34ohm (0x1) +#define LP3_DS_40ohm (0x2) +#define LP3_DS_48ohm (0x3) +#define LP3_DS_60ohm (0x4) +#define LP3_DS_80ohm (0x6) +#define LP3_DS_34D_40U (0x9) +#define LP3_DS_40D_48U (0xa) +#define LP3_DS_34D_48U (0xb) + +#define DDR3_ODT_DIS (0) +#define DDR3_ODT_40ohm ((1 << 2) | (1 << 6)) +#define DDR3_ODT_60ohm (1 << 2) +#define DDR3_ODT_120ohm (1 << 6) + +#define LP3_ODT_DIS (0) +#define LP3_ODT_60ohm (1) +#define LP3_ODT_120ohm (2) +#define LP3_ODT_240ohm (3) + +#define PHY_DDR3_RON_RTT_DISABLE (0) +#define PHY_DDR3_RON_RTT_451ohm (1) +#define PHY_DDR3_RON_RTT_225ohm (2) +#define PHY_DDR3_RON_RTT_150ohm (3) +#define PHY_DDR3_RON_RTT_112ohm (4) +#define PHY_DDR3_RON_RTT_90ohm (5) +#define PHY_DDR3_RON_RTT_75ohm (6) +#define PHY_DDR3_RON_RTT_64ohm (7) +#define PHY_DDR3_RON_RTT_56ohm (16) +#define PHY_DDR3_RON_RTT_50ohm (17) +#define PHY_DDR3_RON_RTT_45ohm (18) +#define PHY_DDR3_RON_RTT_41ohm (19) +#define PHY_DDR3_RON_RTT_37ohm (20) +#define PHY_DDR3_RON_RTT_34ohm (21) +#define PHY_DDR3_RON_RTT_33ohm (22) +#define PHY_DDR3_RON_RTT_30ohm (23) +#define PHY_DDR3_RON_RTT_28ohm (24) +#define PHY_DDR3_RON_RTT_26ohm (25) +#define PHY_DDR3_RON_RTT_25ohm (26) +#define PHY_DDR3_RON_RTT_23ohm (27) +#define PHY_DDR3_RON_RTT_22ohm (28) +#define PHY_DDR3_RON_RTT_21ohm (29) +#define PHY_DDR3_RON_RTT_20ohm (30) +#define PHY_DDR3_RON_RTT_19ohm (31) + +#define PHY_LP23_RON_RTT_DISABLE (0) +#define PHY_LP23_RON_RTT_480ohm (1) +#define PHY_LP23_RON_RTT_240ohm (2) +#define PHY_LP23_RON_RTT_160ohm (3) +#define PHY_LP23_RON_RTT_120ohm (4) +#define PHY_LP23_RON_RTT_96ohm (5) +#define PHY_LP23_RON_RTT_80ohm (6) +#define PHY_LP23_RON_RTT_68ohm (7) +#define PHY_LP23_RON_RTT_60ohm (16) +#define PHY_LP23_RON_RTT_53ohm (17) +#define PHY_LP23_RON_RTT_48ohm (18) +#define PHY_LP23_RON_RTT_43ohm (19) +#define PHY_LP23_RON_RTT_40ohm (20) +#define PHY_LP23_RON_RTT_37ohm (21) +#define PHY_LP23_RON_RTT_34ohm (22) +#define PHY_LP23_RON_RTT_32ohm (23) +#define PHY_LP23_RON_RTT_30ohm (24) +#define PHY_LP23_RON_RTT_28ohm (25) +#define PHY_LP23_RON_RTT_26ohm (26) +#define PHY_LP23_RON_RTT_25ohm (27) +#define PHY_LP23_RON_RTT_24ohm (28) +#define PHY_LP23_RON_RTT_22ohm (29) +#define PHY_LP23_RON_RTT_21ohm (30) +#define PHY_LP23_RON_RTT_20ohm (31) + +#endif /* _DT_BINDINGS_DRAM_ROCKCHIP_RK322X_H */ From 069bbc18e7696280006991de3ce924463d36c42c Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 5 Feb 2018 16:01:38 +0800 Subject: [PATCH 273/427] arm: dts: enable dmc for board rk3229-evb-android Change-Id: I9abf24d165e236d1895efc04336982c2ce81c013 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk3229-evb-android.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/rk3229-evb-android.dts b/arch/arm/boot/dts/rk3229-evb-android.dts index e4f70cfc1e57..dab8caec98f9 100644 --- a/arch/arm/boot/dts/rk3229-evb-android.dts +++ b/arch/arm/boot/dts/rk3229-evb-android.dts @@ -178,6 +178,11 @@ }; }; +&dmc { + center-supply = <&vdd_log>; + status = "okay"; +}; + &gmac { assigned-clocks = <&cru SCLK_MAC_SRC>; assigned-clock-rates = <50000000>; From 3aa3d78ce1f981acd26346417736692b4b1f0e21 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 1 Feb 2018 17:37:54 +0800 Subject: [PATCH 274/427] PM / devfreq: rockchip_dmc: Disable auto-freq if events is disabled Change-Id: Ia39dfc884feea8cb6c29a7ed293bb567aca15b83 Signed-off-by: Finley Xiao --- drivers/devfreq/rockchip_dmc.c | 66 ++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 784d1cc0b2e1..7710925acc85 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -873,10 +873,12 @@ static __maybe_unused int rockchip_dmcfreq_suspend(struct device *dev) struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); int ret = 0; - ret = devfreq_event_disable_edev(dmcfreq->edev); - if (ret < 0) { - dev_err(dev, "failed to disable the devfreq-event devices\n"); - return ret; + if (dmcfreq->edev) { + ret = devfreq_event_disable_edev(dmcfreq->edev); + if (ret < 0) { + dev_err(dev, "failed to disable the devfreq-event devices\n"); + return ret; + } } ret = devfreq_suspend_device(dmcfreq->devfreq); @@ -893,10 +895,12 @@ static __maybe_unused int rockchip_dmcfreq_resume(struct device *dev) struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); int ret = 0; - ret = devfreq_event_enable_edev(dmcfreq->edev); - if (ret < 0) { - dev_err(dev, "failed to enable the devfreq-event devices\n"); - return ret; + if (dmcfreq->edev) { + ret = devfreq_event_enable_edev(dmcfreq->edev); + if (ret < 0) { + dev_err(dev, "failed to enable the devfreq-event devices\n"); + return ret; + } } ret = devfreq_resume_device(dmcfreq->devfreq); @@ -1757,7 +1761,6 @@ static int rockchip_dmcfreq_system_status_notifier(struct notifier_block *nb, void *ptr) { struct rockchip_dmcfreq *dmcfreq = system_status_to_dmcfreq(nb); - struct devfreq *df = dmcfreq->devfreq; unsigned long target_rate = 0; unsigned int refresh = false; bool is_dualview = false; @@ -1821,7 +1824,7 @@ static int rockchip_dmcfreq_system_status_notifier(struct notifier_block *nb, next: - dev_dbg(&df->dev, "status=0x%x\n", (unsigned int)status); + dev_dbg(&dmcfreq->devfreq->dev, "status=0x%x\n", (unsigned int)status); dmcfreq->refresh = refresh; dmcfreq->is_dualview = is_dualview; dmcfreq->status_rate = target_rate; @@ -2130,11 +2133,11 @@ static int devfreq_dmc_ondemand_func(struct devfreq *df, int err; struct devfreq_dev_status *stat; unsigned long long a, b; - struct devfreq_simple_ondemand_data *data = df->data; - unsigned int upthreshold = data->upthreshold; - unsigned int downdifferential = data->downdifferential; unsigned long max_freq = (df->max_freq) ? df->max_freq : UINT_MAX; struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(df->dev.parent); + struct devfreq_simple_ondemand_data *data = &dmcfreq->ondemand_data; + unsigned int upthreshold = data->upthreshold; + unsigned int downdifferential = data->downdifferential; unsigned long target_freq = 0; if (dmcfreq->auto_freq_en && !dmcfreq->is_dualview) { @@ -2223,10 +2226,11 @@ static int devfreq_dmc_ondemand_handler(struct devfreq *devfreq, { struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(devfreq->dev.parent); + if (!dmcfreq->auto_freq_en) + return 0; + switch (event) { case DEVFREQ_GOV_START: - if (!devfreq->data) - devfreq->data = &dmcfreq->ondemand_data; devfreq_monitor_start(devfreq); break; @@ -2361,7 +2365,7 @@ static int ddr_power_model_simple_init(struct rockchip_dmcfreq *dmcfreq) static int rockchip_dmcfreq_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = pdev->dev.of_node; + struct device_node *events_np, *np = pdev->dev.of_node; struct rockchip_dmcfreq *data; struct devfreq_dev_profile *devp = &rockchip_devfreq_dmc_profile; const struct of_device_id *match; @@ -2369,6 +2373,7 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) struct rockchip_dmcfreq *data); #define MAX_PROP_NAME_LEN 3 char name[MAX_PROP_NAME_LEN]; + bool is_events_available = false; int lkg_volt_sel; int ret; @@ -2391,14 +2396,19 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) return PTR_ERR(data->dmc_clk); } - data->edev = devfreq_event_get_edev_by_phandle(dev, 0); - if (IS_ERR(data->edev)) - return -EPROBE_DEFER; + events_np = of_parse_phandle(np, "devfreq-events", 0); + if (events_np && of_device_is_available(events_np)) { + of_node_put(events_np); + data->edev = devfreq_event_get_edev_by_phandle(dev, 0); + if (IS_ERR(data->edev)) + return -EPROBE_DEFER; - ret = devfreq_event_enable_edev(data->edev); - if (ret < 0) { - dev_err(dev, "failed to enable devfreq-event devices\n"); - return ret; + ret = devfreq_event_enable_edev(data->edev); + if (ret < 0) { + dev_err(dev, "failed to enable devfreq-event devices\n"); + return ret; + } + is_events_available = true; } match = of_match_node(rockchip_dmcfreq_of_match, pdev->dev.of_node); @@ -2439,6 +2449,10 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) if (rockchip_get_system_status_rate(np, "system-status-freq", data)) dev_err(dev, "failed to get system status rate\n"); of_property_read_u32(np, "auto-freq-en", &data->auto_freq_en); + if (!is_events_available && data->auto_freq_en) { + dev_warn(dev, "events isn't available, close auto freq\n"); + data->auto_freq_en = 0; + } of_property_read_u32(np, "auto-min-freq", (u32 *)&data->auto_min_rate); data->auto_min_rate *= 1000; if (rockchip_get_freq_map_talbe(np, "vop-bw-dmc-freq", @@ -2456,6 +2470,9 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) return ret; } + data->dev = dev; + platform_set_drvdata(pdev, data); + data->devfreq = devm_devfreq_add_device(dev, devp, "dmc_ondemand", &data->ondemand_data); @@ -2471,9 +2488,6 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) data->devfreq->last_status.current_frequency = data->rate; reset_last_status(data->devfreq); - data->dev = dev; - platform_set_drvdata(pdev, data); - if (rockchip_drm_register_notifier_to_dmc(data->devfreq)) dev_err(dev, "drm fail to register notifier to dmc\n"); From ae5b1c4df1a48f275f78f1d08de9462c6aec886f Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Mon, 5 Feb 2018 19:00:48 +0800 Subject: [PATCH 275/427] arm: dts: rockchip: add dmc thermal control for rk322x add power model for dmc and add dmc as a cooling device in thermal control Change-Id: Ibc5f8ec97b43d4fcf9ff817582711b924d2a7ef0 Signed-off-by: Rocky Hao --- arch/arm/boot/dts/rk322x.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index d03bf7c656d5..790226c01977 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -173,7 +173,16 @@ >; dram_freq = <786000000>; rockchip,dram_timing = <&dram_timing>; + #cooling-cells = <2>; status = "disabled"; + + ddr_power_model: ddr_power_model { + compatible = "ddr_power_model"; + dynamic-power-coefficient = <120>; + static-power-coefficient = <200>; + ts = <32000 4700 (-80) 2>; + thermal-zone = "soc-thermal"; + }; }; dmc_opp_table: dmc-opp-table { @@ -617,6 +626,12 @@ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; contribution = <1024>; }; + map2 { + trip = <&target>; + cooling-device = + <&dmc THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + contribution = <1024>; + }; }; }; }; From f417571488bb393278a8ac8378de186b56833fc9 Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Tue, 6 Feb 2018 17:01:55 +0800 Subject: [PATCH 276/427] PM / devfreq: rockchip_dmc: record opp rate instead of real clock rate opp rate is used to calc power in thermal framework, so we record this rate instead of real clock rate. Change-Id: Ic51a8c36be8d63fcf765e6d49930d1d437a2e502 Signed-off-by: Rocky Hao --- drivers/devfreq/rockchip_dmc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 7710925acc85..69b57982e7e1 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -705,7 +705,7 @@ static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq, struct dev_pm_opp *opp; struct cpufreq_policy *policy; unsigned long old_clk_rate = dmcfreq->rate; - unsigned long temp_rate, target_volt, target_rate; + unsigned long opp_rate, target_volt, target_rate; unsigned int cpu_cur, cpufreq_cur; int err = 0; @@ -716,14 +716,14 @@ static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq, rcu_read_unlock(); return PTR_ERR(opp); } - temp_rate = dev_pm_opp_get_freq(opp); + opp_rate = dev_pm_opp_get_freq(opp); target_volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); - target_rate = clk_round_rate(dmcfreq->dmc_clk, temp_rate); + target_rate = clk_round_rate(dmcfreq->dmc_clk, opp_rate); if ((long)target_rate <= 0) - target_rate = temp_rate; + target_rate = opp_rate; if (dmcfreq->rate == target_rate) { if (dmcfreq->volt == target_volt) @@ -804,7 +804,6 @@ static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq, * 2. Ddr frequency scaling sucessful, we get the rate we set. */ dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); - dmcfreq->devfreq->last_status.current_frequency = dmcfreq->rate; /* If get the incorrect rate, set voltage to old value. */ if (dmcfreq->rate != target_rate) { @@ -822,6 +821,8 @@ static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq, } } + dmcfreq->devfreq->last_status.current_frequency = opp_rate; + dmcfreq->volt = target_volt; out: __cpufreq_driver_target(policy, cpufreq_cur, CPUFREQ_RELATION_L); @@ -844,7 +845,6 @@ static int rockchip_dmcfreq_get_dev_status(struct device *dev, if (ret < 0) return ret; - stat->current_frequency = dmcfreq->rate; stat->busy_time = edata.load_count; stat->total_time = edata.total_count; From 628c1aeb34ddf0c1b6bac9f2a07891cfbf83e75e Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 8 Feb 2018 11:32:15 +0800 Subject: [PATCH 277/427] arm64: dts: rockchip: enable cdn DP for rk3399 sapphire As we had posted the DP firmeware to /lib/firmware/rockchip, so you need check this path in your rootfs first, if enable the DP. Change-Id: Id24a42edc9d6cd0b0de0a2dfefe2727df3965b67 Signed-off-by: Caesar Wang --- arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi index cfd08f030dab..8e4b9e6141b5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi @@ -192,6 +192,12 @@ }; }; +&cdn_dp { + status = "okay"; + extcon = <&fusb0>; + phys = <&tcphy0_dp>; +}; + &cpu_l0 { cpu-supply = <&vdd_cpu_l>; }; From e2e86394f60019bcb2b0f271ff05b6b023821dc3 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 8 Feb 2018 11:39:42 +0800 Subject: [PATCH 278/427] arm64: rockchip_linux_config: enable the cdn DP Change-Id: I2b9812be9a33b31e7b9e9531f5c1acd2c8dc53a2 Signed-off-by: Caesar Wang --- arch/arm64/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index e88c8ebc8375..a01953c4dcc7 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -301,6 +301,7 @@ CONFIG_DRM=y CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_DMA_SYNC=y CONFIG_DRM_ROCKCHIP=y +CONFIG_ROCKCHIP_CDN_DP=y CONFIG_ROCKCHIP_DW_HDMI=y CONFIG_ROCKCHIP_DW_MIPI_DSI=y CONFIG_ROCKCHIP_ANALOGIX_DP=y From 8ee4287ff71888de2035f485e6e564cc45d1ebfe Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 8 Feb 2018 11:25:32 +0800 Subject: [PATCH 279/427] clk: rockchip: px30: Make pclk_top_pre critical Change-Id: I86081f6dbd85ab36e0e83b5b22fdd7b686a2cf9d Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 98cd4e80a99b..0b44a2c36d36 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -1016,6 +1016,7 @@ static const char *const px30_critical_clocks[] __initconst = { "hclk_peri_pre", "aclk_gpu_niu", "clk_gpu_divnp5", + "pclk_top_pre", }; static const char *const px30_pmucru_critical_clocks[] __initconst = { From 65c32d2028c8b1fdddc21453638ec744257a3a54 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Thu, 8 Feb 2018 10:52:03 +0800 Subject: [PATCH 280/427] arm64: dts: rockchip: px30: add default pinctrl for i2s, pdm Change-Id: I5cf7436e65c04a30cc3ef4c89ee49e1e76ef0527 Signed-off-by: Sugar Zhang --- arch/arm64/boot/dts/rockchip/px30.dtsi | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 0739bc773ae2..98567c96ca17 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -289,6 +289,19 @@ clock-names = "i2s_clk", "i2s_hclk"; dmas = <&dmac 16>, <&dmac 17>; dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_8ch_sclktx + &i2s0_8ch_sclkrx + &i2s0_8ch_lrcktx + &i2s0_8ch_lrckrx + &i2s0_8ch_sdi0 + &i2s0_8ch_sdi1 + &i2s0_8ch_sdi2 + &i2s0_8ch_sdi3 + &i2s0_8ch_sdo0 + &i2s0_8ch_sdo1 + &i2s0_8ch_sdo2 + &i2s0_8ch_sdo3>; status = "disabled"; }; @@ -300,6 +313,11 @@ clock-names = "i2s_clk", "i2s_hclk"; dmas = <&dmac 18>, <&dmac 19>; dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_sclk + &i2s1_2ch_lrck + &i2s1_2ch_sdi + &i2s1_2ch_sdo>; status = "disabled"; }; @@ -311,6 +329,11 @@ clock-names = "i2s_clk", "i2s_hclk"; dmas = <&dmac 20>, <&dmac 21>; dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s2_2ch_sclk + &i2s2_2ch_lrck + &i2s2_2ch_sdi + &i2s2_2ch_sdo>; status = "disabled"; }; @@ -321,6 +344,13 @@ clock-names = "pdm_clk", "pdm_hclk"; dmas = <&dmac 24>; dma-names = "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&pdm_clk0m0 + &pdm_clk1 + &pdm_sdi0m0 + &pdm_sdi1 + &pdm_sdi2 + &pdm_sdi3>; status = "disabled"; }; @@ -1793,11 +1823,6 @@ <3 RK_PB5 RK_FUNC_2 &pcfg_pull_none>; }; - i2s0_8ch_sdo: i2s0-8ch-sdo { - rockchip,pins = - <3 RK_PD2 RK_FUNC_3 &pcfg_pull_none>; - }; - i2s0_8ch_sdo0: i2s0-8ch-sdo0 { rockchip,pins = <3 RK_PC4 RK_FUNC_2 &pcfg_pull_none>; @@ -1818,11 +1843,6 @@ <3 RK_PB6 RK_FUNC_2 &pcfg_pull_none>; }; - i2s0_8ch_sdi: i2s0-8ch-sdi { - rockchip,pins = - <3 RK_PD3 RK_FUNC_3 &pcfg_pull_none>; - }; - i2s0_8ch_sdi0: i2s0-8ch-sdi0 { rockchip,pins = <3 RK_PC5 RK_FUNC_2 &pcfg_pull_none>; From 2c20095feac197ff487b55b9548a6e40768aca13 Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Thu, 8 Feb 2018 11:09:10 +0800 Subject: [PATCH 281/427] arm64: dts: rockchip: px30: add vip iommu node reference to vip node Change-Id: Ic2772881a47aeb25ff68e2a39f3895e40db70a42 Signed-off-by: Zhong Yichong --- arch/arm64/boot/dts/rockchip/px30.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 98567c96ca17..319f118ed6bb 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1193,6 +1193,7 @@ power-domains = <&power PX30_PD_VI>; pinctrl-names = "cif_pin_all"; pinctrl-0 = <&dvp_d2d9_m0>; + iommus = <&vip_mmu>; status = "disabled"; }; From 70d0347a0b49a0fef0be944f698609d0050cc8e7 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Thu, 8 Feb 2018 10:34:23 +0800 Subject: [PATCH 282/427] arm64: dts: rockchip: enable vip for rk3326 863 board Change-Id: Ied60270696bc0dfd0dc41937c1e24b289e6063f5 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/rk3326-863-cif-sensor.dtsi | 4 ++-- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-cif-sensor.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-863-cif-sensor.dtsi index 942458d11591..a01be378daa3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-cif-sensor.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-cif-sensor.dtsi @@ -12,7 +12,7 @@ gc2145_b { is_front = <0>; - powerdown-gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; pwdn_active = ; pwr_active = ; mir = <0>; @@ -28,7 +28,7 @@ gc0312_f { is_front = <1>; - powerdown-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>; pwdn_active = ; pwr_active = ; mir = <0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 85d598f5012a..dee77de7ebbd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -481,6 +481,10 @@ }; }; +&i2c2 { + status = "okay"; +}; + &io_domains { status = "okay"; @@ -585,6 +589,10 @@ status = "okay"; }; +&vip_mmu { + status = "okay"; +}; + &vopb { status = "okay"; }; From 92d992f480d4181ab548f60916daf82684c1e119 Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Thu, 8 Feb 2018 10:18:18 +0800 Subject: [PATCH 283/427] arm64: dts: rockchip: modified sensor layout of rk3326-evb-lp3-v10 board Change-Id: Ib8fbddaf02f0e3d77f230e6ff44f0613ff12d822 Signed-off-by: Zorro Liu --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 07483ebef83b..1d3b99554550 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -584,7 +584,7 @@ irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>; irq_enable = <0>; poll_delay_ms = <30>; - layout = <6>; + layout = <1>; reprobe_en = <1>; }; }; From 53d9e933bc78c7d28b92a7e723ee1b0cd00d69d7 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Thu, 8 Feb 2018 11:29:38 +0800 Subject: [PATCH 284/427] fiq_debugger: rockchip: deal with this_cpu and current_cpu are different If this cpu is not the same as current cpu, it means we don't use current cpu any more, and this cpu handles uart interrupt. So it is unnecessary to set uart interrupt to this cpu again. Change-Id: Ia454af96ee766dcbc8b22339652a4aa7eb229568 Signed-off-by: Huibin Hong --- drivers/staging/android/fiq_debugger/fiq_debugger.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c index be7ef2512610..98bfb26bbcea 100644 --- a/drivers/staging/android/fiq_debugger/fiq_debugger.c +++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c @@ -866,8 +866,7 @@ static bool fiq_debugger_handle_uart_interrupt(struct fiq_debugger_state *state, int count = 0; bool signal_helper = false; - if ((this_cpu != state->current_cpu) && - (cpu_online(state->current_cpu))) { + if (this_cpu != state->current_cpu) { if (state->in_fiq) return false; @@ -881,13 +880,10 @@ static bool fiq_debugger_handle_uart_interrupt(struct fiq_debugger_state *state, this_cpu); atomic_set(&state->unhandled_fiq_count, 0); - fiq_debugger_switch_cpu(state, this_cpu); + state->current_cpu = this_cpu; return false; } - if (this_cpu != state->current_cpu) - state->current_cpu = this_cpu; - state->in_fiq = true; while ((c = fiq_debugger_getc(state)) != FIQ_DEBUGGER_NO_CHAR) { From 326d6f59d100304787d710017c3439de20835f3f Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Mon, 5 Feb 2018 10:54:50 +0800 Subject: [PATCH 285/427] clk: rockchip: px30: Add SCLK_DDRCLK for dmc Change-Id: I03d6c18829f8895c28bbaef883e187304c48f9aa Signed-off-by: YouMin Chen --- drivers/clk/rockchip/clk-px30.c | 3 +++ include/dt-bindings/clock/px30-cru.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 0b44a2c36d36..0fdd71978fa5 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -369,6 +369,9 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(0), 7, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(0), 13, GFLAGS), + COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, + CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(2), 7, 1, 0, 3, + ROCKCHIP_DDRCLK_SIP_V2), COMPOSITE_NOGATE(0, "clk_ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(2), 7, 1, MFLAGS, 0, 3, DFLAGS), FACTOR_GATE(0, "clk_ddrphy1x", "clk_ddrphy4x", CLK_IGNORE_UNUSED, 1, 4, diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h index 0873db1498b4..ca6761ae29fb 100644 --- a/include/dt-bindings/clock/px30-cru.h +++ b/include/dt-bindings/clock/px30-cru.h @@ -96,6 +96,7 @@ #define SCLK_SDIO_DIV50 81 #define SCLK_EMMC_DIV 82 #define SCLK_EMMC_DIV50 83 +#define SCLK_DDRCLK 84 /* dclk gates */ #define DCLK_VOPB 150 From 8865f61ad2b24ff8566de86df4ef1b1a30bb0d89 Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Mon, 5 Feb 2018 10:58:07 +0800 Subject: [PATCH 286/427] PM / devfreq: rockchip_dmc: add support for px30 Change-Id: I225088ce179f9b9cd62fce256b87bccb591fd2b2 Signed-off-by: YouMin Chen --- .../bindings/devfreq/rockchip_dmc.txt | 1 + drivers/devfreq/rockchip_dmc.c | 311 ++++++++++++++++++ include/dt-bindings/clock/rockchip-ddr.h | 2 + include/dt-bindings/memory/px30-dram.h | 132 ++++++++ 4 files changed, 446 insertions(+) create mode 100644 include/dt-bindings/memory/px30-dram.h diff --git a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt index 23ac503752a8..59a7c2b7ce15 100644 --- a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt +++ b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt @@ -2,6 +2,7 @@ Required properties: - compatible: Should be one of the following. + - "rockchip,px30-dmc" - for PX30 SoCs. - "rockchip,rk3128-dmc" - for RK3128 SoCs. - "rockchip,rk3228-dmc" - for RK3228 SoCs. - "rockchip,rk3288-dmc" - for RK3288 SoCs. diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 69b57982e7e1..b8d821a74f4a 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -100,6 +100,158 @@ struct share_params { static struct share_params *ddr_psci_param; +/* hope this define can adapt all future platfor */ +static const char * const px30_dts_timing[] = { + "ddr2_speed_bin", + "ddr3_speed_bin", + "ddr4_speed_bin", + "pd_idle", + "sr_idle", + "sr_mc_gate_idle", + "srpd_lite_idle", + "standby_idle", + + "auto_pd_dis_freq", + "auto_sr_dis_freq", + "ddr2_dll_dis_freq", + "ddr3_dll_dis_freq", + "ddr4_dll_dis_freq", + "phy_dll_dis_freq", + + "ddr2_odt_dis_freq", + "phy_ddr2_odt_dis_freq", + "ddr2_drv", + "ddr2_odt", + "phy_ddr2_ca_drv", + "phy_ddr2_ck_drv", + "phy_ddr2_dq_drv", + "phy_ddr2_odt", + + "ddr3_odt_dis_freq", + "phy_ddr3_odt_dis_freq", + "ddr3_drv", + "ddr3_odt", + "phy_ddr3_ca_drv", + "phy_ddr3_ck_drv", + "phy_ddr3_dq_drv", + "phy_ddr3_odt", + + "phy_lpddr2_odt_dis_freq", + "lpddr2_drv", + "phy_lpddr2_ca_drv", + "phy_lpddr2_ck_drv", + "phy_lpddr2_dq_drv", + "phy_lpddr2_odt", + + "lpddr3_odt_dis_freq", + "phy_lpddr3_odt_dis_freq", + "lpddr3_drv", + "lpddr3_odt", + "phy_lpddr3_ca_drv", + "phy_lpddr3_ck_drv", + "phy_lpddr3_dq_drv", + "phy_lpddr3_odt", + + "lpddr4_odt_dis_freq", + "phy_lpddr4_odt_dis_freq", + "lpddr4_drv", + "lpddr4_dq_odt", + "lpddr4_ca_odt", + "phy_lpddr4_ca_drv", + "phy_lpddr4_ck_cs_drv", + "phy_lpddr4_dq_drv", + "phy_lpddr4_odt", + + "ddr4_odt_dis_freq", + "phy_ddr4_odt_dis_freq", + "ddr4_drv", + "ddr4_odt", + "phy_ddr4_ca_drv", + "phy_ddr4_ck_drv", + "phy_ddr4_dq_drv", + "phy_ddr4_odt", +}; + +struct px30_ddr_dts_config_timing { + unsigned int ddr2_speed_bin; + unsigned int ddr3_speed_bin; + unsigned int ddr4_speed_bin; + unsigned int pd_idle; + unsigned int sr_idle; + unsigned int sr_mc_gate_idle; + unsigned int srpd_lite_idle; + unsigned int standby_idle; + + unsigned int auto_pd_dis_freq; + unsigned int auto_sr_dis_freq; + /* for ddr2 only */ + unsigned int ddr2_dll_dis_freq; + /* for ddr3 only */ + unsigned int ddr3_dll_dis_freq; + /* for ddr4 only */ + unsigned int ddr4_dll_dis_freq; + unsigned int phy_dll_dis_freq; + + unsigned int ddr2_odt_dis_freq; + unsigned int phy_ddr2_odt_dis_freq; + unsigned int ddr2_drv; + unsigned int ddr2_odt; + unsigned int phy_ddr2_ca_drv; + unsigned int phy_ddr2_ck_drv; + unsigned int phy_ddr2_dq_drv; + unsigned int phy_ddr2_odt; + + unsigned int ddr3_odt_dis_freq; + unsigned int phy_ddr3_odt_dis_freq; + unsigned int ddr3_drv; + unsigned int ddr3_odt; + unsigned int phy_ddr3_ca_drv; + unsigned int phy_ddr3_ck_drv; + unsigned int phy_ddr3_dq_drv; + unsigned int phy_ddr3_odt; + + unsigned int phy_lpddr2_odt_dis_freq; + unsigned int lpddr2_drv; + unsigned int phy_lpddr2_ca_drv; + unsigned int phy_lpddr2_ck_drv; + unsigned int phy_lpddr2_dq_drv; + unsigned int phy_lpddr2_odt; + + unsigned int lpddr3_odt_dis_freq; + unsigned int phy_lpddr3_odt_dis_freq; + unsigned int lpddr3_drv; + unsigned int lpddr3_odt; + unsigned int phy_lpddr3_ca_drv; + unsigned int phy_lpddr3_ck_drv; + unsigned int phy_lpddr3_dq_drv; + unsigned int phy_lpddr3_odt; + + unsigned int lpddr4_odt_dis_freq; + unsigned int phy_lpddr4_odt_dis_freq; + unsigned int lpddr4_drv; + unsigned int lpddr4_dq_odt; + unsigned int lpddr4_ca_odt; + unsigned int phy_lpddr4_ca_drv; + unsigned int phy_lpddr4_ck_cs_drv; + unsigned int phy_lpddr4_dq_drv; + unsigned int phy_lpddr4_odt; + + unsigned int ddr4_odt_dis_freq; + unsigned int phy_ddr4_odt_dis_freq; + unsigned int ddr4_drv; + unsigned int ddr4_odt; + unsigned int phy_ddr4_ca_drv; + unsigned int phy_ddr4_ck_drv; + unsigned int phy_ddr4_dq_drv; + unsigned int phy_ddr4_odt; + + unsigned int ca_skew[15]; + unsigned int cs0_skew[44]; + unsigned int cs1_skew[44]; + + unsigned int available; +}; + static const char * const rk3128_dts_timing[] = { "ddr3_speed_bin", "pd_idle", @@ -643,6 +795,61 @@ struct rockchip_dmcfreq { int (*set_auto_self_refresh)(u32 en); }; +/* + * function: packaging de-skew setting to px30_ddr_dts_config_timing, + * px30_ddr_dts_config_timing will pass to trust firmware, and + * used direct to set register. + * input: de_skew + * output: tim + */ +static void px30_de_skew_set_2_reg(struct rk3328_ddr_de_skew_setting *de_skew, + struct px30_ddr_dts_config_timing *tim) +{ + u32 n; + u32 offset; + u32 shift; + + memset_io(tim->ca_skew, 0, sizeof(tim->ca_skew)); + memset_io(tim->cs0_skew, 0, sizeof(tim->cs0_skew)); + memset_io(tim->cs1_skew, 0, sizeof(tim->cs1_skew)); + + /* CA de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->ca_de_skew); n++) { + offset = n / 2; + shift = n % 2; + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->ca_skew[offset] &= ~(0xf << shift); + tim->ca_skew[offset] |= (de_skew->ca_de_skew[n] << shift); + } + + /* CS0 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs0_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs0_skew[offset] &= ~(0xf << shift); + tim->cs0_skew[offset] |= (de_skew->cs0_de_skew[n] << shift); + } + + /* CS1 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs1_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs1_skew[offset] &= ~(0xf << shift); + tim->cs1_skew[offset] |= (de_skew->cs1_de_skew[n] << shift); + } +} + /* * function: packaging de-skew setting to rk3328_ddr_dts_config_timing, * rk3328_ddr_dts_config_timing will pass to trust firmware, and @@ -959,6 +1166,64 @@ static inline void reset_last_status(struct devfreq *devfreq) devfreq->last_status.busy_time = 1; } +static void of_get_px30_timings(struct device *dev, + struct device_node *np, uint32_t *timing) +{ + struct device_node *np_tim; + u32 *p; + struct px30_ddr_dts_config_timing *dts_timing; + struct rk3328_ddr_de_skew_setting *de_skew; + int ret = 0; + u32 i; + + dts_timing = + (struct px30_ddr_dts_config_timing *)(timing + + DTS_PAR_OFFSET / 4); + + np_tim = of_parse_phandle(np, "ddr_timing", 0); + if (!np_tim) { + ret = -EINVAL; + goto end; + } + de_skew = kmalloc(sizeof(*de_skew), GFP_KERNEL); + if (!de_skew) { + ret = -ENOMEM; + goto end; + } + p = (u32 *)dts_timing; + for (i = 0; i < ARRAY_SIZE(px30_dts_timing); i++) { + ret |= of_property_read_u32(np_tim, px30_dts_timing[i], + p + i); + } + p = (u32 *)de_skew->ca_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_ca_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_ca_timing[i], + p + i); + } + p = (u32 *)de_skew->cs0_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs0_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs0_timing[i], + p + i); + } + p = (u32 *)de_skew->cs1_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs1_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs1_timing[i], + p + i); + } + if (!ret) + px30_de_skew_set_2_reg(de_skew, dts_timing); + kfree(de_skew); +end: + if (!ret) { + dts_timing->available = 1; + } else { + dts_timing->available = 0; + dev_err(dev, "of_get_ddr_timings: fail\n"); + } + + of_node_put(np_tim); +} + static void of_get_rk3128_timings(struct device *dev, struct device_node *np, uint32_t *timing) { @@ -1303,6 +1568,51 @@ static int rockchip_ddr_set_auto_self_refresh(uint32_t en) return res.a0; } +static int px30_dmc_init(struct platform_device *pdev, + struct rockchip_dmcfreq *dmcfreq) +{ + struct arm_smccc_res res; + u32 size; + + res = sip_smc_dram(0, 0, + ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION); + dev_notice(&pdev->dev, "current ATF version 0x%lx!\n", res.a1); + if (res.a0 || res.a1 < 0x101) { + dev_err(&pdev->dev, + "trusted firmware need to update or is invalid!\n"); + return -ENXIO; + } + + dev_notice(&pdev->dev, "read tf version 0x%lx!\n", res.a1); + + /* + * first 4KB is used for interface parameters + * after 4KB * N is dts parameters + */ + size = sizeof(struct px30_ddr_dts_config_timing); + res = sip_smc_request_share_mem(DIV_ROUND_UP(size, 4096) + 1, + SHARE_PAGE_TYPE_DDR); + if (res.a0 != 0) { + dev_err(&pdev->dev, "no ATF memory for init\n"); + return -ENOMEM; + } + ddr_psci_param = (struct share_params *)res.a1; + of_get_px30_timings(&pdev->dev, pdev->dev.of_node, + (uint32_t *)ddr_psci_param); + + res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0, + ROCKCHIP_SIP_CONFIG_DRAM_INIT); + if (res.a0) { + dev_err(&pdev->dev, "rockchip_sip_config_dram_init error:%lx\n", + res.a0); + return -ENOMEM; + } + + dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh; + + return 0; +} + static int rk3128_dmc_init(struct platform_device *pdev, struct rockchip_dmcfreq *dmcfreq) { @@ -1610,6 +1920,7 @@ static int rk3399_dmc_init(struct platform_device *pdev) } static const struct of_device_id rockchip_dmcfreq_of_match[] = { + { .compatible = "rockchip,px30-dmc", .data = px30_dmc_init }, { .compatible = "rockchip,rk3128-dmc", .data = rk3128_dmc_init }, { .compatible = "rockchip,rk3228-dmc", .data = rk3228_dmc_init }, { .compatible = "rockchip,rk3288-dmc", .data = rk3288_dmc_init }, diff --git a/include/dt-bindings/clock/rockchip-ddr.h b/include/dt-bindings/clock/rockchip-ddr.h index 08c7a850ae5b..b065432e7793 100644 --- a/include/dt-bindings/clock/rockchip-ddr.h +++ b/include/dt-bindings/clock/rockchip-ddr.h @@ -16,6 +16,8 @@ #ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H #define _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H +#define DDR2_DEFAULT (0) + #define DDR3_800D (0) /* 5-5-5 */ #define DDR3_800E (1) /* 6-6-6 */ #define DDR3_1066E (2) /* 6-6-6 */ diff --git a/include/dt-bindings/memory/px30-dram.h b/include/dt-bindings/memory/px30-dram.h new file mode 100644 index 000000000000..17d799d802d9 --- /dev/null +++ b/include/dt-bindings/memory/px30-dram.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#ifndef _DT_BINDINGS_DRAM_ROCKCHIP_PX30_H +#define _DT_BINDINGS_DRAM_ROCKCHIP_PX30_H + +#define DDR2_DS_FULL (0) +#define DDR2_DS_REDUCE (1) + +#define DDR2_ODT_DIS (0) +#define DDR2_ODT_50ohm (50) /* optional */ +#define DDR2_ODT_75ohm (75) +#define DDR2_ODT_150ohm (150) + +#define DDR3_DS_34ohm (34) +#define DDR3_DS_40ohm (40) + +#define DDR3_ODT_DIS (0) +#define DDR3_ODT_40ohm (40) +#define DDR3_ODT_60ohm (60) +#define DDR3_ODT_120ohm (120) + +#define LP2_DS_34ohm (34) +#define LP2_DS_40ohm (40) +#define LP2_DS_48ohm (48) +#define LP2_DS_60ohm (60) +#define LP2_DS_68_6ohm (68) /* optional */ +#define LP2_DS_80ohm (80) +#define LP2_DS_120ohm (120) /* optional */ + +#define LP3_DS_34ohm (34) +#define LP3_DS_40ohm (40) +#define LP3_DS_48ohm (48) +#define LP3_DS_60ohm (60) +#define LP3_DS_80ohm (80) +#define LP3_DS_34D_40U (3440) +#define LP3_DS_40D_48U (4048) +#define LP3_DS_34D_48U (3448) + +#define LP3_ODT_DIS (0) +#define LP3_ODT_60ohm (60) +#define LP3_ODT_120ohm (120) +#define LP3_ODT_240ohm (240) + +#define LP4_PDDS_40ohm (40) +#define LP4_PDDS_48ohm (48) +#define LP4_PDDS_60ohm (60) +#define LP4_PDDS_80ohm (80) +#define LP4_PDDS_120ohm (120) +#define LP4_PDDS_240ohm (240) + +#define LP4_DQ_ODT_40ohm (40) +#define LP4_DQ_ODT_48ohm (48) +#define LP4_DQ_ODT_60ohm (60) +#define LP4_DQ_ODT_80ohm (80) +#define LP4_DQ_ODT_120ohm (120) +#define LP4_DQ_ODT_240ohm (240) +#define LP4_DQ_ODT_DIS (0) + +#define LP4_CA_ODT_40ohm (40) +#define LP4_CA_ODT_48ohm (48) +#define LP4_CA_ODT_60ohm (60) +#define LP4_CA_ODT_80ohm (80) +#define LP4_CA_ODT_120ohm (120) +#define LP4_CA_ODT_240ohm (240) +#define LP4_CA_ODT_DIS (0) + +#define DDR4_DS_34ohm (34) +#define DDR4_DS_48ohm (48) +#define DDR4_RTT_NOM_DIS (0) +#define DDR4_RTT_NOM_60ohm (60) +#define DDR4_RTT_NOM_120ohm (120) +#define DDR4_RTT_NOM_40ohm (40) +#define DDR4_RTT_NOM_240ohm (240) +#define DDR4_RTT_NOM_48ohm (48) +#define DDR4_RTT_NOM_80ohm (80) +#define DDR4_RTT_NOM_34ohm (34) + +#define PHY_DDR3_RON_RTT_DISABLE (0) +#define PHY_DDR3_RON_RTT_451ohm (1) +#define PHY_DDR3_RON_RTT_225ohm (2) +#define PHY_DDR3_RON_RTT_150ohm (3) +#define PHY_DDR3_RON_RTT_112ohm (4) +#define PHY_DDR3_RON_RTT_90ohm (5) +#define PHY_DDR3_RON_RTT_75ohm (6) +#define PHY_DDR3_RON_RTT_64ohm (7) +#define PHY_DDR3_RON_RTT_56ohm (16) +#define PHY_DDR3_RON_RTT_50ohm (17) +#define PHY_DDR3_RON_RTT_45ohm (18) +#define PHY_DDR3_RON_RTT_41ohm (19) +#define PHY_DDR3_RON_RTT_37ohm (20) +#define PHY_DDR3_RON_RTT_34ohm (21) +#define PHY_DDR3_RON_RTT_33ohm (22) +#define PHY_DDR3_RON_RTT_30ohm (23) +#define PHY_DDR3_RON_RTT_28ohm (24) +#define PHY_DDR3_RON_RTT_26ohm (25) +#define PHY_DDR3_RON_RTT_25ohm (26) +#define PHY_DDR3_RON_RTT_23ohm (27) +#define PHY_DDR3_RON_RTT_22ohm (28) +#define PHY_DDR3_RON_RTT_21ohm (29) +#define PHY_DDR3_RON_RTT_20ohm (30) +#define PHY_DDR3_RON_RTT_19ohm (31) + +#define PHY_DDR4_LPDDR3_2_RON_RTT_DISABLE (0) +#define PHY_DDR4_LPDDR3_2_RON_RTT_480ohm (1) +#define PHY_DDR4_LPDDR3_2_RON_RTT_240ohm (2) +#define PHY_DDR4_LPDDR3_2_RON_RTT_160ohm (3) +#define PHY_DDR4_LPDDR3_2_RON_RTT_120ohm (4) +#define PHY_DDR4_LPDDR3_2_RON_RTT_96ohm (5) +#define PHY_DDR4_LPDDR3_2_RON_RTT_80ohm (6) +#define PHY_DDR4_LPDDR3_2_RON_RTT_68ohm (7) +#define PHY_DDR4_LPDDR3_2_RON_RTT_60ohm (16) +#define PHY_DDR4_LPDDR3_2_RON_RTT_53ohm (17) +#define PHY_DDR4_LPDDR3_2_RON_RTT_48ohm (18) +#define PHY_DDR4_LPDDR3_2_RON_RTT_43ohm (19) +#define PHY_DDR4_LPDDR3_2_RON_RTT_40ohm (20) +#define PHY_DDR4_LPDDR3_2_RON_RTT_37ohm (21) +#define PHY_DDR4_LPDDR3_2_RON_RTT_34ohm (22) +#define PHY_DDR4_LPDDR3_2_RON_RTT_32ohm (23) +#define PHY_DDR4_LPDDR3_2_RON_RTT_30ohm (24) +#define PHY_DDR4_LPDDR3_2_RON_RTT_28ohm (25) +#define PHY_DDR4_LPDDR3_2_RON_RTT_26ohm (26) +#define PHY_DDR4_LPDDR3_2_RON_RTT_25ohm (27) +#define PHY_DDR4_LPDDR3_2_RON_RTT_24ohm (28) +#define PHY_DDR4_LPDDR3_2_RON_RTT_22ohm (29) +#define PHY_DDR4_LPDDR3_2_RON_RTT_21ohm (30) +#define PHY_DDR4_LPDDR3_2_RON_RTT_20ohm (31) + +#endif /*_DT_BINDINGS_DRAM_ROCKCHIP_PX30_H*/ From 3f9d4749de2ae42a2f1de08d9ae2475988a02040 Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Mon, 5 Feb 2018 10:57:23 +0800 Subject: [PATCH 287/427] PM / devfreq: event: add support for px30 dfi Change-Id: Ib6808d961b65d993fea05ab15d648d814d14a4a2 Signed-off-by: YouMin Chen --- .../bindings/devfreq/event/rockchip-dfi.txt | 1 + drivers/devfreq/event/rockchip-dfi.c | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt index 7a634bd56cff..80512cc2767d 100644 --- a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt +++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt @@ -3,6 +3,7 @@ Required properties: - compatible: Should be one of the following. + - "rockchip,px30-dfi" - for PX30 SoCs. - "rockchip,rk3128-dfi" - for RK3128 SoCs. - "rockchip,rk3288-dfi" - for RK3288 SoCs. - "rockchip,rk3328-dfi" - for RK3328 SoCs. diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index e7a4df827a6a..ba164ac1f841 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -26,6 +26,8 @@ #include #include +#define PX30_PMUGRF_OS_REG2 0x208 + #define RK3128_GRF_SOC_CON0 0x140 #define RK3128_GRF_OS_REG1 0x1cc #define RK3128_GRF_DFI_WRNUM 0x220 @@ -62,7 +64,7 @@ #define DDR4_EN (0x10001 << 5) #define LPDDR4_EN (0x10001 << 4) #define HARDWARE_EN (0x10001 << 3) -#define LPDDR3_EN (0x10001 << 2) +#define LPDDR2_3_EN (0x10001 << 2) #define SOFTWARE_EN (0x10001 << 1) #define SOFTWARE_DIS (0x10000 << 1) #define TIME_CNT_EN (0x10001 << 0) @@ -78,6 +80,7 @@ enum { DDR4 = 0, DDR3 = 3, + LPDDR2 = 5, LPDDR3 = 6, LPDDR4 = 7, UNUSED = 0xFF @@ -101,6 +104,7 @@ struct rockchip_dfi { void __iomem *regs; struct regmap *regmap_pmu; struct regmap *regmap_grf; + struct regmap *regmap_pmugrf; struct clk *clk; u32 dram_type; /* @@ -344,8 +348,8 @@ static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); /* set ddr type to dfi */ - if (info->dram_type == LPDDR3) - writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); + if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) + writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL); else if (info->dram_type == LPDDR4) writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); else if (info->dram_type == DDR4) @@ -449,6 +453,36 @@ static const struct devfreq_event_ops rockchip_dfi_ops = { .set_event = rockchip_dfi_set_event, }; +static __init int px30_dfi_init(struct platform_device *pdev, + struct rockchip_dfi *data, + struct devfreq_event_desc *desc) +{ + struct device_node *np = pdev->dev.of_node, *node; + struct resource *res; + u32 val; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->regs)) + return PTR_ERR(data->regs); + + node = of_parse_phandle(np, "rockchip,pmugrf", 0); + if (node) { + data->regmap_pmugrf = syscon_node_to_regmap(node); + if (IS_ERR(data->regmap_pmugrf)) + return PTR_ERR(data->regmap_pmugrf); + } + + regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val); + data->dram_type = READ_DRAMTYPE_INFO(val); + data->ch_msk = 1; + data->clk = NULL; + + desc->ops = &rockchip_dfi_ops; + + return 0; +} + static __init int rk3128_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc) @@ -590,6 +624,7 @@ static __init int rk3328_dfi_init(struct platform_device *pdev, } static const struct of_device_id rockchip_dfi_id_match[] = { + { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init }, { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init }, { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init }, From 56dfe1fdbedaad814ab59445442e1938a2b7e98f Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Mon, 5 Feb 2018 10:56:55 +0800 Subject: [PATCH 288/427] arm64: dts: rockchip: add px30 ddr relate node Change-Id: I33119ba0250c6c9fe78d124bf92a94a52f9442bf Signed-off-by: YouMin Chen --- .../rockchip/px30-dram-default-timing.dtsi | 294 ++++++++++++++++++ arch/arm64/boot/dts/rockchip/px30.dtsi | 70 +++++ 2 files changed, 364 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/px30-dram-default-timing.dtsi diff --git a/arch/arm64/boot/dts/rockchip/px30-dram-default-timing.dtsi b/arch/arm64/boot/dts/rockchip/px30-dram-default-timing.dtsi new file mode 100644 index 000000000000..9689a6fa7d53 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-dram-default-timing.dtsi @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#include +#include + +/ { + ddr_timing: ddr_timing { + compatible = "rockchip,ddr-timing"; + ddr2_speed_bin = ; + ddr3_speed_bin = ; + ddr4_speed_bin = ; + pd_idle = <0>; + sr_idle = <0>; + sr_mc_gate_idle = <0>; + srpd_lite_idle = <0>; + standby_idle = <0>; + + auto_pd_dis_freq = <1066>; + auto_sr_dis_freq = <800>; + ddr2_dll_dis_freq = <300>; + ddr3_dll_dis_freq = <300>; + ddr4_dll_dis_freq = <625>; + phy_dll_dis_freq = <400>; + + ddr2_odt_dis_freq = <100>; + phy_ddr2_odt_dis_freq = <100>; + ddr2_drv = ; + ddr2_odt = ; + phy_ddr2_ca_drv = ; + phy_ddr2_ck_drv = ; + phy_ddr2_dq_drv = ; + phy_ddr2_odt = ; + + ddr3_odt_dis_freq = <100>; + phy_ddr3_odt_dis_freq = <100>; + ddr3_drv = ; + ddr3_odt = ; + phy_ddr3_ca_drv = ; + phy_ddr3_ck_drv = ; + phy_ddr3_dq_drv = ; + phy_ddr3_odt = ; + + phy_lpddr2_odt_dis_freq = <666>; + lpddr2_drv = ; + phy_lpddr2_ca_drv = ; + phy_lpddr2_ck_drv = ; + phy_lpddr2_dq_drv = ; + phy_lpddr2_odt = ; + + lpddr3_odt_dis_freq = <666>; + phy_lpddr3_odt_dis_freq = <666>; + lpddr3_drv = ; + lpddr3_odt = ; + phy_lpddr3_ca_drv = ; + phy_lpddr3_ck_drv = ; + phy_lpddr3_dq_drv = ; + phy_lpddr3_odt = ; + + lpddr4_odt_dis_freq = <800>; + phy_lpddr4_odt_dis_freq = <800>; + lpddr4_drv = ; + lpddr4_dq_odt = ; + lpddr4_ca_odt = ; + phy_lpddr4_ca_drv = ; + phy_lpddr4_ck_cs_drv = ; + phy_lpddr4_dq_drv = ; + phy_lpddr4_odt = ; + + ddr4_odt_dis_freq = <666>; + phy_ddr4_odt_dis_freq = <666>; + ddr4_drv = ; + ddr4_odt = ; + phy_ddr4_ca_drv = ; + phy_ddr4_ck_drv = ; + phy_ddr4_dq_drv = ; + phy_ddr4_odt = ; + + /* CA de-skew, one step is 47.8ps, range 0-15 */ + ddr3a1_ddr4a9_de-skew = <7>; + ddr3a0_ddr4a10_de-skew = <7>; + ddr3a3_ddr4a6_de-skew = <8>; + ddr3a2_ddr4a4_de-skew = <8>; + ddr3a5_ddr4a8_de-skew = <7>; + ddr3a4_ddr4a5_de-skew = <9>; + ddr3a7_ddr4a11_de-skew = <7>; + ddr3a6_ddr4a7_de-skew = <9>; + ddr3a9_ddr4a0_de-skew = <8>; + ddr3a8_ddr4a13_de-skew = <7>; + ddr3a11_ddr4a3_de-skew = <9>; + ddr3a10_ddr4cs0_de-skew = <7>; + ddr3a13_ddr4a2_de-skew = <8>; + ddr3a12_ddr4ba1_de-skew = <7>; + ddr3a15_ddr4odt0_de-skew = <7>; + ddr3a14_ddr4a1_de-skew = <8>; + ddr3ba1_ddr4a15_de-skew = <7>; + ddr3ba0_ddr4bg0_de-skew = <7>; + ddr3ras_ddr4cke_de-skew = <7>; + ddr3ba2_ddr4ba0_de-skew = <8>; + ddr3we_ddr4bg1_de-skew = <8>; + ddr3cas_ddr4a12_de-skew = <7>; + ddr3ckn_ddr4ckn_de-skew = <8>; + ddr3ckp_ddr4ckp_de-skew = <8>; + ddr3cke_ddr4a16_de-skew = <8>; + ddr3odt0_ddr4a14_de-skew = <7>; + ddr3cs0_ddr4act_de-skew = <8>; + ddr3reset_ddr4reset_de-skew = <7>; + ddr3cs1_ddr4cs1_de-skew = <7>; + ddr3odt1_ddr4odt1_de-skew = <7>; + + /* DATA de-skew + * RX one step is 25.1ps, range 0-15 + * TX one step is 47.8ps, range 0-15 + */ + cs0_dm0_rx_de-skew = <7>; + cs0_dm0_tx_de-skew = <8>; + cs0_dq0_rx_de-skew = <7>; + cs0_dq0_tx_de-skew = <8>; + cs0_dq1_rx_de-skew = <7>; + cs0_dq1_tx_de-skew = <8>; + cs0_dq2_rx_de-skew = <7>; + cs0_dq2_tx_de-skew = <8>; + cs0_dq3_rx_de-skew = <7>; + cs0_dq3_tx_de-skew = <8>; + cs0_dq4_rx_de-skew = <7>; + cs0_dq4_tx_de-skew = <8>; + cs0_dq5_rx_de-skew = <7>; + cs0_dq5_tx_de-skew = <8>; + cs0_dq6_rx_de-skew = <7>; + cs0_dq6_tx_de-skew = <8>; + cs0_dq7_rx_de-skew = <7>; + cs0_dq7_tx_de-skew = <8>; + cs0_dqs0_rx_de-skew = <6>; + cs0_dqs0p_tx_de-skew = <9>; + cs0_dqs0n_tx_de-skew = <9>; + + cs0_dm1_rx_de-skew = <7>; + cs0_dm1_tx_de-skew = <7>; + cs0_dq8_rx_de-skew = <7>; + cs0_dq8_tx_de-skew = <8>; + cs0_dq9_rx_de-skew = <7>; + cs0_dq9_tx_de-skew = <7>; + cs0_dq10_rx_de-skew = <7>; + cs0_dq10_tx_de-skew = <8>; + cs0_dq11_rx_de-skew = <7>; + cs0_dq11_tx_de-skew = <7>; + cs0_dq12_rx_de-skew = <7>; + cs0_dq12_tx_de-skew = <8>; + cs0_dq13_rx_de-skew = <7>; + cs0_dq13_tx_de-skew = <7>; + cs0_dq14_rx_de-skew = <7>; + cs0_dq14_tx_de-skew = <8>; + cs0_dq15_rx_de-skew = <7>; + cs0_dq15_tx_de-skew = <7>; + cs0_dqs1_rx_de-skew = <7>; + cs0_dqs1p_tx_de-skew = <9>; + cs0_dqs1n_tx_de-skew = <9>; + + cs0_dm2_rx_de-skew = <7>; + cs0_dm2_tx_de-skew = <8>; + cs0_dq16_rx_de-skew = <7>; + cs0_dq16_tx_de-skew = <8>; + cs0_dq17_rx_de-skew = <7>; + cs0_dq17_tx_de-skew = <8>; + cs0_dq18_rx_de-skew = <7>; + cs0_dq18_tx_de-skew = <8>; + cs0_dq19_rx_de-skew = <7>; + cs0_dq19_tx_de-skew = <8>; + cs0_dq20_rx_de-skew = <7>; + cs0_dq20_tx_de-skew = <8>; + cs0_dq21_rx_de-skew = <7>; + cs0_dq21_tx_de-skew = <8>; + cs0_dq22_rx_de-skew = <7>; + cs0_dq22_tx_de-skew = <8>; + cs0_dq23_rx_de-skew = <7>; + cs0_dq23_tx_de-skew = <8>; + cs0_dqs2_rx_de-skew = <6>; + cs0_dqs2p_tx_de-skew = <9>; + cs0_dqs2n_tx_de-skew = <9>; + + cs0_dm3_rx_de-skew = <7>; + cs0_dm3_tx_de-skew = <7>; + cs0_dq24_rx_de-skew = <7>; + cs0_dq24_tx_de-skew = <8>; + cs0_dq25_rx_de-skew = <7>; + cs0_dq25_tx_de-skew = <7>; + cs0_dq26_rx_de-skew = <7>; + cs0_dq26_tx_de-skew = <7>; + cs0_dq27_rx_de-skew = <7>; + cs0_dq27_tx_de-skew = <7>; + cs0_dq28_rx_de-skew = <7>; + cs0_dq28_tx_de-skew = <7>; + cs0_dq29_rx_de-skew = <7>; + cs0_dq29_tx_de-skew = <7>; + cs0_dq30_rx_de-skew = <7>; + cs0_dq30_tx_de-skew = <7>; + cs0_dq31_rx_de-skew = <7>; + cs0_dq31_tx_de-skew = <7>; + cs0_dqs3_rx_de-skew = <7>; + cs0_dqs3p_tx_de-skew = <9>; + cs0_dqs3n_tx_de-skew = <9>; + + cs1_dm0_rx_de-skew = <7>; + cs1_dm0_tx_de-skew = <8>; + cs1_dq0_rx_de-skew = <7>; + cs1_dq0_tx_de-skew = <8>; + cs1_dq1_rx_de-skew = <7>; + cs1_dq1_tx_de-skew = <8>; + cs1_dq2_rx_de-skew = <7>; + cs1_dq2_tx_de-skew = <8>; + cs1_dq3_rx_de-skew = <7>; + cs1_dq3_tx_de-skew = <8>; + cs1_dq4_rx_de-skew = <7>; + cs1_dq4_tx_de-skew = <8>; + cs1_dq5_rx_de-skew = <7>; + cs1_dq5_tx_de-skew = <8>; + cs1_dq6_rx_de-skew = <7>; + cs1_dq6_tx_de-skew = <8>; + cs1_dq7_rx_de-skew = <7>; + cs1_dq7_tx_de-skew = <8>; + cs1_dqs0_rx_de-skew = <6>; + cs1_dqs0p_tx_de-skew = <9>; + cs1_dqs0n_tx_de-skew = <9>; + + cs1_dm1_rx_de-skew = <7>; + cs1_dm1_tx_de-skew = <7>; + cs1_dq8_rx_de-skew = <7>; + cs1_dq8_tx_de-skew = <8>; + cs1_dq9_rx_de-skew = <7>; + cs1_dq9_tx_de-skew = <7>; + cs1_dq10_rx_de-skew = <7>; + cs1_dq10_tx_de-skew = <8>; + cs1_dq11_rx_de-skew = <7>; + cs1_dq11_tx_de-skew = <7>; + cs1_dq12_rx_de-skew = <7>; + cs1_dq12_tx_de-skew = <8>; + cs1_dq13_rx_de-skew = <7>; + cs1_dq13_tx_de-skew = <7>; + cs1_dq14_rx_de-skew = <7>; + cs1_dq14_tx_de-skew = <8>; + cs1_dq15_rx_de-skew = <7>; + cs1_dq15_tx_de-skew = <7>; + cs1_dqs1_rx_de-skew = <7>; + cs1_dqs1p_tx_de-skew = <9>; + cs1_dqs1n_tx_de-skew = <9>; + + cs1_dm2_rx_de-skew = <7>; + cs1_dm2_tx_de-skew = <8>; + cs1_dq16_rx_de-skew = <7>; + cs1_dq16_tx_de-skew = <8>; + cs1_dq17_rx_de-skew = <7>; + cs1_dq17_tx_de-skew = <8>; + cs1_dq18_rx_de-skew = <7>; + cs1_dq18_tx_de-skew = <8>; + cs1_dq19_rx_de-skew = <7>; + cs1_dq19_tx_de-skew = <8>; + cs1_dq20_rx_de-skew = <7>; + cs1_dq20_tx_de-skew = <8>; + cs1_dq21_rx_de-skew = <7>; + cs1_dq21_tx_de-skew = <8>; + cs1_dq22_rx_de-skew = <7>; + cs1_dq22_tx_de-skew = <8>; + cs1_dq23_rx_de-skew = <7>; + cs1_dq23_tx_de-skew = <8>; + cs1_dqs2_rx_de-skew = <6>; + cs1_dqs2p_tx_de-skew = <9>; + cs1_dqs2n_tx_de-skew = <9>; + + cs1_dm3_rx_de-skew = <7>; + cs1_dm3_tx_de-skew = <7>; + cs1_dq24_rx_de-skew = <7>; + cs1_dq24_tx_de-skew = <8>; + cs1_dq25_rx_de-skew = <7>; + cs1_dq25_tx_de-skew = <7>; + cs1_dq26_rx_de-skew = <7>; + cs1_dq26_tx_de-skew = <7>; + cs1_dq27_rx_de-skew = <7>; + cs1_dq27_tx_de-skew = <7>; + cs1_dq28_rx_de-skew = <7>; + cs1_dq28_tx_de-skew = <7>; + cs1_dq29_rx_de-skew = <7>; + cs1_dq29_tx_de-skew = <7>; + cs1_dq30_rx_de-skew = <7>; + cs1_dq30_tx_de-skew = <7>; + cs1_dq31_rx_de-skew = <7>; + cs1_dq31_tx_de-skew = <7>; + cs1_dqs3_rx_de-skew = <7>; + cs1_dqs3p_tx_de-skew = <9>; + cs1_dqs3n_tx_de-skew = <9>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 319f118ed6bb..a5412e236501 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include "px30-dram-default-timing.dtsi" / { compatible = "rockchip,px30"; @@ -1345,6 +1347,74 @@ reg = <0x0 0xff558080 0x0 0x20>; }; + dfi: dfi@ff610000 { + reg = <0x00 0xff610000 0x00 0x400>; + compatible = "rockchip,px30-dfi"; + rockchip,pmugrf = <&pmugrf>; + status = "disabled"; + }; + + dmc: dmc { + compatible = "rockchip,px30-dmc"; + devfreq-events = <&dfi>; + clocks = <&cru SCLK_DDRCLK>; + clock-names = "dmc_clk"; + operating-points-v2 = <&dmc_opp_table>; + ddr_timing = <&ddr_timing>; + upthreshold = <40>; + downdifferential = <20>; + system-status-freq = < + /*system status freq(KHz)*/ + SYS_STATUS_NORMAL 786000 + SYS_STATUS_REBOOT 786000 + SYS_STATUS_SUSPEND 786000 + SYS_STATUS_VIDEO_1080P 786000 + SYS_STATUS_PERFORMANCE 786000 + SYS_STATUS_BOOST 786000 + >; + auto-min-freq = <400000>; + auto-freq-en = <0>; + #cooling-cells = <2>; + status = "disabled"; + + ddr_power_model: ddr_power_model { + compatible = "ddr_power_model"; + dynamic-power-coefficient = <120>; + static-power-coefficient = <200>; + ts = <32000 4700 (-80) 2>; + thermal-zone = "soc-thermal"; + }; + }; + + dmc_opp_table: dmc-opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <925000>; + opp-microvolt-L0 = <925000>; + opp-microvolt-L1 = <900000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1025000>; + opp-microvolt-L0 = <1025000>; + opp-microvolt-L1 = <1000000>; + }; + opp-786000000 { + opp-hz = /bits/ 64 <786000000>; + opp-microvolt = <1075000>; + opp-microvolt-L0 = <1075000>; + opp-microvolt-L1 = <1050000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1075000>; + opp-microvolt-L0 = <1075000>; + opp-microvolt-L1 = <1050000>; + }; + }; + pinctrl: pinctrl { compatible = "rockchip,px30-pinctrl"; rockchip,grf = <&grf>; From 6b1070e6469bded8be3751618adac91d93c9f75f Mon Sep 17 00:00:00 2001 From: Zhang Yunlong Date: Fri, 19 Jan 2018 20:32:09 +0800 Subject: [PATCH 289/427] camera: rockchip: cif: support multi camera config fix gpio_desc request fail when multi cameras defined in dts. Change-Id: I058ea1284ef86fcea621197367e426f018853936 Signed-off-by: Zhang Yunlong --- drivers/media/video/generic_sensor.c | 66 ++++++++++++++ drivers/media/video/generic_sensor.h | 51 +---------- drivers/soc/rockchip/rk_camera.c | 131 +++++++++++++++++++-------- drivers/soc/rockchip/rk_camera.h | 14 +++ 4 files changed, 178 insertions(+), 84 deletions(-) diff --git a/drivers/media/video/generic_sensor.c b/drivers/media/video/generic_sensor.c index 767076256fe5..98875e394d6d 100644 --- a/drivers/media/video/generic_sensor.c +++ b/drivers/media/video/generic_sensor.c @@ -1508,3 +1508,69 @@ int generic_sensor_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeen } +static inline int deinit_sensor_gpio(int pltfrm_gpio) +{ + struct rk29_camera_gpio *camera_gpio; + + list_for_each_entry(camera_gpio, &camera_gpios.gpios, gpios) + if (camera_gpio->pltfrm_gpio == pltfrm_gpio) + break; + + if (camera_gpio->pltfrm_gpio == pltfrm_gpio) { + camera_gpio->count--; + + if (!camera_gpio->count) { + gpiod_direction_input(camera_gpio->gpio_desc); + gpiod_put(camera_gpio->gpio_desc); + + list_del(&camera_gpio->gpios); + kfree(camera_gpio); + } + } + + return 0; +} + +void deinit_sensor_gpios(struct soc_camera_device *icd) +{ + struct soc_camera_desc *desc = to_soc_camera_desc(icd); + struct rk29camera_platform_data *pdata = desc->subdev_desc.drv_priv; + struct rkcamera_platform_data *sensor_device = NULL, *new_camera; + struct rk29camera_gpio_res *gpios = NULL; + + new_camera = pdata->register_dev_new; + while (new_camera) { + if (strcmp(dev_name(icd->pdev), new_camera->dev_name) == 0) { + sensor_device = new_camera; + break; + } + new_camera = new_camera->next_camera; + } + if (!sensor_device) { + pr_err("%s(%d): Could not find %s\n", + __func__, __LINE__, dev_name(icd->pdev)); + return; + } + + gpios = &new_camera->io; + + deinit_sensor_gpio(gpios->power); + deinit_sensor_gpio(gpios->powerdown); + deinit_sensor_gpio(gpios->reset); + deinit_sensor_gpio(gpios->af); + deinit_sensor_gpio(gpios->flash); + deinit_sensor_gpio(gpios->irq); + gpios->gpio_power = NULL; + gpios->gpio_powerdown = NULL; + gpios->gpio_reset = NULL; + gpios->gpio_af = NULL; + gpios->gpio_flash = NULL; + gpios->gpio_irq = NULL; + gpios->power = INVALID_GPIO; + gpios->powerdown = INVALID_GPIO; + gpios->reset = INVALID_GPIO; + gpios->af = INVALID_GPIO; + gpios->flash = INVALID_GPIO; + gpios->irq = INVALID_GPIO; +} + diff --git a/drivers/media/video/generic_sensor.h b/drivers/media/video/generic_sensor.h index 6d68d43862b0..530435a6d6bb 100644 --- a/drivers/media/video/generic_sensor.h +++ b/drivers/media/video/generic_sensor.h @@ -92,6 +92,8 @@ #define CFG_FunChk(a, b) ((a & b) == b) #define CFG_FunDis(a, b) (a &= (~b)) +extern struct rk29_camera_gpio camera_gpios; + enum rk_sensor_sequence_property { SEQUENCE_INIT = 1, SEQUENCE_PREVIEW, @@ -332,6 +334,7 @@ extern int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable); extern int generic_sensor_writebuf(struct i2c_client *client, char *buf, int buf_size); extern int generic_sensor_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cc); extern int generic_sensor_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); +void deinit_sensor_gpios(struct soc_camera_device *icd); static inline int sensor_get_full_width_height(int full_resolution, unsigned short *w, unsigned short *h) { @@ -726,54 +729,6 @@ static inline int sensor_v4l2ctrl_flip_default_cb(struct soc_camera_device *icd, return sensor_v4l2ctrl_flip_cb(icd, ctrl_info, ext_ctrl); } -static inline void deinit_sensor_gpios(struct soc_camera_device *icd) -{ - struct soc_camera_desc *desc = to_soc_camera_desc(icd); - struct rk29camera_platform_data *pdata = desc->subdev_desc.drv_priv; - struct rkcamera_platform_data *sensor_device = NULL, *new_camera; - struct rk29camera_gpio_res *gpios = NULL; - - new_camera = pdata->register_dev_new; - while (new_camera) { - if (strcmp(dev_name(icd->pdev), new_camera->dev_name) == 0) { - sensor_device = new_camera; - break; - } - new_camera = new_camera->next_camera; - } - if (!sensor_device) { - pr_err("%s(%d): Could not find %s\n", - __func__, __LINE__, dev_name(icd->pdev)); - return; - } - - gpios = &new_camera->io; - if (gpios->gpio_reset) { - gpiod_direction_input(gpios->gpio_reset); - gpiod_put(gpios->gpio_reset); - } - if (gpios->gpio_power) { - gpiod_direction_input(gpios->gpio_power); - gpiod_put(gpios->gpio_power); - } - if (gpios->gpio_powerdown) { - gpiod_direction_input(gpios->gpio_powerdown); - gpiod_put(gpios->gpio_powerdown); - } - if (gpios->gpio_flash) { - gpiod_direction_input(gpios->gpio_flash); - gpiod_put(gpios->gpio_flash); - } - if (gpios->gpio_af) { - gpiod_direction_input(gpios->gpio_af); - gpiod_put(gpios->gpio_af); - } - if (gpios->gpio_irq) { - gpiod_direction_input(gpios->gpio_irq); - gpiod_put(gpios->gpio_irq); - } -} - #define new_user_v4l2ctrl(ctl_id, ctl_type, ctl_name, ctl_min, ctl_max, ctl_step, default_val, callback, seqe)\ {\ .qctrl = {\ diff --git a/drivers/soc/rockchip/rk_camera.c b/drivers/soc/rockchip/rk_camera.c index ee41482037d0..2f122aaacb57 100644 --- a/drivers/soc/rockchip/rk_camera.c +++ b/drivers/soc/rockchip/rk_camera.c @@ -99,6 +99,61 @@ static int rk_dts_sensor_remove(struct platform_device *pdev) return 0; } +struct rk29_camera_gpio camera_gpios; +static struct gpio_desc *rk_dts_sensor_parse_gpio( + struct device *dev, + struct fwnode_handle *child, + int pltfrm_gpio, + const char *label) +{ + struct rk29_camera_gpio *camera_gpio; + struct rk29_camera_gpio *new_gpio; + struct gpio_desc *gpio; + + if (IS_ERR_VALUE(pltfrm_gpio)) + return NULL; + + list_for_each_entry(camera_gpio, &camera_gpios.gpios, gpios) { + if (camera_gpio->pltfrm_gpio == pltfrm_gpio) + break; + } + + if (camera_gpio->pltfrm_gpio != pltfrm_gpio) { + dprintk("%s(%d): alloc a new gpio for pltfrm gpio %d\n", + __func__, __LINE__, pltfrm_gpio); + new_gpio = kzalloc(sizeof(*new_gpio), GFP_KERNEL); + if (!new_gpio) { + eprintk("%s(%d): alloc camera_gpio failed\n", + __func__, __LINE__); + return NULL; + } + + new_gpio->pltfrm_gpio = pltfrm_gpio; + new_gpio->count = 1; + new_gpio->gpio_desc = + devm_get_gpiod_from_child(dev, label, child); + if (IS_ERR(new_gpio->gpio_desc)) { + eprintk("gpio reset get failed.\n"); + goto err_alloc; + } + + list_add_tail(&new_gpio->gpios, &camera_gpios.gpios); + gpio = new_gpio->gpio_desc; + } else { + camera_gpio->count++; + gpio = camera_gpio->gpio_desc; + dprintk("%s(%d): gpio %d have get count %d\n", + __func__, __LINE__, + pltfrm_gpio, camera_gpio->count); + } + + return gpio; +err_alloc: + kfree(new_gpio); + + return NULL; +} + static int rk_dts_sensor_probe(struct platform_device *pdev) { struct device_node *np, *cp; @@ -106,6 +161,13 @@ static int rk_dts_sensor_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rkcamera_platform_data *new_camera_list; struct fwnode_handle *child; + enum of_gpio_flags flags; + int power = INVALID_GPIO; + int powerdown = INVALID_GPIO; + int reset = INVALID_GPIO; + int af = INVALID_GPIO; + int flash = INVALID_GPIO; + int irq = INVALID_GPIO; int count; np = dev->of_node; @@ -116,6 +178,7 @@ static int rk_dts_sensor_probe(struct platform_device *pdev) if (!count) return -ENODEV; + INIT_LIST_HEAD(&camera_gpios.gpios); device_for_each_child_node(dev, child) { u32 flash_attach = 0, mir = 0, i2c_chl = 0, i2c_add = 0; u32 cif_chl = 0, mclk_rate = 0, is_front = 0; @@ -286,48 +349,44 @@ static int rk_dts_sensor_probe(struct platform_device *pdev) sprintf(new_camera->dev_name, "%s_%s", name, "back"); new_camera->dev.device_info.dev.init_name = (const char *)&new_camera->dev_name[0]; - new_camera->io.gpio_reset = devm_get_gpiod_from_child(dev, - "reset", child); - if (IS_ERR(new_camera->io.gpio_reset)) { - eprintk("gpio reset get failed.\n"); - new_camera->io.gpio_reset = NULL; - } + power = of_get_named_gpio_flags(cp, "power-gpios", + 0, &flags); + powerdown = of_get_named_gpio_flags(cp, "powerdown-gpios", + 0, &flags); + reset = of_get_named_gpio_flags(cp, "reset-gpios", + 0, &flags); + af = of_get_named_gpio_flags(cp, "af-gpios", + 0, &flags); + flash = of_get_named_gpio_flags(cp, "flash-gpios", + 0, &flags); + irq = of_get_named_gpio_flags(cp, "irq-gpios", + 0, &flags); - new_camera->io.gpio_powerdown = devm_get_gpiod_from_child(dev, - "powerdown", child); - if (IS_ERR(new_camera->io.gpio_powerdown)) { - eprintk("gpio powerdown get failed.\n"); - new_camera->io.gpio_powerdown = NULL; - } + new_camera->io.gpio_reset = + rk_dts_sensor_parse_gpio(dev, child, reset, "reset"); - new_camera->io.gpio_power = devm_get_gpiod_from_child(dev, - "power", child); - if (IS_ERR(new_camera->io.gpio_power)) { - eprintk("gpio power get failed.\n"); - new_camera->io.gpio_power = NULL; - } + new_camera->io.gpio_power = + rk_dts_sensor_parse_gpio(dev, child, power, "power"); - new_camera->io.gpio_af = devm_get_gpiod_from_child(dev, - "af", child); - if (IS_ERR(new_camera->io.gpio_af)) { - eprintk("gpio af get failed.\n"); - new_camera->io.gpio_af = NULL; - } + new_camera->io.gpio_powerdown = + rk_dts_sensor_parse_gpio(dev, child, + powerdown, "powerdown"); - new_camera->io.gpio_flash = devm_get_gpiod_from_child(dev, - "flash", child); - if (IS_ERR(new_camera->io.gpio_flash)) { - eprintk("gpio flash get failed.\n"); - new_camera->io.gpio_flash = NULL; - } + new_camera->io.gpio_af = + rk_dts_sensor_parse_gpio(dev, child, af, "af"); - new_camera->io.gpio_irq = devm_get_gpiod_from_child(dev, - "irq", child); - if (IS_ERR(new_camera->io.gpio_irq)) { - eprintk("gpio irq get failed.\n"); - new_camera->io.gpio_irq = NULL; - } + new_camera->io.gpio_flash = + rk_dts_sensor_parse_gpio(dev, child, flash, "flash"); + new_camera->io.gpio_irq = + rk_dts_sensor_parse_gpio(dev, child, irq, "irq"); + + new_camera->io.reset = reset; + new_camera->io.power = power; + new_camera->io.powerdown = powerdown; + new_camera->io.af = af; + new_camera->io.flash = flash; + new_camera->io.irq = irq; new_camera->io.gpio_flag = ((pwr_active & 0x01) << RK29_CAM_POWERACTIVE_BITPOS) | ((rst_active & 0x01) << RK29_CAM_RESETACTIVE_BITPOS) | ((pwdn_active & 0x01) << RK29_CAM_POWERDNACTIVE_BITPOS) | diff --git a/drivers/soc/rockchip/rk_camera.h b/drivers/soc/rockchip/rk_camera.h index 529385869ece..293342efe1e0 100644 --- a/drivers/soc/rockchip/rk_camera.h +++ b/drivers/soc/rockchip/rk_camera.h @@ -170,6 +170,14 @@ enum rk29camera_flash_cmd Flash_Torch }; +struct rk29_camera_gpio { + struct gpio_desc *gpio_desc; + unsigned int pltfrm_gpio; + int count; + + struct list_head gpios; +}; + struct rk29camera_gpio_res { struct gpio_desc *gpio_reset; struct gpio_desc *gpio_power; @@ -177,6 +185,12 @@ struct rk29camera_gpio_res { struct gpio_desc *gpio_flash; struct gpio_desc *gpio_af; struct gpio_desc *gpio_irq; + int reset; + int power; + int powerdown; + int flash; + int af; + int irq; unsigned int gpio_flag; unsigned int gpio_init; const char *dev_name; From 230ab0bd6c0e9c04cc636cc316a93a6950709873 Mon Sep 17 00:00:00 2001 From: Putin Lee Date: Thu, 8 Feb 2018 15:17:42 +0800 Subject: [PATCH 290/427] arm64: dts: rockchip: px30: add SCLK_RGA_CORE for rk_rga. Change-Id: Ib183606bbd1a4ac2c9669100a6634aca45bcfb5e Signed-off-by: Putin Lee --- arch/arm64/boot/dts/rockchip/px30.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index a5412e236501..dcf3959bb97c 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1177,8 +1177,8 @@ //dev_mode = <1>; reg = <0x0 0xff480000 0x0 0x1000>; interrupts = ; - clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>; - clock-names = "aclk_rga", "hclk_rga"; + clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA_CORE>; + clock-names = "aclk_rga", "hclk_rga", "clk_rga"; power-domains = <&power PX30_PD_VO>; dma-coherent; status = "disabled"; From bc11949511cea84511310911110237b171f834d7 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Thu, 8 Feb 2018 11:38:04 +0800 Subject: [PATCH 291/427] drm/rockchip: vop: fix iommu pagefault This version vop will read buffer when win2 master0-3 disable but win2 enable, this is different from old vop version. so we add to disable win2 en to make sure it's save. Change-Id: Ib239a8901095a6eff980747f219c3aa585437dae Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 6290aec7f100..42ced600c78f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -444,6 +444,7 @@ static void vop_disable_allwin(struct vop *vop) struct vop_win *win = &vop->win[i]; VOP_WIN_SET(vop, win, enable, 0); + VOP_WIN_SET(vop, win, gate, 0); } } @@ -1319,7 +1320,7 @@ static void vop_initial(struct drm_crtc *crtc) VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE); } VOP_WIN_SET(vop, win, enable, 0); - VOP_WIN_SET(vop, win, gate, 1); + VOP_WIN_SET(vop, win, gate, 0); } VOP_CTRL_SET(vop, afbdc_en, 0); @@ -1552,6 +1553,8 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE); } VOP_WIN_SET(vop, win, enable, 0); + if (win->area_id == 0) + VOP_WIN_SET(vop, win, gate, 0); spin_unlock(&vop->reg_lock); @@ -1674,6 +1677,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, VOP_WIN_SET_EXT(vop, win, csc, r2y_en, vop_plane_state->r2y_en); } VOP_WIN_SET(vop, win, enable, 1); + VOP_WIN_SET(vop, win, gate, 1); spin_unlock(&vop->reg_lock); vop->is_iommu_needed = true; } From bbdfca3f4f4b33a2d86d6267ec4170be2e87be17 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 8 Feb 2018 14:46:05 +0800 Subject: [PATCH 292/427] arm64: configs: Enable CONFIG_KEYBOARD_ADC config for rockchip_defconfig Change-Id: Ibb1deaeadc13186f12251a8596c8dd214bd0c12b Signed-off-by: David Wu --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index f33938b387bb..5558681103bd 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -364,6 +364,7 @@ CONFIG_RTL8822BE=m # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y +CONFIG_KEYBOARD_ADC=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_ROCKCHIP=y # CONFIG_INPUT_MOUSE is not set From ff72078491c0276856e348a83edfed14fa27975f Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 8 Feb 2018 14:47:54 +0800 Subject: [PATCH 293/427] arm64: dts: rockchip: Fix some adc key issues for rk3326/px30 board 1. add vref voltage 1.8v; 2. Alphabetical order; 3. Fix the press-threshold-microvolt; 4. Add poll interval 100ms Change-Id: If5e29f5073155be3022053cc3516dda88c5db223 Signed-off-by: David Wu --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 34 ++++++++++--------- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 22 ++++++------ .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 16 +++++---- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 34 ++++++++++--------- 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 97e65dbe75d7..f928d78a4c5b 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -21,36 +21,37 @@ compatible = "adc-keys"; io-channels = <&saradc 2>; io-channel-names = "buttons"; + poll-interval = <100>; keyup-threshold-microvolt = <1800000>; - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <10000>; - }; - - vol-down-key { - linux,code = ; - label = "volume down"; - press-threshold-microvolt = <170000>; + esc-key { + linux,code = ; + label = "esc"; + press-threshold-microvolt = <1270000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <254000>; + press-threshold-microvolt = <602000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <414000>; + press-threshold-microvolt = <952000>; }; - esc-key { - linux,code = ; - label = "esc"; - press-threshold-microvolt = <614000>; + vol-down-key { + linux,code = ; + label = "volume down"; + press-threshold-microvolt = <290000>; + }; + + vol-up-key { + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <17000>; }; }; @@ -587,6 +588,7 @@ &saradc { status = "okay"; + vref-supply = <&vcc1v8_soc>; }; &sdmmc { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 9f51bef0ac96..21bfae817f48 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -21,36 +21,37 @@ compatible = "adc-keys"; io-channels = <&saradc 2>; io-channel-names = "buttons"; + poll-interval = <100>; keyup-threshold-microvolt = <1800000>; esc-key { linux,code = ; label = "esc"; - press-threshold-microvolt = <614000>; + press-threshold-microvolt = <1270000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <254000>; + press-threshold-microvolt = <602000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <414000>; - }; - - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <10000>; + press-threshold-microvolt = <952000>; }; vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <170000>; + press-threshold-microvolt = <290000>; + }; + + vol-up-key { + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <17000>; }; }; @@ -587,6 +588,7 @@ &saradc { status = "okay"; + vref-supply = <&vcc1v8_soc>; }; &sdmmc { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index dee77de7ebbd..648149d24450 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -22,18 +22,19 @@ compatible = "adc-keys"; io-channels = <&saradc 2>; io-channel-names = "buttons"; + poll-interval = <100>; keyup-threshold-microvolt = <1800000>; - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <10000>; - }; - vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <170000>; + press-threshold-microvolt = <290000>; + }; + + vol-up-key { + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <17000>; }; }; @@ -539,6 +540,7 @@ &saradc { status = "okay"; + vref-supply = <&vcc1v8_soc>; }; &sdmmc { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 1d3b99554550..b24b015c10b4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -22,36 +22,37 @@ compatible = "adc-keys"; io-channels = <&saradc 2>; io-channel-names = "buttons"; + poll-interval = <100>; keyup-threshold-microvolt = <1800000>; - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <10000>; - }; - - vol-down-key { - linux,code = ; - label = "volume down"; - press-threshold-microvolt = <170000>; + esc-key { + linux,code = ; + label = "esc"; + press-threshold-microvolt = <1270000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <254000>; + press-threshold-microvolt = <602000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <414000>; + press-threshold-microvolt = <952000>; }; - esc-key { - linux,code = ; - label = "esc"; - press-threshold-microvolt = <614000>; + vol-down-key { + linux,code = ; + label = "volume down"; + press-threshold-microvolt = <290000>; + }; + + vol-up-key { + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <17000>; }; }; @@ -665,6 +666,7 @@ &saradc { status = "okay"; + vref-supply = <&vcc1v8_soc>; }; &sdmmc { From 92b2aac00e81536dc63846d619d0fa1460321177 Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Thu, 8 Feb 2018 15:52:30 +0800 Subject: [PATCH 294/427] arm64: dts: rockchip: Disabeld cif for rk3326 evb board Change-Id: Iebd5858561720521a863bacf5331ace3b89d1150 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index b24b015c10b4..b532b1ad9fdd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -184,14 +184,6 @@ }; }; -&cif { - status = "okay"; -}; - -&cif_sensor { - status = "okay"; -}; - &cpu0 { cpu-supply = <&vdd_arm>; }; From 02213b12e1fc7900b39b014d46578e5e5c566d06 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 6 Feb 2018 16:45:09 +0800 Subject: [PATCH 295/427] ASoC: codec: add rk3228 internal codec Change-Id: Icf83257726f12558cbdde4d4b2876dc8a3123626 Signed-off-by: Sugar Zhang --- .../bindings/sound/rockchip,rk3228-codec.txt | 22 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rk3228_codec.c | 549 ++++++++++++++++++ sound/soc/codecs/rk3228_codec.h | 218 +++++++ 5 files changed, 796 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt create mode 100644 sound/soc/codecs/rk3228_codec.c create mode 100644 sound/soc/codecs/rk3228_codec.h diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt new file mode 100644 index 000000000000..9191a8593380 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt @@ -0,0 +1,22 @@ +* Rockchip Rk3228 internal codec + +Required properties: + +- compatible: "rockchip,rk3228-codec" +- reg: physical base address of the controller and length of memory mapped + region. +- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. +- clock-names: a list of clock names, one for each entry in clocks. +- spk-en-gpio: speaker enable gpio. +- spk-depop-time-ms: speaker depop time msec. + +Example for rk3228 internal codec: + +codec: codec@12010000 { + compatible = "rockchip,rk3228-codec"; + reg = <0x12010000 0x1000>; + clocks = <&cru SCLK_I2S_OUT>, <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>; + clock-names = "mclk", "pclk", "sclk"; + spk-en-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a6ac14935374..0f65f46ee57e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -94,6 +94,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM512x_I2C if I2C select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_RK1000 if I2C + select SND_SOC_RK3228 select SND_SOC_RK3328 select SND_SOC_RT286 if I2C select SND_SOC_RT298 if I2C @@ -579,6 +580,10 @@ config SND_SOC_RK312X select REGMAP_MMIO tristate "Rockchip RK312X CODEC" +config SND_SOC_RK3228 + select REGMAP_MMIO + tristate "Rockchip RK3228 CODEC" + config SND_SOC_RK3328 select REGMAP_MMIO tristate "Rockchip RK3328 CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f4cb89f21e7a..edf27ede08da 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -92,6 +92,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-rk1000-objs := rk1000_codec.o snd-soc-rk312x-objs := rk312x_codec.o +snd-soc-rk3228-objs := rk3228_codec.o snd-soc-rk3328-objs := rk3328_codec.o snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o @@ -301,6 +302,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o +obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o diff --git a/sound/soc/codecs/rk3228_codec.c b/sound/soc/codecs/rk3228_codec.c new file mode 100644 index 000000000000..9c0c831b5bcf --- /dev/null +++ b/sound/soc/codecs/rk3228_codec.c @@ -0,0 +1,549 @@ +/* + * rk3228_codec.c -- rk3228 ALSA Soc Audio driver + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk3228_codec.h" + +/* + * volume setting + * 0: -39dB + * 26: 0dB + * 31: 6dB + * Step: 1.5dB + */ +#define OUT_VOLUME (0x18) +#define INITIAL_FREQ (11289600) + +struct rk3228_codec_priv { + struct regmap *regmap; + struct clk *mclk; + struct clk *pclk; + struct clk *sclk; + struct gpio_desc *spk_en_gpio; + int spk_depop_time; /* msec */ +}; + +static const struct reg_default rk3228_codec_reg_defaults[] = { + { CODEC_RESET, 0x03 }, + { DAC_INIT_CTRL1, 0x00 }, + { DAC_INIT_CTRL2, 0x50 }, + { DAC_INIT_CTRL3, 0x0e }, + { DAC_PRECHARGE_CTRL, 0x01 }, + { DAC_PWR_CTRL, 0x00 }, + { DAC_CLK_CTRL, 0x00 }, + { HPMIX_CTRL, 0x00 }, + { HPOUT_CTRL, 0x00 }, + { HPOUTL_GAIN_CTRL, 0x00 }, + { HPOUTR_GAIN_CTRL, 0x00 }, + { HPOUT_POP_CTRL, 0x11 }, +}; + +static int rk3228_codec_reset(struct snd_soc_codec *codec) +{ + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + + regmap_write(rk3228->regmap, CODEC_RESET, 0); + mdelay(10); + regmap_write(rk3228->regmap, CODEC_RESET, 0x03); + + return 0; +} + +static int rk3228_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + val |= PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE; + break; + case SND_SOC_DAIFMT_CBM_CFM: + val |= PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL1, + PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val); + + val = 0; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + val |= DAC_MODE_PCM; + break; + case SND_SOC_DAIFMT_I2S: + val |= DAC_MODE_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + val |= DAC_MODE_RJM; + break; + case SND_SOC_DAIFMT_LEFT_J: + val |= DAC_MODE_LJM; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL2, + DAC_MODE_MASK, val); + return 0; +} + +static void rk3228_analog_output(struct rk3228_codec_priv *rk3228, int mute) +{ + if (rk3228->spk_en_gpio) + gpiod_set_value(rk3228->spk_en_gpio, mute); +} + +static int rk3228_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0; + + if (mute) + val = HPOUTL_MUTE | HPOUTR_MUTE; + else + val = HPOUTL_UNMUTE | HPOUTR_UNMUTE; + + regmap_update_bits(rk3228->regmap, HPOUT_CTRL, + HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val); + return 0; +} + +static int rk3228_codec_power_on(struct snd_soc_codec *codec, int wait_ms) +{ + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE); + mdelay(10); + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_CURRENT_ALL_MASK, + DAC_CHARGE_CURRENT_ALL_ON); + + mdelay(wait_ms); + + return 0; +} + +static int rk3228_codec_power_off(struct snd_soc_codec *codec, int wait_ms) +{ + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE); + mdelay(10); + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_CURRENT_ALL_MASK, + DAC_CHARGE_CURRENT_ALL_ON); + + mdelay(wait_ms); + + return 0; +} + +static struct rk3228_reg_msk_val playback_open_list[] = { + { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON }, + { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, + DACL_PATH_REFV_ON | DACR_PATH_REFV_ON }, + { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON, + HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON }, + { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, + HPOUTR_POP_WORK | HPOUTL_POP_WORK }, + { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN }, + { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, + HPMIXL_INIT_EN | HPMIXR_INIT_EN }, + { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN }, + { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, + HPOUTL_INIT_EN | HPOUTR_INIT_EN }, + { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, + DACL_REFV_ON | DACR_REFV_ON }, + { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, + DACL_CLK_ON | DACR_CLK_ON }, + { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON }, + { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, + DACL_INIT_ON | DACR_INIT_ON }, + { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, + DACL_SELECT | DACR_SELECT }, + { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, + HPMIXL_INIT2_EN | HPMIXR_INIT2_EN }, + { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, + HPOUTL_UNMUTE | HPOUTR_UNMUTE }, +}; + +#define PLAYBACK_OPEN_LIST_LEN ARRAY_SIZE(playback_open_list) + +static int rk3228_codec_open_playback(struct snd_soc_codec *codec) +{ + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + int i = 0; + + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_CURRENT_ALL_MASK, + DAC_CHARGE_CURRENT_I); + + for (i = 0; i < PLAYBACK_OPEN_LIST_LEN; i++) { + regmap_update_bits(rk3228->regmap, + playback_open_list[i].reg, + playback_open_list[i].msk, + playback_open_list[i].val); + mdelay(1); + } + + msleep(rk3228->spk_depop_time); + rk3228_analog_output(rk3228, 1); + + regmap_update_bits(rk3228->regmap, HPOUTL_GAIN_CTRL, + HPOUTL_GAIN_MASK, OUT_VOLUME); + regmap_update_bits(rk3228->regmap, HPOUTR_GAIN_CTRL, + HPOUTR_GAIN_MASK, OUT_VOLUME); + return 0; +} + +static struct rk3228_reg_msk_val playback_close_list[] = { + { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, + HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS }, + { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, + DACL_DESELECT | DACR_DESELECT }, + { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, + HPOUTL_MUTE | HPOUTR_MUTE }, + { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, + HPOUTL_INIT_DIS | HPOUTR_INIT_DIS }, + { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS }, + { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS }, + { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF }, + { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, + DACL_CLK_OFF | DACR_CLK_OFF }, + { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, + DACL_REFV_OFF | DACR_REFV_OFF }, + { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, + HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE }, + { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, + DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF }, + { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF }, + { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, + HPMIXL_INIT_DIS | HPMIXR_INIT_DIS }, + { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, + DACL_INIT_OFF | DACR_INIT_OFF }, +}; + +#define PLAYBACK_CLOSE_LIST_LEN ARRAY_SIZE(playback_close_list) + +static int rk3228_codec_close_playback(struct snd_soc_codec *codec) +{ + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + int i = 0; + + rk3228_analog_output(rk3228, 0); + + regmap_update_bits(rk3228->regmap, HPOUTL_GAIN_CTRL, + HPOUTL_GAIN_MASK, 0); + regmap_update_bits(rk3228->regmap, HPOUTR_GAIN_CTRL, + HPOUTR_GAIN_MASK, 0); + + for (i = 0; i < PLAYBACK_CLOSE_LIST_LEN; i++) { + regmap_update_bits(rk3228->regmap, + playback_close_list[i].reg, + playback_close_list[i].msk, + playback_close_list[i].val); + mdelay(1); + } + + regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL, + DAC_CHARGE_CURRENT_ALL_MASK, + DAC_CHARGE_CURRENT_I); + return 0; +} + +static int rk3228_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct rk3228_codec_priv *rk3228 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + val |= DAC_VDL_16BITS; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + val |= DAC_VDL_20BITS; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val |= DAC_VDL_24BITS; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val |= DAC_VDL_32BITS; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val); + val = DAC_WL_32BITS | DAC_RST_DIS; + regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL3, + DAC_WL_MASK | DAC_RST_MASK, val); + + return 0; +} + +static int rk3228_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + + return rk3228_codec_open_playback(codec); +} + +static void rk3228_pcm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + + rk3228_codec_close_playback(codec); +} + +static struct snd_soc_dai_ops rk3228_dai_ops = { + .hw_params = rk3228_hw_params, + .set_fmt = rk3228_set_dai_fmt, + .digital_mute = rk3228_digital_mute, + .startup = rk3228_pcm_startup, + .shutdown = rk3228_pcm_shutdown, +}; + +static struct snd_soc_dai_driver rk3228_dai[] = { + { + .name = "rk3228-hifi", + .id = RK3228_HIFI, + .playback = { + .stream_name = "HIFI Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + }, + .ops = &rk3228_dai_ops, + }, +}; + +static int rk3228_codec_probe(struct snd_soc_codec *codec) +{ + rk3228_codec_reset(codec); + rk3228_codec_power_on(codec, 0); + + return 0; +} + +static int rk3228_codec_remove(struct snd_soc_codec *codec) +{ + rk3228_codec_close_playback(codec); + rk3228_codec_power_off(codec, 0); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_rk3228 = { + .probe = rk3228_codec_probe, + .remove = rk3228_codec_remove, +}; + +static bool rk3228_codec_write_read_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CODEC_RESET: + case DAC_INIT_CTRL1: + case DAC_INIT_CTRL2: + case DAC_INIT_CTRL3: + case DAC_PRECHARGE_CTRL: + case DAC_PWR_CTRL: + case DAC_CLK_CTRL: + case HPMIX_CTRL: + case DAC_SELECT: + case HPOUT_CTRL: + case HPOUTL_GAIN_CTRL: + case HPOUTR_GAIN_CTRL: + case HPOUT_POP_CTRL: + return true; + default: + return false; + } +} + +static bool rk3228_codec_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CODEC_RESET: + return true; + default: + return false; + } +} + +static const struct regmap_config rk3228_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = HPOUT_POP_CTRL, + .writeable_reg = rk3228_codec_write_read_reg, + .readable_reg = rk3228_codec_write_read_reg, + .volatile_reg = rk3228_codec_volatile_reg, + .reg_defaults = rk3228_codec_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rk3228_codec_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +#ifdef CONFIG_OF +static const struct of_device_id rk3228codec_of_match[] = { + { .compatible = "rockchip,rk3228-codec", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rk3228codec_of_match); +#endif + +static int rk3228_platform_probe(struct platform_device *pdev) +{ + struct device_node *rk3228_np = pdev->dev.of_node; + struct rk3228_codec_priv *rk3228; + struct resource *res; + void __iomem *base; + int ret = 0; + + rk3228 = devm_kzalloc(&pdev->dev, sizeof(*rk3228), GFP_KERNEL); + if (!rk3228) + return -ENOMEM; + + rk3228->mclk = devm_clk_get(&pdev->dev, "mclk"); + if (PTR_ERR(rk3228->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + rk3228->pclk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(rk3228->pclk)) + return PTR_ERR(rk3228->pclk); + + rk3228->sclk = devm_clk_get(&pdev->dev, "sclk"); + if (IS_ERR(rk3228->sclk)) + return PTR_ERR(rk3228->sclk); + + rk3228->spk_en_gpio = devm_gpiod_get_optional(&pdev->dev, + "spk-en", + GPIOD_OUT_LOW); + if (IS_ERR(rk3228->spk_en_gpio)) + return PTR_ERR(rk3228->spk_en_gpio); + + ret = of_property_read_u32(rk3228_np, "spk-depop-time-ms", + &rk3228->spk_depop_time); + if (ret < 0) { + dev_info(&pdev->dev, "spk_depop_time use default value.\n"); + rk3228->spk_depop_time = 200; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + ret = clk_prepare_enable(rk3228->mclk); + if (ret) + return ret; + + ret = clk_prepare_enable(rk3228->pclk); + if (ret < 0) + goto err_pclk; + + ret = clk_prepare_enable(rk3228->sclk); + if (ret) + goto err_sclk; + + clk_set_rate(rk3228->sclk, INITIAL_FREQ); + + rk3228->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &rk3228_codec_regmap_config); + if (IS_ERR(rk3228->regmap)) { + ret = PTR_ERR(rk3228->regmap); + goto err_clk; + } + + platform_set_drvdata(pdev, rk3228); + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3228, + rk3228_dai, ARRAY_SIZE(rk3228_dai)); + + if (!ret) + return 0; + +err_clk: + clk_disable_unprepare(rk3228->sclk); +err_sclk: + clk_disable_unprepare(rk3228->pclk); +err_pclk: + clk_disable_unprepare(rk3228->mclk); + + return ret; +} + +static int rk3228_platform_remove(struct platform_device *pdev) +{ + struct rk3228_codec_priv *rk3228 = platform_get_drvdata(pdev); + + if (!IS_ERR(rk3228->mclk)) + clk_disable_unprepare(rk3228->mclk); + + if (!IS_ERR(rk3228->pclk)) + clk_disable_unprepare(rk3228->pclk); + + if (!IS_ERR(rk3228->sclk)) + clk_disable_unprepare(rk3228->sclk); + + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver rk3228_codec_driver = { + .driver = { + .name = "rk3228-codec", + .of_match_table = of_match_ptr(rk3228codec_of_match), + }, + .probe = rk3228_platform_probe, + .remove = rk3228_platform_remove, +}; +module_platform_driver(rk3228_codec_driver); + +MODULE_AUTHOR("Sugar Zhang "); +MODULE_DESCRIPTION("ASoC rk3228 codec driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rk3228_codec.h b/sound/soc/codecs/rk3228_codec.h new file mode 100644 index 000000000000..7283d0ba86e8 --- /dev/null +++ b/sound/soc/codecs/rk3228_codec.h @@ -0,0 +1,218 @@ +/* + * rk3228_codec.h -- rk3228 ALSA Soc Audio driver + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef _RK3228_CODEC_H +#define _RK3228_CODEC_H + +/* codec register */ +#define CODEC_RESET (0x00 << 2) +#define DAC_INIT_CTRL1 (0x03 << 2) +#define DAC_INIT_CTRL2 (0x04 << 2) +#define DAC_INIT_CTRL3 (0x05 << 2) +#define DAC_PRECHARGE_CTRL (0x22 << 2) +#define DAC_PWR_CTRL (0x23 << 2) +#define DAC_CLK_CTRL (0x24 << 2) +#define HPMIX_CTRL (0x25 << 2) +#define DAC_SELECT (0x26 << 2) +#define HPOUT_CTRL (0x27 << 2) +#define HPOUTL_GAIN_CTRL (0x28 << 2) +#define HPOUTR_GAIN_CTRL (0x29 << 2) +#define HPOUT_POP_CTRL (0x2a << 2) + +/* REG00: CODEC_RESET */ +#define PWR_RST_BYPASS_DIS BIT(6) +#define PWR_RST_BYPASS_EN BIT(6) +#define DIG_CORE_RST (0 << 1) +#define DIG_CORE_WORK BIT(1) +#define SYS_RST (0) +#define SYS_WORK BIT(0) + +/* REG03: DAC_INIT_CTRL1 */ +#define PIN_DIRECTION_MASK BIT(5) +#define PIN_DIRECTION_IN (0 << 5) +#define PIN_DIRECTION_OUT BIT(5) +#define DAC_I2S_MODE_MASK BIT(4) +#define DAC_I2S_MODE_SLAVE (0 << 4) +#define DAC_I2S_MODE_MASTER BIT(4) + +/* REG04: DAC_INIT_CTRL2 */ +#define DAC_I2S_LRP_MASK BIT(7) +#define DAC_I2S_LRP_NORMAL (0 << 7) +#define DAC_I2S_LRP_REVERSAL BIT(7) +#define DAC_VDL_MASK (3 << 5) +#define DAC_VDL_16BITS (0 << 5) +#define DAC_VDL_20BITS BIT(5) +#define DAC_VDL_24BITS (2 << 5) +#define DAC_VDL_32BITS (3 << 5) +#define DAC_MODE_MASK (3 << 3) +#define DAC_MODE_RJM (0 << 3) +#define DAC_MODE_LJM BIT(3) +#define DAC_MODE_I2S (2 << 3) +#define DAC_MODE_PCM (3 << 3) +#define DAC_LR_SWAP_MASK BIT(2) +#define DAC_LR_SWAP_DIS (0 << 2) +#define DAC_LR_SWAP_EN BIT(2) + +/* REG05: DAC_INIT_CTRL3 */ +#define DAC_WL_MASK (3 << 2) +#define DAC_WL_16BITS (0 << 2) +#define DAC_WL_20BITS BIT(2) +#define DAC_WL_24BITS (2 << 2) +#define DAC_WL_32BITS (3 << 2) +#define DAC_RST_MASK BIT(1) +#define DAC_RST_EN (0 << 1) +#define DAC_RST_DIS BIT(1) +#define DAC_BCP_MASK BIT(0) +#define DAC_BCP_NORMAL (0 << 0) +#define DAC_BCP_REVERSAL BIT(0) + +/* REG22: DAC_PRECHARGE_CTRL */ +#define DAC_CHARGE_PRECHARGE BIT(7) +#define DAC_CHARGE_DISCHARGE (0 << 7) +#define DAC_CHARGE_XCHARGE_MASK BIT(7) +#define DAC_CHARGE_CURRENT_64I BIT(6) +#define DAC_CHARGE_CURRENT_64I_MASK BIT(6) +#define DAC_CHARGE_CURRENT_32I BIT(5) +#define DAC_CHARGE_CURRENT_32I_MASK BIT(5) +#define DAC_CHARGE_CURRENT_16I BIT(4) +#define DAC_CHARGE_CURRENT_16I_MASK BIT(4) +#define DAC_CHARGE_CURRENT_08I BIT(3) +#define DAC_CHARGE_CURRENT_08I_MASK BIT(3) +#define DAC_CHARGE_CURRENT_04I BIT(2) +#define DAC_CHARGE_CURRENT_04I_MASK BIT(2) +#define DAC_CHARGE_CURRENT_02I BIT(1) +#define DAC_CHARGE_CURRENT_02I_MASK BIT(1) +#define DAC_CHARGE_CURRENT_I BIT(0) +#define DAC_CHARGE_CURRENT_I_MASK BIT(0) +#define DAC_CHARGE_CURRENT_ALL_MASK (0x7f) +#define DAC_CHARGE_CURRENT_ALL_OFF (0x0) +#define DAC_CHARGE_CURRENT_ALL_ON (0x7f) + +/* REG23: DAC_PWR_CTRL */ +#define DAC_PWR_OFF (0 << 6) +#define DAC_PWR_ON BIT(6) +#define DAC_PWR_MASK BIT(6) +#define DACL_PATH_REFV_OFF (0 << 5) +#define DACL_PATH_REFV_ON BIT(5) +#define DACL_PATH_REFV_MASK BIT(5) +#define HPOUTL_ZERO_CROSSING_OFF (0 << 4) +#define HPOUTL_ZERO_CROSSING_ON BIT(4) +#define DACR_PATH_REFV_OFF (0 << 1) +#define DACR_PATH_REFV_ON BIT(1) +#define DACR_PATH_REFV_MASK BIT(1) +#define HPOUTR_ZERO_CROSSING_OFF (0 << 0) +#define HPOUTR_ZERO_CROSSING_ON BIT(0) + +/* REG24: DAC_CLK_CTRL */ +#define DACL_REFV_OFF (0 << 7) +#define DACL_REFV_ON BIT(7) +#define DACL_REFV_MASK BIT(7) +#define DACL_CLK_OFF (0 << 6) +#define DACL_CLK_ON BIT(6) +#define DACL_CLK_MASK BIT(6) +#define DACL_OFF (0 << 5) +#define DACL_ON BIT(5) +#define DACL_MASK BIT(5) +#define DACL_INIT_OFF (0 << 4) +#define DACL_INIT_ON BIT(4) +#define DACL_INIT_MASK BIT(4) +#define DACR_REFV_OFF (0 << 3) +#define DACR_REFV_ON BIT(3) +#define DACR_REFV_MASK BIT(3) +#define DACR_CLK_OFF (0 << 2) +#define DACR_CLK_ON BIT(2) +#define DACR_CLK_MASK BIT(2) +#define DACR_OFF (0 << 1) +#define DACR_ON BIT(1) +#define DACR_MASK BIT(1) +#define DACR_INIT_OFF (0 << 0) +#define DACR_INIT_ON BIT(0) +#define DACR_INIT_MASK BIT(0) + +/* REG25: HPMIX_CTRL*/ +#define HPMIXL_DIS (0 << 6) +#define HPMIXL_EN BIT(6) +#define HPMIXL_MASK BIT(6) +#define HPMIXL_INIT_DIS (0 << 5) +#define HPMIXL_INIT_EN BIT(5) +#define HPMIXL_INIT_MASK BIT(5) +#define HPMIXL_INIT2_DIS (0 << 4) +#define HPMIXL_INIT2_EN BIT(4) +#define HPMIXL_INIT2_MASK BIT(4) +#define HPMIXR_DIS (0 << 2) +#define HPMIXR_EN BIT(2) +#define HPMIXR_MASK BIT(2) +#define HPMIXR_INIT_DIS (0 << 1) +#define HPMIXR_INIT_EN BIT(1) +#define HPMIXR_INIT_MASK BIT(1) +#define HPMIXR_INIT2_DIS (0 << 0) +#define HPMIXR_INIT2_EN BIT(0) +#define HPMIXR_INIT2_MASK BIT(0) + +/* REG26: DAC_SELECT */ +#define DACL_SELECT BIT(4) +#define DACL_SELECT_MASK BIT(4) +#define DACL_DESELECT (0 << 4) +#define DACR_SELECT BIT(0) +#define DACR_SELECT_MASK BIT(0) +#define DACR_DESELECT (0 << 0) + +/* REG27: HPOUT_CTRL */ +#define HPOUTL_DIS (0 << 7) +#define HPOUTL_EN BIT(7) +#define HPOUTL_MASK BIT(7) +#define HPOUTL_INIT_DIS (0 << 6) +#define HPOUTL_INIT_EN BIT(6) +#define HPOUTL_INIT_MASK BIT(6) +#define HPOUTL_MUTE (0 << 5) +#define HPOUTL_UNMUTE BIT(5) +#define HPOUTL_MUTE_MASK BIT(5) +#define HPOUTR_DIS (0 << 4) +#define HPOUTR_EN BIT(4) +#define HPOUTR_MASK BIT(4) +#define HPOUTR_INIT_DIS (0 << 3) +#define HPOUTR_INIT_EN BIT(3) +#define HPOUTR_INIT_MASK BIT(3) +#define HPOUTR_MUTE (0 << 2) +#define HPOUTR_UNMUTE BIT(2) +#define HPOUTR_MUTE_MASK BIT(2) + +/* REG28: HPOUTL_GAIN_CTRL */ +#define HPOUTL_GAIN_MASK (0X1f << 0) + +/* REG29: HPOUTR_GAIN_CTRL */ +#define HPOUTR_GAIN_MASK (0X1f << 0) + +/* REG2a: HPOUT_POP_CTRL */ +#define HPOUTR_POP_XCHARGE BIT(4) +#define HPOUTR_POP_WORK (2 << 4) +#define HPOUTR_POP_MASK (3 << 4) +#define HPOUTL_POP_XCHARGE BIT(0) +#define HPOUTL_POP_WORK (2 << 0) +#define HPOUTL_POP_MASK (3 << 0) + +#define RK3228_HIFI (0) + +struct rk3228_reg_msk_val { + unsigned int reg; + unsigned int msk; + unsigned int val; +}; + +#endif From 4d4dfc7e3c6d95142fa02ccfe52ae00682b459c9 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 6 Feb 2018 16:33:09 +0800 Subject: [PATCH 296/427] ARM: dts: rockchip: rk322x: add internal codec Change-Id: I3d376232d02770c72be396487a7481fe8fcbede5 Signed-off-by: Sugar Zhang --- arch/arm/boot/dts/rk322x.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 790226c01977..efce2dd2b7d7 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -655,6 +655,15 @@ status = "disabled"; }; + codec: codec@12010000 { + compatible = "rockchip,rk3228-codec"; + reg = <0x12010000 0x1000>; + clocks = <&cru SCLK_I2S_OUT>, <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>; + clock-names = "mclk", "pclk", "sclk"; + spk-en-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + hdmi_phy: hdmi-phy@12030000 { compatible = "rockchip,rk3228-hdmi-phy"; reg = <0x12030000 0x10000>; From 245adad7ad0e814e21060ea59212e13cf85ed03f Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 6 Feb 2018 14:31:36 +0800 Subject: [PATCH 297/427] ARM: dts: rockchip: rk3229-evb: add internal sound card Change-Id: I60fe52867a60548dbe2d476b2fc161fc13ec8fc1 Signed-off-by: Sugar Zhang --- arch/arm/boot/dts/rk3229-evb.dts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rk3229-evb.dts b/arch/arm/boot/dts/rk3229-evb.dts index 40587d53b99a..ffe32522e3ec 100644 --- a/arch/arm/boot/dts/rk3229-evb.dts +++ b/arch/arm/boot/dts/rk3229-evb.dts @@ -84,6 +84,19 @@ }; }; + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "rockchip,rk3229"; + simple-audio-card,cpu { + sound-dai = <&i2s1>; + }; + simple-audio-card,codec { + sound-dai = <&codec>; + }; + }; + hdmi_sound: hdmi-sound { status = "okay"; compatible = "simple-audio-card"; @@ -266,6 +279,16 @@ #sound-dai-cells = <0>; }; +&i2s1 { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&codec { + #sound-dai-cells = <0>; + status = "okay"; +}; + &pinctrl { keys { pwr_key: pwr-key { From 7a53209b74ccd0cc8dc65d0754a61e7e1bfa3322 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 6 Feb 2018 16:34:57 +0800 Subject: [PATCH 298/427] ARM: configs: rockchip_defconfig: add rk3228 internal codec Change-Id: I7f6cf60a7881a3452a92ce08f9637e52f93627f8 Signed-off-by: Sugar Zhang --- arch/arm/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index ad0b5f897342..0767deb0640a 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -466,6 +466,7 @@ CONFIG_SND_SOC_BT_SCO=y CONFIG_SND_SOC_ES8316=y CONFIG_SND_SOC_GVA_CODEC=y CONFIG_SND_SOC_RK312X=y +CONFIG_SND_SOC_RK3228=y CONFIG_SND_SOC_RT5640=y CONFIG_SND_SOC_RT5651=y CONFIG_SND_SOC_SPDIF=y From 8c4db84a0aa89dfe0d905ae988aea13b72fd9335 Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sun, 14 Jan 2018 00:13:15 +0800 Subject: [PATCH 299/427] ASoC: rockchip: add support for rk817 codec Change-Id: I4fd64900d3ac0e573371af5ba47a3cb7b83a7c93 Signed-off-by: Binyuan Lan --- .../bindings/sound/rockchip,rk817-codec.txt | 34 + drivers/mfd/rk808.c | 4 + sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rk817_codec.c | 919 ++++++++++++++++++ sound/soc/codecs/rk817_codec.h | 180 ++++ 6 files changed, 1145 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt create mode 100644 sound/soc/codecs/rk817_codec.c create mode 100644 sound/soc/codecs/rk817_codec.h diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt new file mode 100644 index 000000000000..95f9430b1757 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt @@ -0,0 +1,34 @@ +* Rockchip rk817 codec + +Required properties: + +- compatible: "rockchip,rk817-codec" +- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. +- clock-names: should be "mclk". + + +Example for rk817 codec: + +rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + + ........ + + rk817_codec: rk817-codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_8ch_mclk>; + status = "okay"; + }; + + ........ + +}; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd9adae77a42..a37ebd70e334 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -767,6 +767,10 @@ static const struct mfd_cell rk817s[] = { .num_resources = ARRAY_SIZE(rk817_rtc_resources), .resources = &rk817_rtc_resources[0], }, + { + .name = "rk817-codec", + .of_compatible = "rockchip,rk817-codec", + }, }; static const struct rk808_reg_data rk817_pre_init_reg[] = { diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0f65f46ee57e..30313b9f9087 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -96,6 +96,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RK1000 if I2C select SND_SOC_RK3228 select SND_SOC_RK3328 + select SND_SOC_RK817 if I2C select SND_SOC_RT286 if I2C select SND_SOC_RT298 if I2C select SND_SOC_RT5616 if I2C @@ -588,6 +589,11 @@ config SND_SOC_RK3328 select REGMAP_MMIO tristate "Rockchip RK3328 CODEC" +config SND_SOC_RK817 + tristate "Rockchip RK817 CODEC" + depends on MFD_RK808 + select REGMAP_I2C + config SND_SOC_RL6231 tristate default y if SND_SOC_RT5616=y diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index edf27ede08da..042a9705da12 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -94,6 +94,7 @@ snd-soc-rk1000-objs := rk1000_codec.o snd-soc-rk312x-objs := rk312x_codec.o snd-soc-rk3228-objs := rk3228_codec.o snd-soc-rk3328-objs := rk3328_codec.o +snd-soc-rk817-objs := rk817_codec.o snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt286-objs := rt286.o @@ -304,6 +305,7 @@ obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o +obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c new file mode 100644 index 000000000000..c1f862966ab8 --- /dev/null +++ b/sound/soc/codecs/rk817_codec.c @@ -0,0 +1,919 @@ +/* + * Copyright (c) 2018 Rockchip Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk817_codec.h" + +static int dbg_enable; +module_param_named(dbg_level, dbg_enable, int, 0644); + +#define DBG(args...) \ + do { \ + if (dbg_enable) { \ + pr_info(args); \ + } \ + } while (0) + +/* For route */ +#define RK817_CODEC_PLAYBACK 1 +#define RK817_CODEC_CAPTURE 2 +#define RK817_CODEC_INCALL 4 +#define RK817_CODEC_ALL (RK817_CODEC_PLAYBACK |\ + RK817_CODEC_CAPTURE | RK817_CODEC_INCALL) + +/* + * DDAC L/R volume setting + * 0: 0dB + * 0x0a:-3.75dB + * 0x7d: -46dB + * 0xff: -95dB + * Step: 0.375dB + */ +#define OUT_VOLUME (0x03) + +/* + * DADC L/R volume setting + * 0: 0dB + * 0x0a:-3.75dB + * 0x7d: -46dB + * 0xff: -95dB + * Step: 0.375dB + */ +#define CAPTURE_VOLUME (0x0) + +struct rk817_codec_priv { + struct snd_soc_codec *codec; + struct regmap *regmap; + struct rk808 *rk817; + struct clk *mclk; + + unsigned int stereo_sysclk; + unsigned int rate; + + unsigned int spk_volume; + unsigned int hp_volume; + unsigned int capture_volume; + + long int playback_path; + long int capture_path; +}; + +static struct rk817_codec_priv *rk817_priv; + +static const struct reg_default rk817_reg_defaults[] = { + { RK817_CODEC_DTOP_VUCTL, 0x003 }, + { RK817_CODEC_DTOP_VUCTIME, 0x00 }, + { RK817_CODEC_DTOP_LPT_SRST, 0x00 }, + { RK817_CODEC_DTOP_DIGEN_CLKE, 0x00 }, + { RK817_CODEC_AREF_RTCFG0, 0x00 }, + { RK817_CODEC_AREF_RTCFG1, 0x06 }, + { RK817_CODEC_AADC_CFG0, 0xc8 }, + { RK817_CODEC_AADC_CFG1, 0x00 }, + { RK817_CODEC_DADC_VOLL, 0x00 }, + { RK817_CODEC_DADC_VOLR, 0x00 }, + { RK817_CODEC_DADC_SR_ACL0, 0x00 }, + { RK817_CODEC_DADC_ALC1, 0x00 }, + { RK817_CODEC_DADC_ALC2, 0x00 }, + { RK817_CODEC_DADC_NG, 0x00 }, + { RK817_CODEC_DADC_HPF, 0x00 }, + { RK817_CODEC_DADC_RVOLL, 0xff }, + { RK817_CODEC_DADC_RVOLR, 0xff }, + { RK817_CODEC_AMIC_CFG0, 0x70 }, + { RK817_CODEC_AMIC_CFG1, 0x00 }, + { RK817_CODEC_DMIC_PGA_GAIN, 0x66 }, + { RK817_CODEC_DMIC_LMT1, 0x00 }, + { RK817_CODEC_DMIC_LMT2, 0x00 }, + { RK817_CODEC_DMIC_NG1, 0x00 }, + { RK817_CODEC_DMIC_NG2, 0x00 }, + { RK817_CODEC_ADAC_CFG0, 0x00 }, + { RK817_CODEC_ADAC_CFG1, 0x07 }, + { RK817_CODEC_DDAC_POPD_DACST, 0x82 }, + { RK817_CODEC_DDAC_VOLL, 0x00 }, + { RK817_CODEC_DDAC_VOLR, 0x00 }, + { RK817_CODEC_DDAC_SR_LMT0, 0x00 }, + { RK817_CODEC_DDAC_LMT1, 0x00 }, + { RK817_CODEC_DDAC_LMT2, 0x00 }, + { RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa0 }, + { RK817_CODEC_DDAC_RVOLL, 0xff }, + { RK817_CODEC_DDAC_RVOLR, 0xff }, + { RK817_CODEC_AHP_ANTI0, 0x00 }, + { RK817_CODEC_AHP_ANTI1, 0x00 }, + { RK817_CODEC_AHP_CFG0, 0xe0 }, + { RK817_CODEC_AHP_CFG1, 0x1f }, + { RK817_CODEC_AHP_CP, 0x09 }, + { RK817_CODEC_ACLASSD_CFG1, 0x69 }, + { RK817_CODEC_ACLASSD_CFG2, 0x44 }, + { RK817_CODEC_APLL_CFG0, 0x04 }, + { RK817_CODEC_APLL_CFG1, 0x00 }, + { RK817_CODEC_APLL_CFG2, 0x30 }, + { RK817_CODEC_APLL_CFG3, 0x19 }, + { RK817_CODEC_APLL_CFG4, 0x65 }, + { RK817_CODEC_APLL_CFG5, 0x01 }, + { RK817_CODEC_DI2S_CKM, 0x01 }, + { RK817_CODEC_DI2S_RSD, 0x00 }, + { RK817_CODEC_DI2S_RXCR1, 0x00 }, + { RK817_CODEC_DI2S_RXCR2, 0x17 }, + { RK817_CODEC_DI2S_RXCMD_TSD, 0x00 }, + { RK817_CODEC_DI2S_TXCR1, 0x00 }, + { RK817_CODEC_DI2S_TXCR2, 0x17 }, + { RK817_CODEC_DI2S_TXCR3_TXCMD, 0x00 }, +}; + +static bool rk817_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RK817_CODEC_DTOP_LPT_SRST: + return true; + default: + return false; + } +} + +static bool rk817_codec_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RK817_CODEC_DTOP_VUCTL: + case RK817_CODEC_DTOP_VUCTIME: + case RK817_CODEC_DTOP_LPT_SRST: + case RK817_CODEC_DTOP_DIGEN_CLKE: + case RK817_CODEC_AREF_RTCFG0: + case RK817_CODEC_AREF_RTCFG1: + case RK817_CODEC_AADC_CFG0: + case RK817_CODEC_AADC_CFG1: + case RK817_CODEC_DADC_VOLL: + case RK817_CODEC_DADC_VOLR: + case RK817_CODEC_DADC_SR_ACL0: + case RK817_CODEC_DADC_ALC1: + case RK817_CODEC_DADC_ALC2: + case RK817_CODEC_DADC_NG: + case RK817_CODEC_DADC_HPF: + case RK817_CODEC_DADC_RVOLL: + case RK817_CODEC_DADC_RVOLR: + case RK817_CODEC_AMIC_CFG0: + case RK817_CODEC_AMIC_CFG1: + case RK817_CODEC_DMIC_PGA_GAIN: + case RK817_CODEC_DMIC_LMT1: + case RK817_CODEC_DMIC_LMT2: + case RK817_CODEC_DMIC_NG1: + case RK817_CODEC_DMIC_NG2: + case RK817_CODEC_ADAC_CFG0: + case RK817_CODEC_ADAC_CFG1: + case RK817_CODEC_DDAC_POPD_DACST: + case RK817_CODEC_DDAC_VOLL: + case RK817_CODEC_DDAC_VOLR: + case RK817_CODEC_DDAC_SR_LMT0: + case RK817_CODEC_DDAC_LMT1: + case RK817_CODEC_DDAC_LMT2: + case RK817_CODEC_DDAC_MUTE_MIXCTL: + case RK817_CODEC_DDAC_RVOLL: + case RK817_CODEC_DDAC_RVOLR: + case RK817_CODEC_AHP_ANTI0: + case RK817_CODEC_AHP_ANTI1: + case RK817_CODEC_AHP_CFG0: + case RK817_CODEC_AHP_CFG1: + case RK817_CODEC_AHP_CP: + case RK817_CODEC_ACLASSD_CFG1: + case RK817_CODEC_ACLASSD_CFG2: + case RK817_CODEC_APLL_CFG0: + case RK817_CODEC_APLL_CFG1: + case RK817_CODEC_APLL_CFG2: + case RK817_CODEC_APLL_CFG3: + case RK817_CODEC_APLL_CFG4: + case RK817_CODEC_APLL_CFG5: + case RK817_CODEC_DI2S_CKM: + case RK817_CODEC_DI2S_RSD: + case RK817_CODEC_DI2S_RXCR1: + case RK817_CODEC_DI2S_RXCR2: + case RK817_CODEC_DI2S_RXCMD_TSD: + case RK817_CODEC_DI2S_TXCR1: + case RK817_CODEC_DI2S_TXCR2: + case RK817_CODEC_DI2S_TXCR3_TXCMD: + return true; + default: + return false; + } +} + +static int rk817_reset(struct snd_soc_codec *codec) +{ + snd_soc_write(codec, RK817_CODEC_DTOP_LPT_SRST, 0x40); + mdelay(10); + + return 0; +} + +static struct rk817_reg_val_typ playback_power_up_list[] = { + {RK817_CODEC_AREF_RTCFG1, 0x40}, + {RK817_CODEC_DDAC_POPD_DACST, 0x02}, + {RK817_CODEC_DDAC_SR_LMT0, 0x02}, + /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f},*/ + /*APLL*/ + {RK817_CODEC_APLL_CFG0, 0x04}, + {RK817_CODEC_APLL_CFG1, 0x58}, + {RK817_CODEC_APLL_CFG2, 0x2d}, + {RK817_CODEC_APLL_CFG3, 0x0c}, + {RK817_CODEC_APLL_CFG4, 0xa5}, + {RK817_CODEC_APLL_CFG5, 0x00}, + + {RK817_CODEC_DI2S_RXCMD_TSD, 0x00}, + {RK817_CODEC_DI2S_RSD, 0x00}, + {RK817_CODEC_DI2S_CKM, 0x00}, + {RK817_CODEC_DI2S_RXCR1, 0x00}, + {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, + {RK817_CODEC_DTOP_VUCTIME, 0xf4}, + + {RK817_CODEC_DDAC_VOLL, 0x0a}, + {RK817_CODEC_DDAC_VOLR, 0x0a}, +}; + +#define RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN \ + ARRAY_SIZE(playback_power_up_list) + +static struct rk817_reg_val_typ playback_power_down_list[] = { + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa1}, + {RK817_CODEC_ADAC_CFG1, 0x0f}, + /* HP */ + {RK817_CODEC_AHP_CFG0, 0xe0}, + {RK817_CODEC_AHP_CP, 0x09}, + /* SPK */ + {RK817_CODEC_ACLASSD_CFG1, 0x69}, +}; + +#define RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN \ + ARRAY_SIZE(playback_power_down_list) + +static struct rk817_reg_val_typ capture_power_up_list[] = { + {RK817_CODEC_AREF_RTCFG1, 0x40}, + {RK817_CODEC_DDAC_SR_LMT0, 0x02}, + {RK817_CODEC_DADC_SR_ACL0, 0x02}, + /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0xff},*/ + {RK817_CODEC_APLL_CFG0, 0x04}, + {RK817_CODEC_APLL_CFG1, 0x58}, + {RK817_CODEC_APLL_CFG2, 0x2d}, + {RK817_CODEC_APLL_CFG3, 0x0c}, + {RK817_CODEC_APLL_CFG4, 0xa5}, + {RK817_CODEC_APLL_CFG5, 0x00}, + + {RK817_CODEC_DI2S_RXCMD_TSD, 0x00}, + {RK817_CODEC_DI2S_RSD, 0x00}, + {RK817_CODEC_DI2S_CKM, 0x00}, + {RK817_CODEC_DI2S_RXCR1, 0x00}, + {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, + {RK817_CODEC_DTOP_VUCTIME, 0xf4}, + + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00}, + {RK817_CODEC_AADC_CFG0, 0x08}, + {RK817_CODEC_AMIC_CFG0, 0x0f}, + {RK817_CODEC_DI2S_TXCR3_TXCMD, 0x88}, + {RK817_CODEC_DDAC_POPD_DACST, 0x02}, + /* 0x29: -18db to 27db*/ + {RK817_CODEC_DMIC_PGA_GAIN, 0xaa}, +}; + +#define RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN \ + ARRAY_SIZE(capture_power_up_list) + +static struct rk817_reg_val_typ capture_power_down_list[] = { + {RK817_CODEC_AADC_CFG0, 0xc8}, + {RK817_CODEC_AMIC_CFG0, 0x70}, +}; + +#define RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN \ + ARRAY_SIZE(capture_power_down_list) + +static int rk817_codec_power_up(int type) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec; + int i; + + codec = rk817->codec; + + dev_info(codec->dev, "%s : power up %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); + + if (type & RK817_CODEC_PLAYBACK) { + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); + for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_up_list[i].reg, + playback_power_up_list[i].value); + usleep_range(1000, 1100); + } + } + + if (type & RK817_CODEC_CAPTURE) { + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); + for (i = 0; i < RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_up_list[i].reg, + capture_power_up_list[i].value); + usleep_range(1000, 1100); + } + snd_soc_write(codec, RK817_CODEC_DADC_VOLL, + rk817->capture_volume); + snd_soc_write(codec, RK817_CODEC_DADC_VOLR, + rk817->capture_volume); + } + + return 0; +} + +static int rk817_codec_power_down(int type) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec; + int i; + + codec = rk817->codec; + + dev_info(codec->dev, "%s : power down %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); + + /* mute output for pop noise */ + if ((type & RK817_CODEC_PLAYBACK) || + (type & RK817_CODEC_INCALL)) { + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_ENABLE); + } + + if (type & RK817_CODEC_CAPTURE) { + for (i = 0; i < RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_down_list[i].reg, + capture_power_down_list[i].value); + } + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); + } + + if (type & RK817_CODEC_PLAYBACK) { + for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_down_list[i].reg, + playback_power_down_list[i].value); + } + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); + } + + if (type == RK817_CODEC_ALL) { + rk817_reset(codec); + snd_soc_write(codec, RK817_CODEC_APLL_CFG5, 0x01); + snd_soc_write(codec, RK817_CODEC_AREF_RTCFG1, 0x06); + } + + return 0; +} + +/* For tiny alsa playback/capture/voice call path */ +static const char * const rk817_playback_path_mode[] = { + "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", /* 0-6 */ + "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"}; /* 7-10 */ + +static const char * const rk817_capture_path_mode[] = { + "MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"}; + +static const char * const rk817_call_path_mode[] = { + "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"}; /* 0-5 */ + +static const char * const rk817_modem_input_mode[] = {"OFF", "ON"}; + +static const SOC_ENUM_SINGLE_DECL(rk817_playback_path_type, + 0, 0, rk817_playback_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_capture_path_type, + 0, 0, rk817_capture_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_call_path_type, + 0, 0, rk817_call_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_modem_input_type, + 0, 0, rk817_modem_input_mode); + +static int rk817_playback_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s : playback_path %ld\n", __func__, rk817->playback_path); + + ucontrol->value.integer.value[0] = rk817->playback_path; + + return 0; +} + +static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + long int pre_path; + + codec->component.regmap = rk817_priv->regmap; + + if (rk817->playback_path == ucontrol->value.integer.value[0]) { + DBG("%s : playback_path is not changed!\n", + __func__); + return 0; + } + + pre_path = rk817->playback_path; + rk817->playback_path = ucontrol->value.integer.value[0]; + + DBG("%s : set playback_path %ld, pre_path %ld\n", + __func__, rk817->playback_path, pre_path); + + switch (rk817->playback_path) { + case OFF: + if (pre_path != OFF) + rk817_codec_power_down(RK817_CODEC_PLAYBACK); + break; + case RCV: + case SPK_PATH: + case RING_SPK: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + /* power on dac ibias/l/r*/ + snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_ON | PWD_DACD_ON | + PWD_DACL_ON | PWD_DACR_ON); + /* CLASS D mode*/ + snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); + /* CLASS D enable*/ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); + /* restart CLASS D, OCPP/N*/ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->spk_volume); + break; + case HP_PATH: + case HP_NO_MIC: + case RING_HP: + case RING_HP_NO_MIC: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + /* HP_CP_EN , CP 2.3V */ + snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); + /* power on HP two stage opamp ,HP amplitude 0db*/ + snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); + /* power on dac ibias/l/r*/ + snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_ON | PWD_DACD_DOWN | + PWD_DACL_ON | PWD_DACR_ON); + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_DISABLE); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); + break; + case BT: + break; + case SPK_HP: + case RING_SPK_HP: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk817_capture_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s : capture_path %ld\n", __func__, + rk817->capture_path); + + ucontrol->value.integer.value[0] = rk817->capture_path; + + return 0; +} + +static int rk817_capture_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct rk817_codec_priv *rk817 = rk817_priv; + long int pre_path; + + codec->component.regmap = rk817_priv->regmap; + + if (rk817->capture_path == ucontrol->value.integer.value[0]) { + DBG("%s : capture_path is not changed!\n", + __func__); + return 0; + } + + pre_path = rk817->capture_path; + rk817->capture_path = ucontrol->value.integer.value[0]; + + DBG("%s : set capture_path %ld, pre_path %ld\n", __func__, + rk817->capture_path, pre_path); + + switch (rk817->capture_path) { + case MIC_OFF: + if (pre_path != MIC_OFF) + rk817_codec_power_down(RK817_CODEC_CAPTURE); + break; + case MAIN_MIC: + if (pre_path == MIC_OFF) + rk817_codec_power_up(RK817_CODEC_CAPTURE); + break; + case HANDS_FREE_MIC: + if (pre_path == MIC_OFF) + rk817_codec_power_up(RK817_CODEC_CAPTURE); + break; + case BT_SCO_MIC: + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct snd_kcontrol_new rk817_snd_path_controls[] = { + SOC_ENUM_EXT("Playback Path", rk817_playback_path_type, + rk817_playback_path_get, rk817_playback_path_put), + + SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type, + rk817_capture_path_get, rk817_capture_path_put), +}; + +static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + rk817->stereo_sysclk = freq; + + DBG("%s : MCLK = %dHz\n", __func__, rk817->stereo_sysclk); + + return 0; +} + +static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int i2s_mst = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + i2s_mst |= RK817_I2S_MODE_SLV; + break; + case SND_SOC_DAIFMT_CBM_CFM: + i2s_mst |= RK817_I2S_MODE_MST; + break; + default: + dev_err(codec->dev, "%s : set master mask failed!\n", + __func__); + return -EINVAL; + } + DBG("%s : i2s %s mode\n", __func__, + i2s_mst ? "master" : "slave"); + + snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM, + RK817_I2S_MODE_MASK, i2s_mst); + + return 0; +} + +static int rk817_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct rk817_codec_priv *rk817 = rk817_priv; + unsigned int rate = params_rate(params); + + DBG("%s : MCLK = %dHz, sample rate = %dHz\n", + __func__, rk817->stereo_sysclk, rate); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_16BITS); + snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_16BITS); + break; + case SNDRV_PCM_FORMAT_S24_LE: + snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_24BITS); + snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_24BITS); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk817_digital_mute(struct snd_soc_dai *dai, int mute) +{ + DBG("%s immediately return for mid\n", __func__); + return 0; +} + +#define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK817_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK817_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops rk817_dai_ops = { + .hw_params = rk817_hw_params, + .set_fmt = rk817_set_dai_fmt, + .set_sysclk = rk817_set_dai_sysclk, + .digital_mute = rk817_digital_mute, +}; + +static struct snd_soc_dai_driver rk817_dai[] = { + { + .name = "rk817-hifi", + .id = RK817_HIFI, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 2, + .channels_max = 8, + .rates = RK817_PLAYBACK_RATES, + .formats = RK817_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 2, + .channels_max = 2, + .rates = RK817_CAPTURE_RATES, + .formats = RK817_FORMATS, + }, + .ops = &rk817_dai_ops, + }, +}; + +static int rk817_suspend(struct snd_soc_codec *codec) +{ + rk817_codec_power_down(RK817_CODEC_ALL); + return 0; +} + +static int rk817_resume(struct snd_soc_codec *codec) +{ + return 0; +} + +static int rk817_probe(struct snd_soc_codec *codec) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(codec->dev, "%s : rk817 priv is NULL!\n", + __func__); + return -EINVAL; + } + codec->component.regmap = rk817_priv->regmap; + rk817->codec = codec; + rk817->playback_path = OFF; + rk817->capture_path = MIC_OFF; + + rk817_reset(codec); + + snd_soc_add_codec_controls(codec, rk817_snd_path_controls, + ARRAY_SIZE(rk817_snd_path_controls)); + return 0; +} + +/* power down chip */ +static int rk817_remove(struct snd_soc_codec *codec) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(codec->dev, "%s : rk817_priv is NULL\n", __func__); + return 0; + } + + rk817_codec_power_down(RK817_CODEC_ALL); + mdelay(10); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_rk817 = { + .probe = rk817_probe, + .remove = rk817_remove, + .suspend = rk817_suspend, + .resume = rk817_resume, +}; + +static int rk817_codec_parse_dt_property(struct device *dev, + struct rk817_codec_priv *rk817) +{ + struct device_node *node = dev->parent->of_node; + int ret; + + DBG("%s()\n", __func__); + + if (!node) { + dev_err(dev, "%s() dev->parent->of_node is NULL\n", + __func__); + return -ENODEV; + } + + node = of_get_child_by_name(dev->parent->of_node, "rk817-codec"); + if (!node) { + dev_err(dev, "%s() Can not get child: rk817-codec\n", + __func__); + return -ENODEV; + } + + ret = of_property_read_u32(node, "skp-volume", &rk817->spk_volume); + if (ret < 0) { + DBG("%s() Can not read property skp-volume\n", __func__); + rk817->spk_volume = OUT_VOLUME; + } + + ret = of_property_read_u32(node, "hp-volume", + &rk817->hp_volume); + if (ret < 0) { + DBG("%s() Can not read property hp-volume\n", + __func__); + rk817->hp_volume = OUT_VOLUME; + } + + ret = of_property_read_u32(node, "capture-volume", + &rk817->capture_volume); + if (ret < 0) { + DBG("%s() Can not read property capture-volume\n", + __func__); + rk817->capture_volume = CAPTURE_VOLUME; + } + + return 0; +} + +static const struct regmap_config rk817_codec_regmap_config = { + .name = "rk817-codec", + .reg_bits = 8, + .val_bits = 8, + .reg_stride = 1, + .max_register = 0x4f, + .cache_type = REGCACHE_NONE, + .volatile_reg = rk817_volatile_register, + .writeable_reg = rk817_codec_register, + .readable_reg = rk817_codec_register, + .reg_defaults = rk817_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rk817_reg_defaults), +}; + +static int rk817_platform_probe(struct platform_device *pdev) +{ + struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent); + struct rk817_codec_priv *rk817_codec_data; + int ret; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(&pdev->dev, "%s : rk817 is NULL\n", __func__); + return -EINVAL; + } + + rk817_codec_data = devm_kzalloc(&pdev->dev, + sizeof(struct rk817_codec_priv), + GFP_KERNEL); + if (!rk817_codec_data) + return -ENOMEM; + + rk817_priv = rk817_codec_data; + platform_set_drvdata(pdev, rk817_codec_data); + + ret = rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data); + if (ret < 0) { + dev_err(&pdev->dev, "%s() parse device tree property error %d\n", + __func__, ret); + goto err_; + } + + rk817_codec_data->regmap = devm_regmap_init_i2c(rk817->i2c, + &rk817_codec_regmap_config); + if (IS_ERR(rk817_codec_data->regmap)) { + ret = PTR_ERR(rk817_codec_data->regmap); + dev_err(&pdev->dev, "failed to allocate register map: %d\n", + ret); + goto err_; + } + + rk817_codec_data->mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(rk817_codec_data->mclk)) { + dev_err(&pdev->dev, "Unable to get mclk\n"); + ret = -ENXIO; + goto err_; + } + clk_prepare_enable(rk817_codec_data->mclk); + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk817, + rk817_dai, ARRAY_SIZE(rk817_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "%s() register codec error %d\n", + __func__, ret); + goto err_; + } + + return 0; +err_: + + rk817_priv = NULL; + + return ret; +} + +static int rk817_platform_remove(struct platform_device *pdev) +{ + if (!IS_ERR(rk817_priv->mclk)) + clk_disable_unprepare(rk817_priv->mclk); + + snd_soc_unregister_codec(&pdev->dev); + + rk817_priv = NULL; + + return 0; +} + +static void rk817_platform_shutdown(struct platform_device *pdev) +{ + DBG("%s\n", __func__); + + rk817_codec_power_down(RK817_CODEC_ALL); + + if (rk817_priv) + rk817_priv = NULL; +} + +static const struct of_device_id rk817_codec_dt_ids[] = { + { .compatible = "rockchip,rk817-codec" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rk817_codec_dt_ids); + +static struct platform_driver rk817_codec_driver = { + .driver = { + .name = "rk817-codec", + .of_match_table = rk817_codec_dt_ids, + }, + .probe = rk817_platform_probe, + .remove = rk817_platform_remove, + .shutdown = rk817_platform_shutdown, +}; + +module_platform_driver(rk817_codec_driver); + +MODULE_DESCRIPTION("ASoC RK817 codec driver"); +MODULE_AUTHOR("binyuan "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rk817_codec.h b/sound/soc/codecs/rk817_codec.h new file mode 100644 index 000000000000..cdf56a087308 --- /dev/null +++ b/sound/soc/codecs/rk817_codec.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018 Rockchip Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __RK817_CODEC_H__ +#define __RK817_CODEC_H__ + +/* codec register */ +#define RK817_CODEC_BASE 0x0000 + +#define RK817_CODEC_DTOP_VUCTL (RK817_CODEC_BASE + 0x12) +#define RK817_CODEC_DTOP_VUCTIME (RK817_CODEC_BASE + 0x13) +#define RK817_CODEC_DTOP_LPT_SRST (RK817_CODEC_BASE + 0x14) +#define RK817_CODEC_DTOP_DIGEN_CLKE (RK817_CODEC_BASE + 0x15) +#define RK817_CODEC_AREF_RTCFG0 (RK817_CODEC_BASE + 0x16) +#define RK817_CODEC_AREF_RTCFG1 (RK817_CODEC_BASE + 0x17) +#define RK817_CODEC_AADC_CFG0 (RK817_CODEC_BASE + 0x18) +#define RK817_CODEC_AADC_CFG1 (RK817_CODEC_BASE + 0x19) +#define RK817_CODEC_DADC_VOLL (RK817_CODEC_BASE + 0x1a) +#define RK817_CODEC_DADC_VOLR (RK817_CODEC_BASE + 0x1b) +#define RK817_CODEC_DADC_SR_ACL0 (RK817_CODEC_BASE + 0x1e) +#define RK817_CODEC_DADC_ALC1 (RK817_CODEC_BASE + 0x1f) +#define RK817_CODEC_DADC_ALC2 (RK817_CODEC_BASE + 0x20) +#define RK817_CODEC_DADC_NG (RK817_CODEC_BASE + 0x21) +#define RK817_CODEC_DADC_HPF (RK817_CODEC_BASE + 0x22) +#define RK817_CODEC_DADC_RVOLL (RK817_CODEC_BASE + 0x23) +#define RK817_CODEC_DADC_RVOLR (RK817_CODEC_BASE + 0x24) +#define RK817_CODEC_AMIC_CFG0 (RK817_CODEC_BASE + 0x27) +#define RK817_CODEC_AMIC_CFG1 (RK817_CODEC_BASE + 0x28) +#define RK817_CODEC_DMIC_PGA_GAIN (RK817_CODEC_BASE + 0x29) +#define RK817_CODEC_DMIC_LMT1 (RK817_CODEC_BASE + 0x2a) +#define RK817_CODEC_DMIC_LMT2 (RK817_CODEC_BASE + 0x2b) +#define RK817_CODEC_DMIC_NG1 (RK817_CODEC_BASE + 0x2c) +#define RK817_CODEC_DMIC_NG2 (RK817_CODEC_BASE + 0x2d) +#define RK817_CODEC_ADAC_CFG0 (RK817_CODEC_BASE + 0x2e) +#define RK817_CODEC_ADAC_CFG1 (RK817_CODEC_BASE + 0x2f) +#define RK817_CODEC_DDAC_POPD_DACST (RK817_CODEC_BASE + 0x30) +#define RK817_CODEC_DDAC_VOLL (RK817_CODEC_BASE + 0x31) +#define RK817_CODEC_DDAC_VOLR (RK817_CODEC_BASE + 0x32) +#define RK817_CODEC_DDAC_SR_LMT0 (RK817_CODEC_BASE + 0x35) +#define RK817_CODEC_DDAC_LMT1 (RK817_CODEC_BASE + 0x36) +#define RK817_CODEC_DDAC_LMT2 (RK817_CODEC_BASE + 0x37) +#define RK817_CODEC_DDAC_MUTE_MIXCTL (RK817_CODEC_BASE + 0x38) +#define RK817_CODEC_DDAC_RVOLL (RK817_CODEC_BASE + 0x39) +#define RK817_CODEC_DDAC_RVOLR (RK817_CODEC_BASE + 0x3a) +#define RK817_CODEC_AHP_ANTI0 (RK817_CODEC_BASE + 0x3b) +#define RK817_CODEC_AHP_ANTI1 (RK817_CODEC_BASE + 0x3c) +#define RK817_CODEC_AHP_CFG0 (RK817_CODEC_BASE + 0x3d) +#define RK817_CODEC_AHP_CFG1 (RK817_CODEC_BASE + 0x3e) +#define RK817_CODEC_AHP_CP (RK817_CODEC_BASE + 0x3f) +#define RK817_CODEC_ACLASSD_CFG1 (RK817_CODEC_BASE + 0x40) +#define RK817_CODEC_ACLASSD_CFG2 (RK817_CODEC_BASE + 0x41) +#define RK817_CODEC_APLL_CFG0 (RK817_CODEC_BASE + 0x42) +#define RK817_CODEC_APLL_CFG1 (RK817_CODEC_BASE + 0x43) +#define RK817_CODEC_APLL_CFG2 (RK817_CODEC_BASE + 0x44) +#define RK817_CODEC_APLL_CFG3 (RK817_CODEC_BASE + 0x45) +#define RK817_CODEC_APLL_CFG4 (RK817_CODEC_BASE + 0x46) +#define RK817_CODEC_APLL_CFG5 (RK817_CODEC_BASE + 0x47) +#define RK817_CODEC_DI2S_CKM (RK817_CODEC_BASE + 0x48) +#define RK817_CODEC_DI2S_RSD (RK817_CODEC_BASE + 0x49) +#define RK817_CODEC_DI2S_RXCR1 (RK817_CODEC_BASE + 0x4a) +#define RK817_CODEC_DI2S_RXCR2 (RK817_CODEC_BASE + 0x4b) +#define RK817_CODEC_DI2S_RXCMD_TSD (RK817_CODEC_BASE + 0x4c) +#define RK817_CODEC_DI2S_TXCR1 (RK817_CODEC_BASE + 0x4d) +#define RK817_CODEC_DI2S_TXCR2 (RK817_CODEC_BASE + 0x4e) +#define RK817_CODEC_DI2S_TXCR3_TXCMD (RK817_CODEC_BASE + 0x4f) + +/*RK817_CODEC_DTOP_DIGEN_CLKE*/ +#define ADC_DIG_CLK_MASK (0xf << 4) +#define ADC_DIG_CLK_SFT 4 +#define ADC_DIG_CLK_DIS (0x0 << 4) +#define ADC_DIG_CLK_EN (0xf << 4) + +#define DAC_DIG_CLK_MASK (0xf << 0) +#define DAC_DIG_CLK_SFT 0 +#define DAC_DIG_CLK_DIS (0x0 << 0) +#define DAC_DIG_CLK_EN (0xf << 0) + +/*RK817_CODEC_APLL_CFG5*/ +#define PLL_PW_DOWN (0x01 << 0) +#define PLL_PW_UP (0x00 << 0) + +/*RK817_CODEC_DI2S_CKM*/ +#define SCK_EN_ENABLE (0x1 << 2) +#define SCK_EN_DISABLE (0x0 << 2) + +#define RK817_I2S_MODE_MASK (0x1 << 0) +#define RK817_I2S_MODE_SFT 0 +#define RK817_I2S_MODE_MST (0x1 << 0) +#define RK817_I2S_MODE_SLV (0x0 << 0) + +/*RK817_CODEC_DDAC_MUTE_MIXCTL*/ +#define DACMT_ENABLE (0x1 << 0) +#define DACMT_DISABLE (0x0 << 0) + +/*RK817_CODEC_DI2S_RXCR2*/ +#define VDW_RX_24BITS (0x17) +#define VDW_RX_16BITS (0x0f) +/*RK817_CODEC_DI2S_TXCR2*/ +#define VDW_TX_24BITS (0x17) +#define VDW_TX_16BITS (0x0f) + +/*RK817_CODEC_AHP_CFG1*/ +#define HP_ANTIPOP_ENABLE (0x1 << 4) +#define HP_ANTIPOP_DISABLE (0x0 << 4) + +/*RK817_CODEC_ADAC_CFG1*/ +#define PWD_DACBIAS_MASK (0x1 << 3) +#define PWD_DACBIAS_SFT 3 +#define PWD_DACBIAS_DOWN (0x1 << 3) +#define PWD_DACBIAS_ON (0x0 << 3) + +#define PWD_DACD_MASK (0x1 << 2) +#define PWD_DACD_SFT 2 +#define PWD_DACD_DOWN (0x1 << 2) +#define PWD_DACD_ON (0x0 << 2) + +#define PWD_DACL_MASK (0x1 << 1) +#define PWD_DACL_SFT 1 +#define PWD_DACL_DOWN (0x1 << 1) +#define PWD_DACL_ON (0x0 << 1) + +#define PWD_DACR_MASK (0x1 << 0) +#define PWD_DACR_SFT 0 +#define PWD_DACR_DOWN (0x1 << 0) +#define PWD_DACR_ON (0x0 << 0) + +enum { + RK817_HIFI, + RK817_VOICE, +}; + +enum { + RK817_MONO = 1, + RK817_STEREO, +}; + +enum { + OFF, + RCV, + SPK_PATH, + HP_PATH, + HP_NO_MIC, + BT, + SPK_HP, + RING_SPK, + RING_HP, + RING_HP_NO_MIC, + RING_SPK_HP, +}; + +enum { + MIC_OFF, + MAIN_MIC, + HANDS_FREE_MIC, + BT_SCO_MIC, +}; + +struct rk817_reg_val_typ { + unsigned int reg; + unsigned int value; +}; + +struct rk817_init_bit_typ { + unsigned int reg; + unsigned int power_bit; + unsigned int init_bit; +}; + +#endif /* __RK817_CODEC_H__ */ From 63c07f8a393a39d4b46f68bbc430a817aab04d8c Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Mon, 5 Feb 2018 20:56:19 +0800 Subject: [PATCH 300/427] arm64: dts: rockchip: add rk817 codec for rk3326 Change-Id: I8d86246b8e75ae028ba0f1d9b58c8facd2816556 Signed-off-by: Binyuan Lan --- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 36 +++++++++++++++++++ .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 648149d24450..d7ca8b7cf8d8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -77,6 +77,27 @@ default-brightness-level = <200>; }; + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,rk817-codec"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Mic Jack", "MICBIAS1", + "IN1P", "Mic Jack", + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR"; + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk817_codec>; + }; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; clocks = <&cru SCLK_WIFI_PMU>; @@ -455,6 +476,16 @@ virtual_power = <0>; dc_det_adc = <0>; }; + + rk817_codec: rk817-codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + status = "okay"; + }; }; }; @@ -486,6 +517,11 @@ status = "okay"; }; +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + &io_domains { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index b532b1ad9fdd..d86dc42435ac 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -137,6 +137,27 @@ }; }; + rk817-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,rk817-codec"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Mic Jack", "MICBIAS1", + "IN1P", "Mic Jack", + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR"; + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk817_codec>; + }; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk817 1>;*/ @@ -545,6 +566,16 @@ virtual_power = <0>; dc_det_adc = <0>; }; + + rk817_codec: rk817-codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + status = "okay"; + }; }; }; @@ -582,6 +613,11 @@ }; }; +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + &io_domains { status = "okay"; From 2f0ec89e19274c153b4b8e159cc25c9789ae6136 Mon Sep 17 00:00:00 2001 From: William Wu Date: Thu, 8 Feb 2018 09:48:10 +0800 Subject: [PATCH 301/427] Revert "usb: gadget: f_fs: Update driver to handle compat id descriptors" This reverts commit 548b453dcc349f7d621f81e4b2599ee9218561a4 which is replaced with the upstream commit 53642399aa71 ("usb: gadget: f_fs: Fix wrong check on reserved1 of OS_DESC_EXT_COMPAT"). Change-Id: I34e0f68d1e54a1852d021ee3ef78e3944fea675f Signed-off-by: William Wu --- drivers/usb/gadget/function/f_fs.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 598e73089da6..10cbce848e56 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2073,17 +2073,11 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, if (len < sizeof(*d) || d->bFirstInterfaceNumber >= ffs->interfaces_count || - d->Reserved1 != 1) { - pr_err("%s(): Invalid os_desct_ext_compat\n", - __func__); + d->Reserved1) return -EINVAL; - } for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) - if (d->Reserved2[i]) { - pr_err("%s(): Invalid Reserved2 of ext_compat\n", - __func__); + if (d->Reserved2[i]) return -EINVAL; - } length = sizeof(struct usb_ext_compat_desc); } From 9fac9f59aaf2d7be5f1ce65412a2a185bae89001 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Fri, 20 May 2016 18:13:19 +0800 Subject: [PATCH 302/427] UPSTREAM: usb: gadget: f_fs: Fix wrong check on reserved1 of OS_DESC_EXT_COMPAT Current __ffs_data_do_os_desc() of f_fs.c will check reserved1 field of OS_DESC_EXT_COMPAT and return -EINVAL if it's 1. But MS OS 1.0 Descriptors http://msdn.microsoft.com/en-us/library/windows/hardware/gg463179.aspx defines that field to be 1. Change-Id: I9a3c7cf148c161ff1f0f8e798208a196c4aca3d2 Signed-off-by: Jim Lin Signed-off-by: Felipe Balbi Signed-off-by: William Wu (cherry picked from commit 53642399aa71b7c3b15d0305dc54738c4222bb1e) --- drivers/usb/gadget/function/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 10cbce848e56..8e5c066557a7 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2073,7 +2073,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, if (len < sizeof(*d) || d->bFirstInterfaceNumber >= ffs->interfaces_count || - d->Reserved1) + !d->Reserved1) return -EINVAL; for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) if (d->Reserved2[i]) From 411314c56de374434db9a2e8237ab08384e2461a Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Mon, 9 Jan 2017 13:46:00 +0000 Subject: [PATCH 303/427] UPSTREAM: usb: gadget: f_fs: Fix iterations on endpoints. When zero endpoints are declared for a function, there is no endpoint to disable, enable or free, so replace do...while loops with while loops. Change pre-decrement to post-decrement to iterate the same number of times when there are endpoints to process. Change-Id: Ia6cb1324ce5acdab00677181475b34ab5731f578 Signed-off-by: Vincent Pelletier Signed-off-by: Felipe Balbi Signed-off-by: William Wu (cherry picked from commit 08f37148b6a915a6996c7dbef87769b9efee2dba) --- drivers/usb/gadget/function/f_fs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 8e5c066557a7..60075b5f9f27 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1617,7 +1617,7 @@ static void ffs_func_eps_disable(struct ffs_function *func) unsigned long flags; spin_lock_irqsave(&func->ffs->eps_lock, flags); - do { + while (count--) { /* pending requests get nuked */ if (likely(ep->ep)) usb_ep_disable(ep->ep); @@ -1627,7 +1627,7 @@ static void ffs_func_eps_disable(struct ffs_function *func) epfile->ep = NULL; ++epfile; } - } while (--count); + } spin_unlock_irqrestore(&func->ffs->eps_lock, flags); } @@ -1641,7 +1641,7 @@ static int ffs_func_eps_enable(struct ffs_function *func) int ret = 0; spin_lock_irqsave(&func->ffs->eps_lock, flags); - do { + while(count--) { struct usb_endpoint_descriptor *ds; struct usb_ss_ep_comp_descriptor *comp_desc = NULL; int needs_comp_desc = false; @@ -1688,7 +1688,7 @@ static int ffs_func_eps_enable(struct ffs_function *func) ++ep; ++epfile; - } while (--count); + } spin_unlock_irqrestore(&func->ffs->eps_lock, flags); return ret; @@ -3251,12 +3251,12 @@ static void ffs_func_unbind(struct usb_configuration *c, /* cleanup after autoconfig */ spin_lock_irqsave(&func->ffs->eps_lock, flags); - do { + while (count--) { if (ep->ep && ep->req) usb_ep_free_request(ep->ep, ep->req); ep->req = NULL; ++ep; - } while (--count); + } spin_unlock_irqrestore(&func->ffs->eps_lock, flags); kfree(func->eps); func->eps = NULL; From 67bb2799fb7e2b0bb0516da51c546f760e229ec0 Mon Sep 17 00:00:00 2001 From: Jim Baxter Date: Thu, 8 Sep 2016 11:18:16 +0200 Subject: [PATCH 304/427] UPSTREAM: usb: gadget: f_fs: Stop ffs_closed NULL pointer dereference The struct ffs_data::private_data has a pointer to ffs_dev stored in it during the ffs_fs_mount() function however it is not cleared when the ffs_dev is freed later which causes the ffs_closed function to crash with "Unable to handle kernel NULL pointer dereference" error when using the data in ffs_data::private_data. This clears this pointer during the ffs_free_dev clean up function. Change-Id: I1fde26421cb44084d73e8c2a1786ea3f09f952fc Signed-off-by: Jim Baxter Signed-off-by: Jiada Wang Signed-off-by: Harish Jenny K N Signed-off-by: Felipe Balbi Signed-off-by: William Wu (cherry picked from commit 3262ad824307c275922161e82c2db1458822f28c) --- drivers/usb/gadget/function/f_fs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 60075b5f9f27..f613694b563e 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3381,6 +3381,11 @@ static void _ffs_free_dev(struct ffs_dev *dev) list_del(&dev->entry); if (dev->name_allocated) kfree(dev->name); + + /* Clear the private_data pointer to stop incorrect dev access */ + if (dev->ffs_data) + dev->ffs_data->private_data = NULL; + kfree(dev); if (list_empty(&ffs_devices)) functionfs_cleanup(); From bb16981daa8e633ea34867eb585537034e19494c Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Wed, 8 Nov 2017 10:13:15 -0700 Subject: [PATCH 305/427] UPSTREAM: usb: gadget: f_fs: Fix use-after-free in ffs_free_inst KASAN enabled configuration reports an error BUG: KASAN: use-after-free in ffs_free_inst+... [usb_f_fs] at addr ... Write of size 8 by task ... This is observed after "ffs-test" is run and interrupted. If after that functionfs is unmounted and g_ffs module is unloaded, that use-after-free occurs during g_ffs module removal. Although the report indicates ffs_free_inst() function, the actual use-after-free condition occurs in _ffs_free_dev() function, which is probably inlined into ffs_free_inst(). This happens due to keeping the ffs_data reference in device structure during functionfs unmounting, while ffs_data itself is freed as no longer needed. The fix is to clear that reference in ffs_closed() function, which is a counterpart of ffs_ready(), where the reference is stored. Change-Id: Ia7d30dfe643ef5de184620b483ef3ad16a76d309 Fixes: 3262ad824307 ("usb: gadget: f_fs: Stop ffs_closed NULL pointer dereference") Cc: stable@vger.kernel.org Signed-off-by: Andrew Gabbasov Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman Signed-off-by: William Wu (cherry picked from commit cdafb6d8b8da7fde266f79b3287ac221aa841879) --- drivers/usb/gadget/function/f_fs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index f613694b563e..5ca7271580d3 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3478,6 +3478,7 @@ static void ffs_closed(struct ffs_data *ffs) goto done; ffs_obj->desc_ready = false; + ffs_obj->ffs_data = NULL; if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) && ffs_obj->ffs_closed_callback) From 984ae2a17b79d9a64dacd60b28ee6d177afae3e1 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 27 Nov 2017 18:15:40 +0000 Subject: [PATCH 306/427] UPSTREAM: usb: f_fs: Force Reserved1=1 in OS_DESC_EXT_COMPAT The specification says that the Reserved1 field in OS_DESC_EXT_COMPAT must have the value "1", but when this feature was first implemented we rejected any non-zero values. This was adjusted to accept all non-zero values (while now rejecting zero) in commit 53642399aa71 ("usb: gadget: f_fs: Fix wrong check on reserved1 of OS_DESC_EXT_COMPAT"), but that breaks any userspace programs that worked previously by returning EINVAL when Reserved1 == 0 which was previously the only value that succeeded! If we just set the field to "1" ourselves, both old and new userspace programs continue to work correctly and, as a bonus, old programs are now compliant with the specification without having to fix anything themselves. Change-Id: I7fe3d54ce649049ad0a1db4564319af03488ad48 Fixes: 53642399aa71 ("usb: gadget: f_fs: Fix wrong check on reserved1 of OS_DESC_EXT_COMPAT") Cc: Signed-off-by: John Keeping Signed-off-by: Felipe Balbi Signed-off-by: William Wu (cherry picked from commit a3acc696085e112733d191a77b106e67a4fa110b) --- drivers/usb/gadget/function/f_fs.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 5ca7271580d3..807a3e7dc94e 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2072,9 +2072,18 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, int i; if (len < sizeof(*d) || - d->bFirstInterfaceNumber >= ffs->interfaces_count || - !d->Reserved1) + d->bFirstInterfaceNumber >= ffs->interfaces_count) return -EINVAL; + if (d->Reserved1 != 1) { + /* + * According to the spec, Reserved1 must be set to 1 + * but older kernels incorrectly rejected non-zero + * values. We fix it here to avoid returning EINVAL + * in response to values we used to accept. + */ + pr_debug("usb_ext_compat_desc::Reserved1 forced to 1\n"); + d->Reserved1 = 1; + } for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) if (d->Reserved2[i]) return -EINVAL; From 109121e68dd19c33ff8f29e2890856bd89cc8eb1 Mon Sep 17 00:00:00 2001 From: William Wu Date: Thu, 8 Feb 2018 10:13:42 +0800 Subject: [PATCH 307/427] FROMLIST: usb: gadget: f_fs: Use config_ep_by_speed() In commit 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") there is a pointer arithmetic bug where the comp_desc is obtained as follows: comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + USB_DT_ENDPOINT_SIZE); Since ds is a pointer to usb_endpoint_descriptor, adding 7 to it ends up going out of bounds (7 * sizeof(struct usb_endpoint_descriptor), which is actually 7*9 bytes) past the SS descriptor. As a result the maxburst value will be read incorrectly, and the UDC driver will also get a garbage comp_desc (assuming it uses it). Since Felipe wrote, "Eventually, f_fs.c should be converted to use config_ep_by_speed() like all other functions, though", let's finally do it. This allows the other usb_ep fields to be properly populated, such as maxpacket and mult. It also eliminates the awkward speed-based descriptor lookup since config_ep_by_speed() does that already using the ones found in struct usb_function. Fixes: 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") Change-Id: Ic3f6297781571268a0b6b1b3f0a04b70d7fa7a68 Signed-off-by: Jack Pham Signed-off-by: William Wu (am from https://www.spinics.net/lists/linux-usb/msg165149.html) --- drivers/usb/gadget/function/f_fs.c | 38 ++++++------------------------ 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 807a3e7dc94e..8a0e35acaf50 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1642,44 +1642,20 @@ static int ffs_func_eps_enable(struct ffs_function *func) spin_lock_irqsave(&func->ffs->eps_lock, flags); while(count--) { - struct usb_endpoint_descriptor *ds; - struct usb_ss_ep_comp_descriptor *comp_desc = NULL; - int needs_comp_desc = false; - int desc_idx; - - if (ffs->gadget->speed == USB_SPEED_SUPER) { - desc_idx = 2; - needs_comp_desc = true; - } else if (ffs->gadget->speed == USB_SPEED_HIGH) - desc_idx = 1; - else - desc_idx = 0; - - /* fall-back to lower speed if desc missing for current speed */ - do { - ds = ep->descs[desc_idx]; - } while (!ds && --desc_idx >= 0); - - if (!ds) { - ret = -EINVAL; - break; - } - ep->ep->driver_data = ep; - ep->ep->desc = ds; - if (needs_comp_desc) { - comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + - USB_DT_ENDPOINT_SIZE); - ep->ep->maxburst = comp_desc->bMaxBurst + 1; - ep->ep->comp_desc = comp_desc; + ret = config_ep_by_speed(func->gadget, &func->function, ep->ep); + if (ret) { + pr_err("%s: config_ep_by_speed(%s) returned %d\n", + __func__, ep->ep->name, ret); + break; } ret = usb_ep_enable(ep->ep); if (likely(!ret)) { epfile->ep = ep; - epfile->in = usb_endpoint_dir_in(ds); - epfile->isoc = usb_endpoint_xfer_isoc(ds); + epfile->in = usb_endpoint_dir_in(ep->ep->desc); + epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc); } else { break; } From cdfac2ac67ecc267f2dd9455e632f3582f9841f9 Mon Sep 17 00:00:00 2001 From: Feng Mingli Date: Tue, 30 Jan 2018 17:14:22 +0800 Subject: [PATCH 308/427] usb: dwc_otg_310: hcd: Giveback URB in tasklet context In commit 94dfd7edfd5c ("USB: HCD: support giveback of URB in tasklet context") support was added to give back the URB in tasklet context. Let's take advantage of this in dwc_otg_310. This speeds up the dwc_otg_310 interrupt handler considerably, it means we've got a better chance of not missing SOF interrupts. TEST=Unable to preview yuyv format usb camera on rk3288 board when use dwc usb controller because of missing SOF interrupts. Change-Id: I52194d7fbddaf684c601d328e2a3c0f28fcb83b8 Signed-off-by: Feng Mingli --- drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c index d6fc10a818f3..fb642935956f 100644 --- a/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c @@ -115,7 +115,7 @@ static struct hc_driver dwc_otg_hc_driver = { .irq = dwc_otg_hcd_irq, - .flags = HCD_MEMORY | HCD_USB2, + .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, /* .reset = */ .start = hcd_start, @@ -330,13 +330,11 @@ static int _complete(dwc_otg_hcd_t *hcd, void *urb_handle, usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); - DWC_SPINUNLOCK(hcd->lock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); #else usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); #endif - DWC_SPINLOCK(hcd->lock); return 0; } From 51246818af1f41b3b48fae8cb35be5c1bec69799 Mon Sep 17 00:00:00 2001 From: William Wu Date: Thu, 8 Feb 2018 19:43:30 +0800 Subject: [PATCH 309/427] arm64: dts: rockchip: remove HCLK_HOST_ARB from usb host for px30 The HCLK_HOST_ARB is enabled with CLK_IGNORE_UNUSED flag, so we don't need to control this clk in usb host EHCI and OHCI controller driver. Change-Id: I25201170977b30f904611bbcfdcb1eb6230195fe Signed-off-by: William Wu --- arch/arm64/boot/dts/rockchip/px30.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index dcf3959bb97c..ca4420cf2dbd 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -859,8 +859,7 @@ compatible = "generic-ehci"; reg = <0x0 0xff340000 0x0 0x10000>; interrupts = ; - clocks = <&cru HCLK_HOST>, <&cru HCLK_HOST_ARB>, - <&u2phy>; + clocks = <&cru HCLK_HOST>, <&u2phy>; clock-names = "usbhost", "arbiter", "utmi"; power-domains = <&power PX30_PD_USB>; phys = <&u2phy_host>; @@ -872,8 +871,7 @@ compatible = "generic-ohci"; reg = <0x0 0xff350000 0x0 0x10000>; interrupts = ; - clocks = <&cru HCLK_HOST>, <&cru HCLK_HOST_ARB>, - <&u2phy>; + clocks = <&cru HCLK_HOST>, <&u2phy>; clock-names = "usbhost", "arbiter", "utmi"; power-domains = <&power PX30_PD_USB>; phys = <&u2phy_host>; From d86b2eeb5607b9bef37e2e9b4b7fdf825c5f043e Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Fri, 2 Feb 2018 23:33:54 +0800 Subject: [PATCH 310/427] arm64: rockchip_defconfig: add CONFIG_SND_SOC_RK817 Change-Id: I3771ee617de44d9cfd8d142fc66ca5ea8df64899 Signed-off-by: Binyuan Lan --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 5558681103bd..c7141119969f 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -557,6 +557,7 @@ CONFIG_SND_SOC_ES8396=y CONFIG_SND_SOC_FM1288=y CONFIG_SND_SOC_RK1000=y CONFIG_SND_SOC_RK3328=y +CONFIG_SND_SOC_RK817=y CONFIG_SND_SOC_RT5640=y CONFIG_SND_SOC_SPDIF=y CONFIG_SND_SIMPLE_CARD=y From 1ec3c339429636a2a407e2b84eca6df25ebcba12 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Thu, 8 Feb 2018 15:40:22 +0800 Subject: [PATCH 311/427] phy: rockchip: inno-hdmi: fix 3328 phy status with uboot logo on If hdmi phy had been set in uboot, it's need to set power_count to 1 to match actutal phy status. This patch use regc8 bit[7:6] to detect phy is set in uboot or not. After phy power up, value will be zero which is different to its default value(2'b11). Change-Id: I6e5deea1d5a0973788c39a200d5c5a0f6a14bdd2 Signed-off-by: Zheng Yang --- drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c index 6aea5b23067f..f8f48b9b04ab 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c @@ -734,6 +734,15 @@ static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) */ inno_write(inno, 0x01, 0x07); inno_write(inno, 0x02, 0x91); + + /* + * reg0xc8 default value is 0xc0, if phy had been set in uboot, + * the value of bit[7:6] will be zero. + */ + if ((inno_read(inno, 0xc8) & 0xc0) == 0) { + dev_info(inno->dev, "phy had been powered up\n"); + inno->phy->power_count = 1; + } } static int From 816e9c33582044f2af79d64ff25a2d86439a7eac Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 8 Feb 2018 21:00:13 +0800 Subject: [PATCH 312/427] arm: dts: move memory of ramoops to 46M for rk312x/rk322x We put memory of ramoops on 46M from now on for arm32, beacause some board only have 128M memory. Change-Id: Ie94a7619bfe006e196d3269711a499acbd7c87b9 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk312x-android.dtsi | 4 ++-- arch/arm/boot/dts/rk322x-android.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk312x-android.dtsi b/arch/arm/boot/dts/rk312x-android.dtsi index e4ed16e0df0f..b9e4bbdcd80e 100644 --- a/arch/arm/boot/dts/rk312x-android.dtsi +++ b/arch/arm/boot/dts/rk312x-android.dtsi @@ -129,8 +129,8 @@ reg = <0x88000000 0x1800000>; }; - ramoops_mem: ramoops@68000000 { - reg = <0x68000000 0xf0000>; + ramoops_mem: ramoops@62e00000 { + reg = <0x62e00000 0xf0000>; }; drm_logo: drm-logo@00000000 { diff --git a/arch/arm/boot/dts/rk322x-android.dtsi b/arch/arm/boot/dts/rk322x-android.dtsi index f19ae5668ca7..29b0f444663f 100644 --- a/arch/arm/boot/dts/rk322x-android.dtsi +++ b/arch/arm/boot/dts/rk322x-android.dtsi @@ -92,8 +92,8 @@ reg = <0x0 0x0>; }; - ramoops_mem: ramoops@68000000 { - reg = <0x68000000 0xf0000>; + ramoops_mem: ramoops@62e00000 { + reg = <0x62e00000 0xf0000>; }; }; From 405105146fd8a25ef3c9c46d18895ad243a6db2d Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 9 Feb 2018 09:43:31 +0800 Subject: [PATCH 313/427] arm: dts: enable arm arch virtual timer for rk312x Change-Id: Ife287d9b1de02dfeb75fbb202d4b4e1825af0c2f Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk312x.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index d8c376684f66..3ac3096f7bc7 100644 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -214,7 +214,9 @@ timer { compatible = "arm,armv7-timer"; interrupts = , - ; + , + , + ; clock-frequency = <24000000>; }; From 602e41b4691f932a0aa1bc825bed1a749979378b Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 9 Feb 2018 10:26:30 +0800 Subject: [PATCH 314/427] arm: dts: enable arm arch virtual timer for rk322x Change-Id: I355c0cd558484cb7fbe96d4c462329ece62348af Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk322x.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index efce2dd2b7d7..772b61795238 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -216,7 +216,6 @@ timer { compatible = "arm,armv7-timer"; - arm,cpu-registers-not-fw-configured; interrupts = , , , From 36e2b2b2f01ec9c601d5530d1b9330e76f158437 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 5 Feb 2018 15:19:38 +0800 Subject: [PATCH 315/427] arm: dts: fix reg length err for rk322x RK322x is a 32-bit SoC, the length of register is 32-bit. Change-Id: I3fe506b0f9c7f8ec70a56863f95decdc12e61e85 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk322x.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 772b61795238..153babf5e393 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -1043,17 +1043,17 @@ qos_vpu: qos@31040000 { compatible = "syscon"; - reg = <0x0 0x31040000 0x0 0x20>; + reg = <0x31040000 0x20>; }; qos_rkvdec_r: qos@31070000 { compatible = "syscon"; - reg = <0x0 0x31070000 0x0 0x20>; + reg = <0x31070000 0x20>; }; qos_rkvdec_w: qos@31070080 { compatible = "syscon"; - reg = <0x0 0x31070080 0x0 0x20>; + reg = <0x31070080 0x20>; }; gic: interrupt-controller@32010000 { From 5be2cb19cf8e678655b59ec70c6a5f66f08d9418 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Feb 2018 21:23:15 +0800 Subject: [PATCH 316/427] soc: rockchip: power-domain: Add support to ignore on/off Change-Id: I96c3ae8ae53b9ae95f6f896363b761798a534821 Signed-off-by: Finley Xiao --- drivers/soc/rockchip/pm_domains.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 6dafbf6d428c..a74aaa44e9bc 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -72,6 +72,7 @@ struct rockchip_pm_domain { struct regmap **qos_regmap; u32 *qos_save_regs[MAX_QOS_REGS_NUM]; int num_clks; + bool is_ignore_pwr; struct clk *clks[]; }; @@ -400,6 +401,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain) { struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + if (pd->is_ignore_pwr) + return 0; + return rockchip_pd_power(pd, true); } @@ -407,6 +411,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain) { struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + if (pd->is_ignore_pwr) + return 0; + return rockchip_pd_power(pd, false); } @@ -501,6 +508,8 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, pd->info = pd_info; pd->pmu = pmu; + if (!pd_info->pwr_mask) + pd->is_ignore_pwr = true; for (i = 0; i < clk_cnt; i++) { clk = of_clk_get(node, i); @@ -643,6 +652,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, { struct device_node *np; struct generic_pm_domain *child_domain, *parent_domain; + struct rockchip_pm_domain *child_pd, *parent_pd; int error; for_each_child_of_node(parent, np) { @@ -683,6 +693,17 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, parent_domain->name, child_domain->name); } + /* + * If child_pd doesn't do idle request or power on/off, + * parent_pd may fail to do power on/off, so if parent_pd + * need to power on/off, child_pd can't ignore to do idle + * request and power on/off. + */ + child_pd = to_rockchip_pd(child_domain); + parent_pd = to_rockchip_pd(parent_domain); + if (!parent_pd->is_ignore_pwr) + child_pd->is_ignore_pwr = false; + rockchip_pm_add_subdomain(pmu, np); } From ed2deb39578ddd25d8d75642076ddb3c83df2df2 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Thu, 8 Feb 2018 16:10:56 +0800 Subject: [PATCH 317/427] iommu/rockchip: return -ENODEV when a disabled iommu node is referenced by master When a disabled iommu node is referenced by a master which cause the previous iommu nodes removed from the iommu group, finally cause kernel crash, return -ENODEV instead -EPROBE_DEFER if iommu node disabled can fix this issue Change-Id: I3adf3f4119ff6fff0a2068301338813f5aca8969 Signed-off-by: Simon Xue --- drivers/iommu/rockchip-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index c174b6c1433c..3ef7d54576df 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1105,7 +1105,7 @@ static int rk_iommu_group_set_iommudata(struct iommu_group *group, of_node_put(args.np); if (!pd) { dev_err(dev, "iommu %s not found\n", args.np->full_name); - return -EPROBE_DEFER; + return -ENODEV; } /* TODO(djkurtz): handle multiple slave iommus for a single master */ From ea8b9e13c26f52eda33bb9f5b0c271f3569fe461 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 8 Feb 2018 16:02:35 +0800 Subject: [PATCH 318/427] clk: rockchip: rk3328: Fix aclk_gmac select register Change-Id: Ie800d876644f1a7abac3f7d7f8352ba405a9537a Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3328.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c index 6d182e4705a9..7e83b3dffa16 100644 --- a/drivers/clk/rockchip/clk-rk3328.c +++ b/drivers/clk/rockchip/clk-rk3328.c @@ -664,7 +664,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { /* PD_GMAC */ COMPOSITE(ACLK_GMAC, "aclk_gmac", mux_2plls_hdmiphy_p, 0, - RK3328_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3328_CLKSEL_CON(25), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3328_CLKGATE_CON(3), 2, GFLAGS), COMPOSITE_NOMUX(PCLK_GMAC, "pclk_gmac", "aclk_gmac", 0, RK3328_CLKSEL_CON(25), 8, 3, DFLAGS, From 7ba436d229f958b191c48816c313a8db4377cbb9 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 8 Feb 2018 16:59:15 +0800 Subject: [PATCH 319/427] arm64: dts: rockchip: px30: Change bus and peri to sign off frequency Change-Id: Ie40eb2610b277b1f7e257fdd6e8f578373b0294e Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index ca4420cf2dbd..6a067e6f4678 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -748,9 +748,9 @@ <&cru HCLK_PERI_PRE>, <&cru PCLK_BUS_PRE>; assigned-clock-rates = <1200000000>, <100000000>, - <26000000>, <300000000>, - <300000000>, <150000000>, - <150000000>, <75000000>; + <26000000>, <200000000>, + <200000000>, <150000000>, + <150000000>, <100000000>; }; usb2phy_grf: syscon@ff2c0000 { From c170469b8ba86e29e586d8e814904984edf82d8b Mon Sep 17 00:00:00 2001 From: Zhangbin Tong Date: Fri, 9 Feb 2018 09:30:00 +0800 Subject: [PATCH 320/427] arm64: dts: rockchip: add rk3328-rock64 android support Change-Id: Ibc0ce72839858c391280ea109aa731877e6b0928 Signed-off-by: Zhangbin Tong --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../dts/rockchip/rk3328-rock64-android.dts | 585 ++++++++++++++++++ 2 files changed, 586 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rock64-android.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index af2d18ed3e21..2ad38b3c0917 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-863-lp3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb-android.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64-android.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3366-fpga.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3366-sheep.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64-android.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64-android.dts new file mode 100644 index 000000000000..e04483ecca37 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64-android.dts @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +/dts-v1/; +#include "rk3328.dtsi" +#include "rk3328-android.dtsi" +#include + +/ { + model = "Pine64 Rock64"; + compatible = "pine64,rock64-android", "rockchip,rk3328"; + + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0m1_gpio>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io>; + }; + + vcc_host_5v: vcc-host-5v-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb30_host_drv>; + regulator-name = "vcc_host_5v"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb20_host_drv>; + regulator-name = "vcc_host1_5v"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "rockchip,rk3328"; + simple-audio-card,cpu { + sound-dai = <&i2s1>; + }; + simple-audio-card,codec { + sound-dai = <&codec>; + }; + }; + + hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <128>; + simple-audio-card,name = "rockchip,hdmi"; + simple-audio-card,cpu { + sound-dai = <&i2s0>; + }; + simple-audio-card,codec { + sound-dai = <&hdmi>; + }; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&codec { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&dfi { + status = "okay"; +}; + +&dmc { + center-supply = <&vdd_logic>; + status = "okay"; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + supports-emmc; + disable-wp; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + status = "okay"; +}; + +&gmac2io { + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmiim1_pins>; + tx_delay = <0x26>; + rx_delay = <0x11>; + status = "okay"; +}; + +&gmac2phy { + phy-supply = <&vcc_phy>; + clock_in_out = "output"; + assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; + assigned-clock-rate = <50000000>; + assigned-clocks = <&cru SCLK_MAC2PHY>; + assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; + status = "disabled"; +}; + +&gpu { + status = "okay"; + mali-supply = <&vdd_logic>; +}; + +&hdmi { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&hdmiphy { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + + rk805: rk805@18 { + compatible = "rockchip,rk805"; + status = "okay"; + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + wakeup-source; + gpio-controller; + #gpio-cells = <2>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + + rtc { + status = "okay"; + }; + + pwrkey { + status = "disabled"; + }; + + gpio { + status = "okay"; + }; + + regulators { + compatible = "rk805-regulator"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + vdd_logic: RK805_DCDC1@0 { + regulator-compatible = "RK805_DCDC1"; + regulator-name = "vdd_logic"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: RK805_DCDC2@1 { + regulator-compatible = "RK805_DCDC2"; + regulator-name = "vdd_arm"; + regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: RK805_DCDC3@2 { + regulator-compatible = "RK805_DCDC3"; + regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + }; + }; + + vcc_io: RK805_DCDC4@3 { + regulator-compatible = "RK805_DCDC4"; + regulator-name = "vcc_io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd_18: RK805_LDO1@4 { + regulator-compatible = "RK805_LDO1"; + regulator-name = "vdd_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_18emmc: RK805_LDO2@5 { + regulator-compatible = "RK805_LDO2"; + regulator-name = "vcc_18emmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_11: RK805_LDO3@6 { + regulator-compatible = "RK805_LDO3"; + regulator-name = "vdd_11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1100000>; + }; + }; + }; + }; +}; + +&h265e { + status = "okay"; +}; + +&i2s0 { + #sound-dai-cells = <0>; + rockchip,bclk-fs = <128>; + status = "okay"; +}; + +&i2s1 { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc_io>; + vccio2-supply = <&vcc_18emmc>; + vccio3-supply = <&vcc_io>; + vccio4-supply = <&vdd_18>; + vccio5-supply = <&vcc_io>; + vccio6-supply = <&vcc_io>; + pmuio-supply = <&vcc_io>; +}; + +&pinctrl { + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <2 6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + usb20_host_drv: usb20-host-drv { + rockchip,pins = <0 27 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb3 { + usb30_host_drv: usb30-host-drv { + rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm3 { + status = "okay"; + compatible = "rockchip,remotectl-pwm"; + remote_pwm_id = <3>; + handle_cpu_id = <1>; + remote_support_psci = <1>; + + ir_key1 { + rockchip,usercode = <0x4040>; + rockchip,key_table = + <0xf2 KEY_REPLY>, + <0xba KEY_BACK>, + <0xf4 KEY_UP>, + <0xf1 KEY_DOWN>, + <0xef KEY_LEFT>, + <0xee KEY_RIGHT>, + <0xbd KEY_HOME>, + <0xea KEY_VOLUMEUP>, + <0xe3 KEY_VOLUMEDOWN>, + <0xe2 KEY_SEARCH>, + <0xb2 KEY_POWER>, + <0xbc KEY_MUTE>, + <0xec KEY_MENU>, + <0xbf 0x190>, + <0xe0 0x191>, + <0xe1 0x192>, + <0xe9 183>, + <0xe6 248>, + <0xe8 185>, + <0xe7 186>, + <0xf0 388>, + <0xbe 0x175>; + }; + + ir_key2 { + rockchip,usercode = <0xff00>; + rockchip,key_table = + <0xf9 KEY_HOME>, + <0xbf KEY_BACK>, + <0xfb KEY_MENU>, + <0xaa KEY_REPLY>, + <0xb9 KEY_UP>, + <0xe9 KEY_DOWN>, + <0xb8 KEY_LEFT>, + <0xea KEY_RIGHT>, + <0xeb KEY_VOLUMEDOWN>, + <0xef KEY_VOLUMEUP>, + <0xf7 KEY_MUTE>, + <0xe7 KEY_POWER>, + <0xfc KEY_POWER>, + <0xa9 KEY_VOLUMEDOWN>, + <0xa8 KEY_PLAYPAUSE>, + <0xe0 KEY_VOLUMEDOWN>, + <0xa5 KEY_VOLUMEDOWN>, + <0xab 183>, + <0xb7 388>, + <0xe8 388>, + <0xf8 184>, + <0xaf 185>, + <0xed KEY_VOLUMEDOWN>, + <0xee 186>, + <0xb3 KEY_VOLUMEDOWN>, + <0xf1 KEY_VOLUMEDOWN>, + <0xf2 KEY_VOLUMEDOWN>, + <0xf3 KEY_SEARCH>, + <0xb4 KEY_VOLUMEDOWN>, + <0xa4 KEY_SETUP>, + <0xbe KEY_SEARCH>; + }; + + ir_key3 { + rockchip,usercode = <0x1dcc>; + rockchip,key_table = + <0xee KEY_REPLY>, + <0xf0 KEY_BACK>, + <0xf8 KEY_UP>, + <0xbb KEY_DOWN>, + <0xef KEY_LEFT>, + <0xed KEY_RIGHT>, + <0xfc KEY_HOME>, + <0xf1 KEY_VOLUMEUP>, + <0xfd KEY_VOLUMEDOWN>, + <0xb7 KEY_SEARCH>, + <0xff KEY_POWER>, + <0xf3 KEY_MUTE>, + <0xbf KEY_MENU>, + <0xf9 0x191>, + <0xf5 0x192>, + <0xb3 388>, + <0xbe KEY_1>, + <0xba KEY_2>, + <0xb2 KEY_3>, + <0xbd KEY_4>, + <0xf9 KEY_5>, + <0xb1 KEY_6>, + <0xfc KEY_7>, + <0xf8 KEY_8>, + <0xb0 KEY_9>, + <0xb6 KEY_0>, + <0xb5 KEY_BACKSPACE>; + }; +}; + +&rga { + status = "okay"; +}; + +&rkvdec { + status = "okay"; + vcodec-supply = <&vdd_logic>; +}; + +&rockchip_suspend { + status = "okay"; + rockchip,virtual-poweroff = <1>; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; + supports-sd; + status = "okay"; + vmmc-supply = <&vcc_sd>; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "gigadevice,gd25q128", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + m25p,fast-read; + /* The max SCLK of the flash 104/80 MHZ */ + spi-max-frequency = <50000000>; + }; +}; + +&threshold { + temperature = <90000>; /* millicelsius */ +}; + +&target { + temperature = <105000>; /* millicelsius */ +}; + +&soc_crit { + temperature = <110000>; /* millicelsius */ +}; + +&tsadc { + rockchip,hw-tshut-temp = <120000>; + status = "okay"; +}; + +&u2phy { + status = "okay"; + +}; + +&u2phy_host { + phy-supply = <&vcc_host1_5v>; + status = "okay"; +}; + +&u2phy_otg { + phy-supply = <&vcc_otg_5v>; + status = "okay"; +}; + +&u3phy { + phy-supply = <&vcc_host_5v>; + status = "okay"; +}; + +&u3phy_utmi { + status = "okay"; +}; + +&u3phy_pipe { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usbdrd3 { + status = "okay"; +}; + +&usbdrd_dwc3 { + status = "okay"; +}; + +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vpu_service { + status = "okay"; +}; + +&vepu { + status = "okay"; +}; From a5e68c507a25770d04ae1ae75900fc9d3107c798 Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Thu, 11 Jan 2018 14:55:08 +0800 Subject: [PATCH 321/427] drivers: input: sensors: add gsensor stk8baxx Change-Id: I983df89f746e42221009e9123116900041b9a06a Signed-off-by: Zorro Liu --- drivers/input/sensors/accel/Kconfig | 75 +- drivers/input/sensors/accel/Makefile | 25 +- drivers/input/sensors/accel/stk8baxx.c | 950 +++++++++++++++++++++++++ drivers/input/sensors/sensor-dev.c | 2 + include/linux/sensor-dev.h | 1 + 5 files changed, 1006 insertions(+), 47 deletions(-) create mode 100644 drivers/input/sensors/accel/stk8baxx.c diff --git a/drivers/input/sensors/accel/Kconfig b/drivers/input/sensors/accel/Kconfig index fe3d25e6ee71..7b0d026f7f2f 100644 --- a/drivers/input/sensors/accel/Kconfig +++ b/drivers/input/sensors/accel/Kconfig @@ -12,83 +12,89 @@ menuconfig GSENSOR_DEVICE if GSENSOR_DEVICE config GS_MMA8452 - bool "gsensor mma8451/mma8452/mma8453/mma8653" - default y - help + bool "gsensor mma8451/mma8452/mma8453/mma8653" + default y + help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. - + +config STK8BAXX_ACC + bool "gsensor STK8BAXX" + default n + help + To have support for your specific gsesnor you will have to + select the proper drivers which depend on this option. + config MPU6880_ACC - bool "Sensor mpu6880_acc" - default y - help + bool "Sensor mpu6880_acc" + default y + help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. config MPU6500_ACC - bool "Sensor mpu6500_acc" - default y + bool "Sensor mpu6500_acc" + default y help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. config GS_KXTIK - bool "gsensor kxtik" + bool "gsensor kxtik" help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. - config GS_KXTJ9 - bool "gsensor kxtj9" - help - To have support for your specific gsesnor you will have to - select the proper drivers which depend on this option. + bool "gsensor kxtj9" + help + To have support for your specific gsesnor you will have to + select the proper drivers which depend on this option. config GS_LIS3DH - bool "gsensor lis3dh" - default y - help + bool "gsensor lis3dh" + default y + help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. config GS_MMA7660 - bool "gsensor mma7660" - default y - help + bool "gsensor mma7660" + default y + help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. - + config GS_MC3230 - bool "gsensor mc3230" - help + bool "gsensor mc3230" + help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. config GS_MXC6225 bool "gsensor mxc6225" help - To have support for your sepcific gsensor you will have to - select het proper drivers which depend on this option. + To have support for your sepcific gsensor you will have to + select het proper drivers which depend on this option. config GS_DMT10 bool "gsensor dmard10" help - To have support for your sepcific gsensor you will have to - select het proper drivers which depend on this option. + To have support for your sepcific gsensor you will have to + select het proper drivers which depend on this option. config GS_LSM303D bool "gsensor lsm303d" default y help - To have support for your sepcific gsensor you will have to - select het proper drivers which depend on this option. + To have support for your sepcific gsensor you will have to + select het proper drivers which depend on this option. config GS_BMA023 - bool "gsensor bma023" - help - To have support for your specific gsesnor you will have to - select the proper drivers which depend on this option. + bool "gsensor bma023" + help + To have support for your specific gsesnor you will have to + select the proper drivers which depend on this option. config LSM330_ACC bool "gsensor lsm330" @@ -105,4 +111,3 @@ config BMA2XX_ACC select the proper drivers which depend on this option. endif - diff --git a/drivers/input/sensors/accel/Makefile b/drivers/input/sensors/accel/Makefile index d42d4d5ad597..deed0a8057dc 100644 --- a/drivers/input/sensors/accel/Makefile +++ b/drivers/input/sensors/accel/Makefile @@ -1,14 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_GS_KXTIK) += kxtik.o -obj-$(CONFIG_GS_KXTJ9) += kxtj9.o -obj-$(CONFIG_GS_MMA8452) += mma8452.o -obj-$(CONFIG_GS_LIS3DH) += lis3dh.o -obj-$(CONFIG_GS_MMA7660) += mma7660.o -obj-$(CONFIG_GS_MXC6225) += mxc622x.o -obj-$(CONFIG_GS_DMT10) += dmard10.o -obj-$(CONFIG_GS_LSM303D) += lsm303d.o -obj-$(CONFIG_GS_MC3230) += mc3230.o -obj-$(CONFIG_MPU6880_ACC) += mpu6880_acc.o -obj-$(CONFIG_MPU6500_ACC) += mpu6500_acc.o -obj-$(CONFIG_LSM330_ACC) += lsm330_acc.o +obj-$(CONFIG_GS_KXTIK) += kxtik.o +obj-$(CONFIG_GS_KXTJ9) += kxtj9.o +obj-$(CONFIG_GS_MMA8452) += mma8452.o +obj-$(CONFIG_GS_LIS3DH) += lis3dh.o +obj-$(CONFIG_GS_MMA7660) += mma7660.o +obj-$(CONFIG_GS_MXC6225) += mxc622x.o +obj-$(CONFIG_GS_DMT10) += dmard10.o +obj-$(CONFIG_GS_LSM303D) += lsm303d.o +obj-$(CONFIG_GS_MC3230) += mc3230.o +obj-$(CONFIG_MPU6880_ACC) += mpu6880_acc.o +obj-$(CONFIG_MPU6500_ACC) += mpu6500_acc.o +obj-$(CONFIG_LSM330_ACC) += lsm330_acc.o obj-$(CONFIG_BMA2XX_ACC) += bma2xx.o +obj-$(CONFIG_STK8BAXX_ACC) += stk8baxx.o diff --git a/drivers/input/sensors/accel/stk8baxx.c b/drivers/input/sensors/accel/stk8baxx.c new file mode 100644 index 000000000000..c25573427fb0 --- /dev/null +++ b/drivers/input/sensors/accel/stk8baxx.c @@ -0,0 +1,950 @@ +/* + * stk8baxx.c - Linux kernel modules for sensortek stk8ba50 / stk8ba50-R / + * stk8ba53 accelerometer + * + * Copyright (C) 2012~2016 Lex Hsieh / Sensortek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STK_ACC_DRIVER_VERSION "3.7.1_rk_0425_0428" + +/*------------------User-defined settings-------------------------*/ +/* #define CONFIG_SENSORS_STK8BA53 */ +#define CONFIG_SENSORS_STK8BA50 +/* #define STK_DEBUG_PRINT */ +/* #define STK_LOWPASS */ +#define STK_FIR_LEN 4 /* 1~32 */ +/* #define STK_TUNE */ +/* #define STK_ZG_FILTER */ +#define STK_HOLD_ODR +#define STK_DEBUG_CALI +#define STK8BAXX_DEF_PLACEMENT 7 + +/*------------------Miscellaneous settings-------------------------*/ +#define STK8BAXX_I2C_NAME "stk8baxx" +#define ACC_IDEVICE_NAME "accelerometer" + +#define STK8BAXX_INIT_ODR 0xD /* 0xB:125Hz, 0xA:62Hz */ + +#define STK8BAXX_RNG_2G 0x3 +#define STK8BAXX_RNG_4G 0x5 +#define STK8BAXX_RNG_8G 0x8 +#define STK8BAXX_RNG_16G 0xC + +#ifdef CONFIG_SENSORS_STK8BA53 +/* Parameters under +-4g dynamic range */ +#define STK_DEF_DYNAMIC_RANGE STK8BAXX_RNG_4G + +#if (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_4G) +#define STK_LSB_1G 512 +#define STK_DEF_RANGE 4 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_2G) +#define STK_LSB_1G 1024 +#define STK_DEF_RANGE 2 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_8G) +#define STK_LSB_1G 256 +#define STK_DEF_RANGE 8 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_16G) +#define STK_LSB_1G 128 +#define STK_DEF_RANGE 16 +#endif + +#define STK_ZG_COUNT (STK_LSB_1G / 128) +#define STK_TUNE_XYOFFSET (STK_LSB_1G * 3 / 10) +#define STK_TUNE_ZOFFSET (STK_LSB_1G * 3 / 10) /* (STK_LSB_1G * 3 / 20) */ +#define STK_TUNE_NOISE (STK_LSB_1G / 10) +#else +/* Parameters under +-2g dynamic range */ +#define STK_DEF_DYNAMIC_RANGE STK8BAXX_RNG_2G + +#if (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_2G) +#define STK_LSB_1G 256 +#define STK_DEF_RANGE 2 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_4G) +#define STK_LSB_1G 128 +#define STK_DEF_RANGE 4 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_8G) +#define STK_LSB_1G 64 +#define STK_DEF_RANGE 8 +#elif (STK_DEF_DYNAMIC_RANGE == STK8BAXX_RNG_16G) +#define STK_LSB_1G 32 +#define STK_DEF_RANGE 16 +#endif +#define STK_ZG_COUNT (STK_LSB_1G / 128 + 1) +#define STK_TUNE_XYOFFSET (STK_LSB_1G * 4 / 10) +#define STK_TUNE_ZOFFSET (STK_LSB_1G * 4 / 10) /* (STK_LSB_1G * 3 / 20) */ +#define STK_TUNE_NOISE (STK_LSB_1G / 10) +#endif + +#define STK8BAXX_RANGE_UG (STK_DEF_RANGE * 16384) + +/* STK_OFFSET_REG_LSB_1G is fixed for all dynamic range */ +#define STK_OFFSET_REG_LSB_1G 128 + +#define STK_TUNE_NUM 60 +#define STK_TUNE_DELAY 30 + +#define STK_EVENT_SINCE_EN_LIMIT_DEF (1) + +#define STK8BA50_ID 0x09 +#define STK8BA50R_ID 0x86 +#define STK8BA53_ID 0x87 + +/*------------------Calibration prameters-------------------------*/ +#define STK_SAMPLE_NO 10 +#define STK_ACC_CALI_VER0 0x18 +#define STK_ACC_CALI_VER1 0x03 +#define STK_ACC_CALI_END '\0' +#define STK_ACC_CALI_FILE "/data/misc/stkacccali.conf" +#define STK_ACC_CALI_FILE_SDCARD "/sdcard/.stkacccali.conf" +#define STK_ACC_CALI_FILE_SIZE 25 + +#define STK_K_SUCCESS_TUNE 0x04 +#define STK_K_SUCCESS_FT2 0x03 +#define STK_K_SUCCESS_FT1 0x02 +#define STK_K_SUCCESS_FILE 0x01 +#define STK_K_NO_CALI 0xFF +#define STK_K_RUNNING 0xFE +#define STK_K_FAIL_LRG_DIFF 0xFD +#define STK_K_FAIL_OPEN_FILE 0xFC +#define STK_K_FAIL_W_FILE 0xFB +#define STK_K_FAIL_R_BACK 0xFA +#define STK_K_FAIL_R_BACK_COMP 0xF9 +#define STK_K_FAIL_I2C 0xF8 +#define STK_K_FAIL_K_PARA 0xF7 +#define STK_K_FAIL_OUT_RG 0xF6 +#define STK_K_FAIL_ENG_I2C 0xF5 +#define STK_K_FAIL_FT1_USD 0xF4 +#define STK_K_FAIL_FT2_USD 0xF3 +#define STK_K_FAIL_WRITE_NOFST 0xF2 +#define STK_K_FAIL_OTP_5T 0xF1 +#define STK_K_FAIL_PLACEMENT 0xF0 + +/*------------------stk8baxx registers-------------------------*/ +#define STK8BAXX_XOUT1 0x02 +#define STK8BAXX_XOUT2 0x03 +#define STK8BAXX_YOUT1 0x04 +#define STK8BAXX_YOUT2 0x05 +#define STK8BAXX_ZOUT1 0x06 +#define STK8BAXX_ZOUT2 0x07 +#define STK8BAXX_INTSTS1 0x09 +#define STK8BAXX_INTSTS2 0x0A +#define STK8BAXX_EVENTINFO1 0x0B +#define STK8BAXX_EVENTINFO2 0x0C +#define STK8BAXX_RANGESEL 0x0F +#define STK8BAXX_BWSEL 0x10 +#define STK8BAXX_POWMODE 0x11 +#define STK8BAXX_DATASETUP 0x13 +#define STK8BAXX_SWRST 0x14 +#define STK8BAXX_INTEN1 0x16 +#define STK8BAXX_INTEN2 0x17 +#define STK8BAXX_INTMAP1 0x19 +#define STK8BAXX_INTMAP2 0x1A +#define STK8BAXX_INTMAP3 0x1B +#define STK8BAXX_DATASRC 0x1E +#define STK8BAXX_INTCFG1 0x20 +#define STK8BAXX_INTCFG2 0x21 +#define STK8BAXX_LGDLY 0x22 +#define STK8BAXX_LGTHD 0x23 +#define STK8BAXX_HLGCFG 0x24 +#define STK8BAXX_HGDLY 0x25 +#define STK8BAXX_HGTHD 0x26 +#define STK8BAXX_SLOPEDLY 0x27 +#define STK8BAXX_SLOPETHD 0x28 +#define STK8BAXX_TAPTIME 0x2A +#define STK8BAXX_TAPCFG 0x2B +#define STK8BAXX_ORIENTCFG 0x2C +#define STK8BAXX_ORIENTTHETA 0x2D +#define STK8BAXX_FLATTHETA 0x2E +#define STK8BAXX_FLATHOLD 0x2F +#define STK8BAXX_SLFTST 0x32 +#define STK8BAXX_INTFCFG 0x34 +#define STK8BAXX_OFSTCOMP1 0x36 +#define STK8BAXX_OFSTCOMP2 0x37 +#define STK8BAXX_OFSTFILTX 0x38 +#define STK8BAXX_OFSTFILTY 0x39 +#define STK8BAXX_OFSTFILTZ 0x3A +#define STK8BAXX_OFSTUNFILTX 0x3B +#define STK8BAXX_OFSTUNFILTY 0x3C +#define STK8BAXX_OFSTUNFILTZ 0x3D + +/* ZOUT1 register */ +#define STK8BAXX_O_NEW 0x01 + +/* SWRST register */ +#define STK8BAXX_SWRST_VAL 0xB6 + +/* STK8BAXX_POWMODE register */ +#define STK8BAXX_MD_SUSPEND 0x80 +#define STK8BAXX_MD_NORMAL 0x00 +#define STK8BAXX_MD_SLP_MASK 0x1E + +/* RANGESEL register */ +#define STK8BAXX_RANGE_MASK 0x0F + +/* OFSTCOMP1 register */ +#define STK8BAXX_OF_CAL_DRY_MASK 0x10 +#define CAL_AXIS_X_EN 0x20 +#define CAL_AXIS_Y_EN 0x40 +#define CAL_AXIS_Z_EN 0x60 +#define CAL_OFST_RST 0x80 + +/* OFSTCOMP2 register */ +#define CAL_TG_X0_Y0_ZPOS1 0x20 +#define CAL_TG_X0_Y0_ZNEG1 0x40 + +/*no_create_attr:the initial is 1-->no create attr. if created, change no_create_att to 0.*/ +static int no_create_att = 1; +static int enable_status = -1; + +/*------------------Data structure-------------------------*/ +struct stk8baxx_acc { + union { + struct { + s16 x; + s16 y; + s16 z; + }; + s16 acc[3]; + }; +}; + +#if defined(STK_LOWPASS) +#define MAX_FIR_LEN 32 +struct data_filter { + s16 raw[MAX_FIR_LEN][3]; + int sum[3]; + int num; + int idx; +}; +#endif + +struct stk8baxx_data { + struct i2c_client *client; + struct input_dev *input_dev; + int irq; + struct stk8baxx_acc acc_xyz; + atomic_t enabled; + bool first_enable; + struct work_struct stk_work; + struct hrtimer acc_timer; + struct workqueue_struct *stk_mems_work_queue; + unsigned char stk8baxx_placement; + atomic_t cali_status; + atomic_t recv_reg; + bool re_enable; +#if defined(STK_LOWPASS) + atomic_t firlength; + atomic_t fir_en; + struct data_filter fir; +#endif + int event_since_en; + int event_since_en_limit; + u8 stk_tune_offset_record[3]; +#ifdef STK_TUNE + int stk_tune_offset[3]; + int stk_tune_sum[3]; + int stk_tune_max[3]; + int stk_tune_min[3]; + int stk_tune_index; + int stk_tune_done; + s64 stk_tune_square_sum[3]; + u32 variance[3]; +#endif +}; + +/*------------------Function prototype-------------------------*/ +static int stk8baxx_set_enable(struct stk8baxx_data *stk, char en); +static int stk8baxx_read_sensor_data(struct stk8baxx_data *stk); +/*------------------Global variables-------------------------*/ +static struct stk8baxx_data *stk8baxx_data_ptr; +static struct sensor_private_data *sensor_ptr; +/*------------------Main functions-------------------------*/ + +static s32 stk8baxx_smbus_write_byte_data(u8 command, u8 value) +{ + return sensor_write_reg(stk8baxx_data_ptr->client, command, value); +} + +static int stk8baxx_smbus_read_byte_data(u8 command) +{ + return sensor_read_reg(stk8baxx_data_ptr->client, command); +} + +static int stk8baxx_chk_for_addr(struct stk8baxx_data *stk, s32 org_address, unsigned short reset_address) +{ + int result; + s32 expected_reg0 = 0x86; + + if ((org_address & 0xFE) == 0x18) + expected_reg0 = 0x86; + else + expected_reg0 = 0x87; + + stk->client->addr = reset_address; + result = stk8baxx_smbus_write_byte_data(STK8BAXX_SWRST, STK8BAXX_SWRST_VAL); + printk(KERN_INFO "%s:issue sw reset to 0x%x, result=%d\n", __func__, reset_address, result); + usleep_range(2000, 3000); + + stk->client->addr = org_address; + printk(KERN_INFO "%s Revise I2C Address = 0x%x\n", __func__, org_address); + result = stk8baxx_smbus_write_byte_data(STK8BAXX_POWMODE, STK8BAXX_MD_NORMAL); + result = stk8baxx_smbus_read_byte_data(0x0); + if (result < 0) { + printk(KERN_INFO "%s: read 0x0, result=%d\n", __func__, result); + return result; + } + if (result == expected_reg0) { + printk(KERN_INFO "%s:passed, expected_reg0=0x%x\n", __func__, expected_reg0); + result = stk8baxx_smbus_write_byte_data(STK8BAXX_SWRST, STK8BAXX_SWRST_VAL); + if (result < 0) { + printk(KERN_ERR "%s:failed to issue software reset, error=%d\n", __func__, result); + return result; + } + usleep_range(2000, 3000); + return 1; + } + return 0; +} + +static int stk8baxx_sw_reset(struct stk8baxx_data *stk) +{ + unsigned short org_addr = 0; + int result; + + org_addr = stk->client->addr; + printk(KERN_INFO "%s:org_addr=0x%x\n", __func__, org_addr); + + if ((org_addr & 0xFE) == 0x18) { + result = stk8baxx_chk_for_addr(stk, org_addr, 0x18); + if (result == 1) + return 0; + result = stk8baxx_chk_for_addr(stk, org_addr, 0x19); + if (result == 1) + return 0; + result = stk8baxx_chk_for_addr(stk, org_addr, 0x08); + if (result == 1) + return 0; + result = stk8baxx_chk_for_addr(stk, org_addr, 0x28); + if (result == 1) + return 0; + } else if (org_addr == 0x28) { + result = stk8baxx_chk_for_addr(stk, org_addr, 0x28); + if (result == 1) + return 0; + result = stk8baxx_chk_for_addr(stk, org_addr, 0x18); + if (result == 1) + return 0; + result = stk8baxx_chk_for_addr(stk, org_addr, 0x08); + if (result == 1) + return 0; + } + result = stk8baxx_chk_for_addr(stk, org_addr, 0x0B); + return 0; +} + +static int stk8baxx_reg_init(struct stk8baxx_data *stk, struct i2c_client *client, struct sensor_private_data *sensor) +{ + int result; + int aa; + +#ifdef CONFIG_SENSORS_STK8BA53 + printk(KERN_INFO "%s: Initialize stk8ba53\n", __func__); +#else + printk(KERN_INFO "%s: Initialize stk8ba50/stk8ba50-r\n", __func__); +#endif + + /* sw reset */ + result = stk8baxx_sw_reset(stk); + if (result < 0) { + printk(KERN_ERR "%s:failed to stk8baxx_sw_reset, error=%d\n", __func__, result); + return result; + } + + result = stk8baxx_smbus_write_byte_data(STK8BAXX_POWMODE, STK8BAXX_MD_NORMAL); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_POWMODE, result); + return result; + } + + result = stk8baxx_smbus_read_byte_data(STK8BAXX_LGDLY); + if (result < 0) { + printk(KERN_ERR "%s: failed to read acc data, error=%d\n", __func__, result); + return result; + } + + if (result == STK8BA50_ID) { + printk(KERN_INFO "%s: chip is stk8ba50\n", __func__); + sensor->devid = STK8BA50_ID; + } else { + result = stk8baxx_smbus_read_byte_data(0x0); + if (result < 0) { + printk(KERN_ERR "%s: failed to read acc data, error=%d\n", __func__, result); + return result; + } + printk(KERN_INFO "%s: 0x0=0x%x\n", __func__, result); + if (result == STK8BA50R_ID) { + printk(KERN_INFO "%s: chip is stk8ba50-R\n", __func__); + sensor->devid = STK8BA50R_ID; + } else { + printk(KERN_INFO "%s: chip is stk8ba53\n", __func__); + sensor->devid = STK8BA53_ID; + } + } +#ifdef CONFIG_SENSORS_STK8BA53 + if (sensor->devid != STK8BA53_ID) { + printk(KERN_ERR "%s: stk8ba53 is not attached, devid=0x%x\n", __func__, sensor->devid); + return -ENODEV; + } +#else + if (sensor->devid == STK8BA53_ID) { + printk(KERN_ERR "%s: stk8ba50/stk8ba50-R is not attached, devid=0x%x\n", __func__, sensor->devid); + return -ENODEV; + } +#endif + if (sensor->pdata->irq_enable) { + /* map new data int to int1 */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_INTMAP2, 0x01); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_INTMAP2, result); + return result; + } + /* enable new data in */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_INTEN2, 0x10); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_INTEN2, result); + return result; + } + /* non-latch int */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_INTCFG2, 0x00); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_INTCFG2, result); + return result; + } + /* filtered data source for new data int */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_DATASRC, 0x00); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_DATASRC, result); + return result; + } + /* int1, push-pull, active high */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_INTCFG1, 0x01); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_INTCFG1, result); + return result; + } + } +#ifdef CONFIG_SENSORS_STK8BA53 + /* +- 4g */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_RANGESEL, STK_DEF_DYNAMIC_RANGE); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_RANGESEL, result); + return result; + } +#else + /* +- 2g */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_RANGESEL, STK_DEF_DYNAMIC_RANGE); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_RANGESEL, result); + return result; + } +#endif + /* ODR = 62 Hz */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_BWSEL, STK8BAXX_INIT_ODR); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_BWSEL, result); + return result; + } + + /* i2c watchdog enable, 1 ms timer perios */ + result = stk8baxx_smbus_write_byte_data(STK8BAXX_INTFCFG, 0x04); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_INTFCFG, result); + return result; + } + + result = stk8baxx_smbus_write_byte_data(STK8BAXX_POWMODE, STK8BAXX_MD_SUSPEND); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_POWMODE, result); + return result; + } + atomic_set(&stk->enabled, 0); + stk->first_enable = true; + atomic_set(&stk->cali_status, STK_K_NO_CALI); + atomic_set(&stk->recv_reg, 0); +#ifdef STK_LOWPASS + memset(&stk->fir, 0x00, sizeof(stk->fir)); + atomic_set(&stk->firlength, STK_FIR_LEN); + atomic_set(&stk->fir_en, 1); +#endif + + for (aa = 0; aa < 3; aa++) + stk->stk_tune_offset_record[aa] = 0; +#ifdef STK_TUNE + for (aa = 0; aa < 3; aa++) { + stk->stk_tune_offset[aa] = 0; + stk->stk_tune_sum[aa] = 0; + stk->stk_tune_max[aa] = 0; + stk->stk_tune_min[aa] = 0; + stk->stk_tune_square_sum[aa] = 0LL; + stk->variance[aa] = 0; + } + stk->stk_tune_done = 0; + stk->stk_tune_index = 0; +#endif + stk->event_since_en_limit = STK_EVENT_SINCE_EN_LIMIT_DEF; + + return 0; +} + +#ifdef STK_LOWPASS +static void stk8baxx_low_pass(struct stk8baxx_data *stk, struct stk8baxx_acc *acc_lp) +{ + int idx, firlength = atomic_read(&stk->firlength); +#ifdef STK_ZG_FILTER + s16 zero_fir = 0; +#endif + + if (atomic_read(&stk->fir_en)) { + if (stk->fir.num < firlength) { + stk->fir.raw[stk->fir.num][0] = acc_lp->x; + stk->fir.raw[stk->fir.num][1] = acc_lp->y; + stk->fir.raw[stk->fir.num][2] = acc_lp->z; + stk->fir.sum[0] += acc_lp->x; + stk->fir.sum[1] += acc_lp->y; + stk->fir.sum[2] += acc_lp->z; + stk->fir.num++; + stk->fir.idx++; + } else { + idx = stk->fir.idx % firlength; + stk->fir.sum[0] -= stk->fir.raw[idx][0]; + stk->fir.sum[1] -= stk->fir.raw[idx][1]; + stk->fir.sum[2] -= stk->fir.raw[idx][2]; + stk->fir.raw[idx][0] = acc_lp->x; + stk->fir.raw[idx][1] = acc_lp->y; + stk->fir.raw[idx][2] = acc_lp->z; + stk->fir.sum[0] += acc_lp->x; + stk->fir.sum[1] += acc_lp->y; + stk->fir.sum[2] += acc_lp->z; + stk->fir.idx++; +#ifdef STK_ZG_FILTER + if (abs(stk->fir.sum[0] / firlength) <= STK_ZG_COUNT) + acc_lp->x = (stk->fir.sum[0] * zero_fir) / firlength; + else + acc_lp->x = stk->fir.sum[0] / firlength; + if (abs(stk->fir.sum[1] / firlength) <= STK_ZG_COUNT) + acc_lp->y = (stk->fir.sum[1] * zero_fir) / firlength; + else + acc_lp->y = stk->fir.sum[1] / firlength; + if (abs(stk->fir.sum[2] / firlength) <= STK_ZG_COUNT) + acc_lp->z = (stk->fir.sum[2] * zero_fir) / firlength; + else + acc_lp->z = stk->fir.sum[2] / firlength; +#else + acc_lp->x = stk->fir.sum[0] / firlength; + acc_lp->y = stk->fir.sum[1] / firlength; + acc_lp->z = stk->fir.sum[2] / firlength; +#endif + } + } +} +#endif + +#ifdef STK_TUNE +static void stk8baxx_reset_para(struct stk8baxx_data *stk) +{ + int ii; + + for (ii = 0; ii < 3; ii++) { + stk->stk_tune_sum[ii] = 0; + stk->stk_tune_square_sum[ii] = 0LL; + stk->stk_tune_min[ii] = 4096; + stk->stk_tune_max[ii] = -4096; + stk->variance[ii] = 0; + } +} + +static void stk8baxx_tune(struct stk8baxx_data *stk, struct stk8baxx_acc *acc_xyz) +{ + int ii; + u8 offset[3]; + s16 acc[3]; + s64 s64_temp; + const s64 var_enlarge_scale = 64; + + if (stk->stk_tune_done != 0) + return; + + acc[0] = acc_xyz->x; + acc[1] = acc_xyz->y; + acc[2] = acc_xyz->z; + + if (stk->event_since_en >= STK_TUNE_DELAY) { + if ((abs(acc[0]) <= STK_TUNE_XYOFFSET) && (abs(acc[1]) <= STK_TUNE_XYOFFSET) && + (abs(abs(acc[2]) - STK_LSB_1G) <= STK_TUNE_ZOFFSET)) { + stk->stk_tune_index++; + /* printk("\n-qhy20161108--%s----acc[0]=0x%x,,acc[1]=0x%x,,acc[2]=0x%x\n",__func__,acc[0],acc[1],acc[2]); */ + } else { + stk->stk_tune_index = 0; + } + + if (stk->stk_tune_index == 0) { + stk8baxx_reset_para(stk); + /* printk("\n--qhy20161108--%s-- %d--\n",__func__,__LINE__); */ + } else { + for (ii = 0; ii < 3; ii++) { + stk->stk_tune_sum[ii] += acc[ii]; + stk->stk_tune_square_sum[ii] += acc[ii] * acc[ii]; + if (acc[ii] > stk->stk_tune_max[ii]) + stk->stk_tune_max[ii] = acc[ii]; + if (acc[ii] < stk->stk_tune_min[ii]) + stk->stk_tune_min[ii] = acc[ii]; + } + } + + if (stk->stk_tune_index == STK_TUNE_NUM) { + for (ii = 0; ii < 3; ii++) { + if ((stk->stk_tune_max[ii] - stk->stk_tune_min[ii]) > STK_TUNE_NOISE) { + stk->stk_tune_index = 0; + stk8baxx_reset_para(stk); + return; + } + } + + stk->stk_tune_offset[0] = stk->stk_tune_sum[0] / STK_TUNE_NUM; + stk->stk_tune_offset[1] = stk->stk_tune_sum[1] / STK_TUNE_NUM; + if (acc[2] > 0) + stk->stk_tune_offset[2] = stk->stk_tune_sum[2] / STK_TUNE_NUM - STK_LSB_1G; + else + stk->stk_tune_offset[2] = stk->stk_tune_sum[2] / STK_TUNE_NUM - (-STK_LSB_1G); + + offset[0] = (u8)(-stk->stk_tune_offset[0]); + offset[1] = (u8)(-stk->stk_tune_offset[1]); + offset[2] = (u8)(-stk->stk_tune_offset[2]); + stk->stk_tune_offset_record[0] = offset[0]; + stk->stk_tune_offset_record[1] = offset[1]; + stk->stk_tune_offset_record[2] = offset[2]; + + stk->stk_tune_done = 1; + atomic_set(&stk->cali_status, STK_K_SUCCESS_TUNE); + stk->event_since_en = 0; + printk(KERN_INFO "%s:TUNE done, %d,%d,%d\n", __func__, offset[0], offset[1], offset[2]); + printk(KERN_INFO "%s:TUNE done, var=%u,%u,%u\n", __func__, stk->variance[0], stk->variance[1], stk->variance[2]); + } + } +} +#endif + +static void stk8baxx_sign_conv(struct stk8baxx_data *stk, s16 raw_acc_data[], u8 acc_reg_data[]) +{ +#ifdef CONFIG_SENSORS_STK8BA53 + raw_acc_data[0] = acc_reg_data[1] << 8 | acc_reg_data[0]; + raw_acc_data[0] >>= 4; + raw_acc_data[1] = acc_reg_data[3] << 8 | acc_reg_data[2]; + raw_acc_data[1] >>= 4; + raw_acc_data[2] = acc_reg_data[5] << 8 | acc_reg_data[4]; + raw_acc_data[2] >>= 4; +#else + raw_acc_data[0] = acc_reg_data[1] << 8 | acc_reg_data[0]; + raw_acc_data[0] >>= 6; + raw_acc_data[1] = acc_reg_data[3] << 8 | acc_reg_data[2]; + raw_acc_data[1] >>= 6; + raw_acc_data[2] = acc_reg_data[5] << 8 | acc_reg_data[4]; + raw_acc_data[2] >>= 6; +#endif +} + +static int stk8baxx_set_enable(struct stk8baxx_data *stk, char en) +{ + s8 result; + s8 write_buffer = 0; + int new_enabled = (en) ? 1 : 0; + + /*int k_status = atomic_read(&stk->cali_status);*/ +#ifdef STK_DEBUG_PRINT + printk("%s:+++1+++--k_status=%d,first_enable=%d\n", __func__, k_status, stk->first_enable); + if (stk->first_enable && k_status != STK_K_RUNNING) { + stk->first_enable = false; + printk("%s:+++2+++first_enable=%d\n", __func__, stk->first_enable); + stk8baxx_load_cali(stk); + } +#endif + enable_status = new_enabled; + if (new_enabled == atomic_read(&stk->enabled)) + return 0; + /* printk(KERN_INFO "%s:%x\n", __func__, en); */ + + if (en) + write_buffer = STK8BAXX_MD_NORMAL; + else + write_buffer = STK8BAXX_MD_SUSPEND; + + result = stk8baxx_smbus_write_byte_data(STK8BAXX_POWMODE, write_buffer); + if (result < 0) { + printk(KERN_ERR "%s:failed to write reg 0x%x, error=%d\n", __func__, STK8BAXX_POWMODE, result); + goto error_enable; + } + + if (en) { + stk->event_since_en = 0; +#ifdef STK_TUNE + if ((k_status & 0xF0) != 0 && stk->stk_tune_done == 0) { + stk->stk_tune_index = 0; + stk8baxx_reset_para(stk); + } +#endif + } + + atomic_set(&stk->enabled, new_enabled); + return 0; + +error_enable: + return result; +} + +static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + + /* Report acceleration sensor information */ + input_report_abs(sensor->input_dev, ABS_X, axis->x); + input_report_abs(sensor->input_dev, ABS_Y, axis->y); + input_report_abs(sensor->input_dev, ABS_Z, axis->z); + input_sync(sensor->input_dev); +#ifdef STK_DEBUG_PRINT + printk(KERN_INFO "Gsensor x==%d y==%d z==%d\n", axis->x, axis->y, axis->z); +#endif + return 0; +} + +static int stk8baxx_read_sensor_data(struct stk8baxx_data *stk) +{ + int result; + u8 acc_reg[6]; + int x, y, z; + struct stk8baxx_acc acc; + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(stk->client); + struct sensor_platform_data *pdata = sensor->pdata; + s16 raw_acc[3]; + + acc.x = 0; + acc.y = 0; + acc.z = 0; + + *acc_reg = sensor->ops->read_reg; + result = sensor_rx_data(stk->client, (char *)acc_reg, sensor->ops->read_len); + if (result < 0) { + printk(KERN_ERR "%s: failed to read acc data, error=%d\n", __func__, result); + return result; + } + + stk8baxx_sign_conv(stk, raw_acc, acc_reg); +#ifdef STK_DEBUG_PRINT + printk(KERN_INFO "%s: raw_acc=%4d,%4d,%4d\n", __func__, (int)raw_acc[0], (int)raw_acc[1], (int)raw_acc[2]); +#endif + acc.x = raw_acc[0]; + acc.y = raw_acc[1]; + acc.z = raw_acc[2]; +#ifdef STK_TUNE + if ((k_status & 0xF0) != 0) + stk8baxx_tune(stk, &acc); +#endif + x = acc.x; + y = acc.y; + z = acc.z; + acc.x = (pdata->orientation[0]) * x + (pdata->orientation[1]) * y + (pdata->orientation[2]) * z; + acc.y = (pdata->orientation[3]) * x + (pdata->orientation[4]) * y + (pdata->orientation[5]) * z; + acc.z = (pdata->orientation[6]) * x + (pdata->orientation[7]) * y + (pdata->orientation[8]) * z; + +#ifdef STK_LOWPASS + stk8baxx_low_pass(stk, &acc); +#endif + + stk->acc_xyz.x = acc.x; + stk->acc_xyz.y = acc.y; + stk->acc_xyz.z = acc.z; +#ifdef STK_DEBUG_PRINT + printk(KERN_INFO "stk8baxx acc= %4d, %4d, %4d\n", (int)stk->acc_xyz.x, (int)stk->acc_xyz.y, (int)stk->acc_xyz.z); +#endif + return 0; +} + +static int sensor_report_value(struct i2c_client *client) +{ + unsigned int xyz_adc_rang = 0; + struct sensor_axis axis; + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + static int flag; + + stk8baxx_read_sensor_data(stk8baxx_data_ptr); + + xyz_adc_rang = STK_LSB_1G * STK_DEF_RANGE; + axis.x = stk8baxx_data_ptr->acc_xyz.x * (STK8BAXX_RANGE_UG / xyz_adc_rang); + axis.y = stk8baxx_data_ptr->acc_xyz.y * (STK8BAXX_RANGE_UG / xyz_adc_rang); + axis.z = stk8baxx_data_ptr->acc_xyz.z * (STK8BAXX_RANGE_UG / xyz_adc_rang); + + /* + *input dev will ignore report data if data value is the same with last_value, + *sample rate will not enough by this way, so just avoid this case + */ + if ((sensor->axis.x == axis.x) && (sensor->axis.y == axis.y) && (sensor->axis.z == axis.z)) { + if (flag) { + flag = 0; + axis.x += 1; + axis.y += 1; + axis.z += 1; + } else { + flag = 1; + axis.x -= 1; + axis.y -= 1; + axis.z -= 1; + } + } + + gsensor_report_value(client, &axis); + + mutex_lock(&sensor->data_mutex); + sensor->axis = axis; + mutex_unlock(&sensor->data_mutex); + + return 0; +} + +static int sensor_active(struct i2c_client *client, int enable, int rate) +{ + if (enable) + stk8baxx_set_enable(stk8baxx_data_ptr, 1); + else + stk8baxx_set_enable(stk8baxx_data_ptr, 0); + + return 0; +} + +static int sensor_init(struct i2c_client *client) +{ + int ret = 0; + struct stk8baxx_data *stk; + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + + printk(KERN_INFO "driver version:%s\n", STK_ACC_DRIVER_VERSION); + if (!enable_status) + return 0; + stk = kzalloc(sizeof(*stk), GFP_KERNEL); + if (!stk) { + printk(KERN_ERR "%s:memory allocation error\n", __func__); + return -ENOMEM; + } + stk8baxx_data_ptr = stk; + sensor_ptr = sensor; + stk->stk8baxx_placement = STK8BAXX_DEF_PLACEMENT; + stk->client = client; + ret = stk8baxx_reg_init(stk, client, sensor); + if (ret) { + printk(KERN_ERR "%s:stk8baxx initialization failed\n", __func__); + return ret; + } + stk->re_enable = false; + sensor->status_cur = SENSOR_OFF; + + /* Sys Attribute Register */ + if (no_create_att) { + struct input_dev *p_input_dev = NULL; + + p_input_dev = input_allocate_device(); + if (!p_input_dev) { + dev_err(&client->dev, + "Failed to allocate input device\n"); + return -ENOMEM; + } + + p_input_dev->name = "stk8baxx_attr"; + set_bit(EV_ABS, p_input_dev->evbit); + dev_set_drvdata(&p_input_dev->dev, stk); + ret = input_register_device(p_input_dev); + if (ret) { + dev_err(&client->dev, + "Unable to register input device %s\n", p_input_dev->name); + return ret; + } + + DBG("Sys Attribute Register here %s is called for stk8baxx.\n", __func__); + no_create_att = 0; + } + + return 0; +} + +struct sensor_operate gsensor_stk8baxx_ops = { + .name = "gs_stk8baxx", + .type = SENSOR_TYPE_ACCEL, /*sensor type and it should be correct*/ + .id_i2c = ACCEL_ID_STK8BAXX, /*i2c id number*/ + .read_reg = STK8BAXX_XOUT1, /*read data*/ + .read_len = 6, /*data length*/ + .id_reg = SENSOR_UNKNOW_DATA, /*read device id from this register*/ + .id_data = SENSOR_UNKNOW_DATA, /*device id*/ + .precision = SENSOR_UNKNOW_DATA, /*12 bit*/ + .ctrl_reg = STK8BAXX_POWMODE, /*enable or disable*/ + /*intterupt status register*/ + .int_status_reg = STK8BAXX_INTSTS2, + .range = {-STK8BAXX_RANGE_UG, STK8BAXX_RANGE_UG}, /*range*/ + .trig = IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + .active = sensor_active, + .init = sensor_init, + .report = sensor_report_value, +}; + +static struct sensor_operate *stk8baxx_get_ops(void) +{ + return &gsensor_stk8baxx_ops; +} + +static int __init stk8baxx_init(void) +{ + struct sensor_operate *ops = stk8baxx_get_ops(); + int type = ops->type; + + return sensor_register_slave(type, NULL, NULL, stk8baxx_get_ops); +} + +static void __exit stk8baxx_exit(void) +{ + struct sensor_operate *ops = stk8baxx_get_ops(); + int type = ops->type; + + sensor_unregister_slave(type, NULL, NULL, stk8baxx_get_ops); +} + +module_init(stk8baxx_init); +module_exit(stk8baxx_exit); + +MODULE_AUTHOR("Lex Hsieh, Sensortek"); +MODULE_DESCRIPTION("stk8baxx 3-Axis accelerometer driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(STK_ACC_DRIVER_VERSION); diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c index f880460620ff..816a56a92a04 100644 --- a/drivers/input/sensors/sensor-dev.c +++ b/drivers/input/sensors/sensor-dev.c @@ -2012,6 +2012,7 @@ static const struct i2c_device_id sensor_id[] = { {"mpu6500_acc", ACCEL_ID_MPU6500}, {"lsm330_acc", ACCEL_ID_LSM330}, {"bma2xx_acc", ACCEL_ID_BMA2XX}, + {"gs_stk8baxx", ACCEL_ID_STK8BAXX}, /*compass*/ {"compass", COMPASS_ID_ALL}, {"ak8975", COMPASS_ID_AK8975}, @@ -2066,6 +2067,7 @@ static struct of_device_id sensor_dt_ids[] = { { .compatible = "gs_mc3230" }, { .compatible = "lsm330_acc" }, { .compatible = "bma2xx_acc" }, + { .compatible = "gs_stk8baxx" }, /*compass*/ { .compatible = "ak8975" }, { .compatible = "ak8963" }, diff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.h index 8909c4faaad5..19a8f03f3e0c 100644 --- a/include/linux/sensor-dev.h +++ b/include/linux/sensor-dev.h @@ -59,6 +59,7 @@ enum sensor_id { ACCEL_ID_MPU6500, ACCEL_ID_LSM330, ACCEL_ID_BMA2XX, + ACCEL_ID_STK8BAXX, COMPASS_ID_ALL, COMPASS_ID_AK8975, COMPASS_ID_AK8963, From caf5f8628864eb6904af3cd7af25804f8973f8cd Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Tue, 6 Feb 2018 15:45:59 +0800 Subject: [PATCH 322/427] Revert "drivers: input: sensors: reset sensor rate" This reverts commit 3726b810fe652dbe17bc09500452c94dcb36fbef. Change-Id: I23692bb090f5a1c946b57071366d4611bc3d7189 Signed-off-by: Zorro Liu --- drivers/input/sensors/sensor-dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c index 816a56a92a04..5c3e9da79f03 100644 --- a/drivers/input/sensors/sensor-dev.c +++ b/drivers/input/sensors/sensor-dev.c @@ -491,10 +491,10 @@ static int sensor_reset_rate(struct i2c_client *client, int rate) dev_info(&client->dev, "set sensor poll time to %dms\n", rate); /* work queue is always slow, we need more quickly to match hal rate */ - if (sensor->pdata->poll_delay_ms == (rate - 5)) + if (sensor->pdata->poll_delay_ms == (rate - 2)) return 0; - sensor->pdata->poll_delay_ms = rate - 5; + sensor->pdata->poll_delay_ms = rate - 2; if (sensor->status_cur == SENSOR_ON) { if (!sensor->pdata->irq_enable) { From f29923d12029ef791242321d2af03e55078a39f0 Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sat, 3 Feb 2018 11:47:26 +0800 Subject: [PATCH 323/427] arm64: dts: rockchip: add headset detect for rk3326 Change-Id: Ia816a8f8fdcdd2265841965a59654e3b5f13cc06 Signed-off-by: Binyuan Lan --- .../boot/dts/rockchip/rk3326-863-lp3-v10.dts | 15 ++++++++++++++- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index d7ca8b7cf8d8..be7db00881ab 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -98,6 +98,13 @@ }; }; + rk_headset { + compatible = "rockchip_headset"; + headset_gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; clocks = <&cru SCLK_WIFI_PMU>; @@ -541,10 +548,16 @@ }; &pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + pmic { pmic_int: pmic_int { rockchip,pins = - <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index d86dc42435ac..d4e51dc87f15 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -158,6 +158,14 @@ }; }; + rk_headset { + compatible = "rockchip_headset"; + headset_gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + io-channels = <&saradc 1>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk817 1>;*/ @@ -655,10 +663,16 @@ }; &pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + pmic { pmic_int: pmic_int { rockchip,pins = - <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; }; }; From 762aa32d74eed93b9f6a7688c17c90dccecb0fa7 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Fri, 9 Feb 2018 09:33:44 +0800 Subject: [PATCH 324/427] ARM: dts: rk3288-android: Add hdmi route Change-Id: I0c0848abac414b1c03afc564a2375e12ec9ab422 Signed-off-by: Algea Cao --- arch/arm/boot/dts/rk3288-android.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-android.dtsi b/arch/arm/boot/dts/rk3288-android.dtsi index 13456d018646..aacddd06dc1c 100644 --- a/arch/arm/boot/dts/rk3288-android.dtsi +++ b/arch/arm/boot/dts/rk3288-android.dtsi @@ -231,6 +231,15 @@ charge_logo,mode = "center"; connect = <&vopl_out_lvds>; }; + + route_hdmi: route-hdmi { + status = "disabled"; + logo,uboot = "logo.bmp"; + logo,kernel = "logo_kernel.bmp"; + logo,mode = "center"; + charge_logo,mode = "center"; + connect = <&vopb_out_hdmi>; + }; }; }; From 3cd33bec9296bbf840a0b01ec855fbf04411b28f Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 9 Feb 2018 11:31:00 +0800 Subject: [PATCH 325/427] arm64: dts: rockchip: correct ep-gpios for rk3399 sapphire PCIe slot Change-Id: I349d7f9267e50d90afb12902ee4ced98f8e4cfa5 Signed-off-by: Shawn Lin --- arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi index 8e4b9e6141b5..2e0caf1e76a4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi @@ -522,7 +522,7 @@ }; &pcie0 { - ep-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + ep-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>; num-lanes = <4>; pinctrl-names = "default"; pinctrl-0 = <&pcie_clkreqn>; From 57123b5e034058507239f66916c9d5be1d97071a Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 9 Feb 2018 10:44:21 +0800 Subject: [PATCH 326/427] arm: dts: modify dmc frequency of normal to 600M for rk322x Change-Id: Idbff23336040ac33c6906cc350483f0877e216e4 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk322x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 153babf5e393..7362235a229b 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -167,7 +167,7 @@ operating-points-v2 = <&dmc_opp_table>; system-status-freq = < /*system status freq(KHz)*/ - SYS_STATUS_NORMAL 400000 + SYS_STATUS_NORMAL 600000 SYS_STATUS_VIDEO_4K 600000 SYS_STATUS_VIDEO_4K_10B 786000 >; From edd344986fc767354997b15383d909a66f86535e Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Fri, 9 Feb 2018 14:25:58 +0800 Subject: [PATCH 327/427] power: rk817: fix the error when plug in OTG [ 36.485506] [] __queue_delayed_work+0x6c/0x148 [ 36.485523] [] queue_delayed_work_on+0x50/0x6c [ 36.485543] [] rk817_charge_host_evt_notifier+0x20/0x2c [ 36.485561] [] notifier_call_chain+0x48/0x80 [ 36.485576] [] raw_notifier_call_chain+0x14/0x1c [ 36.485596] [] extcon_sync+0x74/0x1c4 [ 36.485615] [] rockchip_usb2phy_id_irq+0x270/0x2b8 [ 36.485633] [] irq_thread_fn+0x28/0x68 [ 36.485648] [] irq_thread+0x100/0x1d8 [ 36.485662] [] kthread+0xe8/0xf0 [ 36.485678] [] ret_from_fork+0x10/0x30 Change-Id: Ib1a50dbf2210e43efb056835e4fef1caae2ca059 Signed-off-by: shengfei Xu --- drivers/power/rk817_charger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/rk817_charger.c b/drivers/power/rk817_charger.c index c2c426e608f0..2378f5b449be 100644 --- a/drivers/power/rk817_charger.c +++ b/drivers/power/rk817_charger.c @@ -1083,9 +1083,9 @@ static int rk817_charge_host_evt_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct rk817_charger *charge = - container_of(nb, struct rk817_charger, cable_discnt_nb); + container_of(nb, struct rk817_charger, cable_host_nb); - queue_delayed_work(charge->usb_charger_wq, &charge->discnt_work, + queue_delayed_work(charge->usb_charger_wq, &charge->host_work, msecs_to_jiffies(10)); return NOTIFY_DONE; From d0524a053140474f7484ef497e249b3a7bd0c302 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:00:27 +0800 Subject: [PATCH 328/427] arm64: rockchip_defconfig: remove CONFIG_CGROUP_DEBUG 97841e574afb ("ANDROID: android-base.cfg: remove CONFIG_CGROUP_DEBUG") This config option is not required by Android. Change-Id: Ica7ed956e2340d5fd8756a400d13725799857423 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index c7141119969f..bc86b44ad0e5 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -9,7 +9,6 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=19 CONFIG_CGROUPS=y -CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y From b14ec5d805290cc2e8cb864314a2567c19299826 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:06:37 +0800 Subject: [PATCH 329/427] ARM: rockchip_defconfig: remove CONFIG_CGROUP_DEBUG 97841e574afb ("ANDROID: android-base.cfg: remove CONFIG_CGROUP_DEBUG") This config option is not required by Android. Change-Id: I2c57f98f94465d56aac60fe12b9b4d0a42d42242 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 0767deb0640a..ea2042768b90 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -10,7 +10,6 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=19 CONFIG_CGROUPS=y -CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y From 75b2bdbcf39b26746e811531905bd778f21d2dd7 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Fri, 9 Feb 2018 15:00:41 +0800 Subject: [PATCH 330/427] mfd: rk808: fix the shutdown function for rk817 Change-Id: Ieb980e9d2c779821d90061e79cebd302554176fc Signed-off-by: shengfei Xu --- drivers/mfd/rk808.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index a37ebd70e334..09a2260906d2 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -148,7 +148,7 @@ static int rk817_shutdown_prepare(struct regmap *regmap) /* pmic sleep shutdown function */ ret = regmap_update_bits(regmap, RK817_SYS_CFG(3), - RK817_SLPPIN_FUNC_MSK, SHUTDOWN_FUN); + RK817_SLPPIN_FUNC_MSK, SLPPIN_DN_FUN); return ret; } From 7c4d90fc8ab0fec490711d42deb411265777e356 Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 9 Feb 2018 15:05:25 +0800 Subject: [PATCH 331/427] arm64: dts: rockchip: Remove unused sdmmc1 pinctrl for px30 1. remove sdmmc1 pinctrl 2. move sdio pinctrl to sdmmc together Change-Id: Ibcde69298cfdfdd99228de941082cde6be6dfa6b Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/px30.dtsi | 59 ++++++++------------------ 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 6a067e6f4678..4c89dbe25c4c 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -2022,38 +2022,33 @@ }; }; - sdmmc1 { - sdmmc1_clk: sdmmc1-clk { + sdio { + sdio_clk: sdio-clk { rockchip,pins = - <1 RK_PC5 RK_FUNC_1 &pcfg_pull_none_8ma>; + <1 RK_PC5 RK_FUNC_1 &pcfg_pull_none>; }; - sdmmc1_cmd: sdmmc1-cmd { + sdio_cmd: sdio-cmd { rockchip,pins = - <1 RK_PC4 RK_FUNC_1 &pcfg_pull_up_8ma>; + <1 RK_PC4 RK_FUNC_1 &pcfg_pull_up>; }; - sdmmc1_bus1: sdmmc1-bus1 { + sdio_bus4: sdio-bus4 { rockchip,pins = - <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up_8ma>; + <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PC7 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PD0 RK_FUNC_1 &pcfg_pull_up>, + <1 RK_PD1 RK_FUNC_1 &pcfg_pull_up>; }; - sdmmc1_bus4: sdmmc1-bus4 { + sdio_gpio: sdio-gpio { rockchip,pins = - <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up_8ma>, - <1 RK_PC7 RK_FUNC_1 &pcfg_pull_up_8ma>, - <1 RK_PD0 RK_FUNC_1 &pcfg_pull_up_8ma>, - <1 RK_PD1 RK_FUNC_1 &pcfg_pull_up_8ma>; - }; - - sdmmc1_gpio: sdmmc1-gpio { - rockchip,pins = - <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up_4ma>, - <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up_4ma>, - <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up_4ma>, - <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up_4ma>, - <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, - <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; }; @@ -2454,25 +2449,5 @@ rockchip,pins = <3 RK_PD1 RK_FUNC_4 &pcfg_pull_none>;/* ISP_PRELIGHTTRIG */ }; }; - - sdio { - sdio_bus4: sdio-bus4 { - rockchip,pins = - <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up>, - <1 RK_PC7 RK_FUNC_1 &pcfg_pull_up>, - <1 RK_PD0 RK_FUNC_1 &pcfg_pull_up>, - <1 RK_PD1 RK_FUNC_1 &pcfg_pull_up>; - }; - - sdio_cmd: sdio-cmd { - rockchip,pins = - <1 RK_PC4 RK_FUNC_1 &pcfg_pull_up>; - }; - - sdio_clk: sdio-clk { - rockchip,pins = - <1 RK_PC5 RK_FUNC_1 &pcfg_pull_none>; - }; - }; }; }; From f4d7a8591d4d73dda9ec7adc64a1a45a32ff713a Mon Sep 17 00:00:00 2001 From: Zhou weixin Date: Fri, 9 Feb 2018 10:27:54 +0800 Subject: [PATCH 332/427] arm64: dts: rockchip: px30: Add sdmmc iomux Change-Id: I3debec6ca7010d2e15f1302d3403852a951da768 Signed-off-by: Weixin Zhou --- arch/arm64/boot/dts/rockchip/px30.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 4c89dbe25c4c..5b10f1a0004f 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -910,6 +910,8 @@ power-domains = <&power PX30_PD_SDCARD>; fifo-depth = <0x100>; interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; status = "disabled"; }; @@ -1998,6 +2000,11 @@ <1 RK_PD7 RK_FUNC_1 &pcfg_pull_up_4ma>; }; + sdmmc0_det: sdmmc0-det { + rockchip,pins = + <0 RK_PA3 RK_FUNC_1 &pcfg_pull_up_4ma>; + }; + sdmmc0_bus1: sdmmc0-bus1 { rockchip,pins = <1 RK_PD2 RK_FUNC_1 &pcfg_pull_up_4ma>; From 880bdfc09763dd1612246140a9912fbb43adba44 Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 9 Feb 2018 15:15:01 +0800 Subject: [PATCH 333/427] arm64: dts: rockchip: Change the pinctrl name sdmmc0 to sdmmc for px30 Change-Id: I57a4d732337fcf4356234e58658dd82655e53751 Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/px30.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 5b10f1a0004f..eff77e3531ae 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -911,7 +911,7 @@ fifo-depth = <0x100>; interrupts = ; pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>; status = "disabled"; }; @@ -1989,28 +1989,28 @@ }; }; - sdmmc0 { - sdmmc0_clk: sdmmc0-clk { + sdmmc { + sdmmc_clk: sdmmc-clk { rockchip,pins = <1 RK_PD6 RK_FUNC_1 &pcfg_pull_none_4ma>; }; - sdmmc0_cmd: sdmmc0-cmd { + sdmmc_cmd: sdmmc-cmd { rockchip,pins = <1 RK_PD7 RK_FUNC_1 &pcfg_pull_up_4ma>; }; - sdmmc0_det: sdmmc0-det { + sdmmc_det: sdmmc-det { rockchip,pins = <0 RK_PA3 RK_FUNC_1 &pcfg_pull_up_4ma>; }; - sdmmc0_bus1: sdmmc0-bus1 { + sdmmc_bus1: sdmmc-bus1 { rockchip,pins = <1 RK_PD2 RK_FUNC_1 &pcfg_pull_up_4ma>; }; - sdmmc0_bus4: sdmmc0-bus4 { + sdmmc_bus4: sdmmc-bus4 { rockchip,pins = <1 RK_PD2 RK_FUNC_1 &pcfg_pull_up_4ma>, <1 RK_PD3 RK_FUNC_1 &pcfg_pull_up_4ma>, @@ -2018,7 +2018,7 @@ <1 RK_PD5 RK_FUNC_1 &pcfg_pull_up_4ma>; }; - sdmmc0_gpio: sdmmc0-gpio { + sdmmc_gpio: sdmmc-gpio { rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up_4ma>, <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up_4ma>, From ce71feccf991a66677b41fc9a4299dd304781603 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:18:21 +0800 Subject: [PATCH 334/427] arm64: rockchip_defconfig: remove NETFILTER_XT_MATCH_QUOTA2_LOG bc86c1de1ded ("ANDROID: android-base.cfg: remove NETFILTER_XT_MATCH_QUOTA2_LOG") There are currently a couple different implementations for this functionality. Until things are unified, remove the requirement for this kernel config. Change-Id: Ibbe93ae71d4b7512be397e689abc36ba51011b30 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index bc86b44ad0e5..fecd026a5a3f 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -163,7 +163,6 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y From 7f9eafd04711e8a3f666a02d2fa50b931f578832 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:30:39 +0800 Subject: [PATCH 335/427] ARM: rockchip_defconfig: remove NETFILTER_XT_MATCH_QUOTA2_LOG bc86c1de1ded ("ANDROID: android-base.cfg: remove NETFILTER_XT_MATCH_QUOTA2_LOG") There are currently a couple different implementations for this functionality. Until things are unified, remove the requirement for this kernel config. Change-Id: Ia3f515452871118dab4b8688ff9fd16e87beb9b6 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index ea2042768b90..226eef102434 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -150,7 +150,6 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y From 4db3204bdbe2fa39a83d28fb623e8b09e5e146a9 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:33:56 +0800 Subject: [PATCH 336/427] arm64: rockchip_defconfig: remove USB_OTG_WAKELOCK cc756e682c1a ("ANDROID: android-base.cfg: remove USB_OTG_WAKELOCK") CONFIG_USB_OTG_WAKELOCK is currently somewhat outdated and as such is not applicable to all Android devices. Until it is brought up to date, remove it from the base Android kernel configuration. Change-Id: Id112f1e692fce021b8ab5437ae7811c216c8d272 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index fecd026a5a3f..ffa2cff14d9a 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -657,7 +657,6 @@ CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_OPTION=y CONFIG_USB_TRANCEVIBRATOR=y -CONFIG_USB_OTG_WAKELOCK=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_VBUS_DRAW=500 From 393a65de77f9fa41d9a599a132f9fb9e08e731be Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 15:36:07 +0800 Subject: [PATCH 337/427] ARM: rockchip_defconfig: remove USB_OTG_WAKELOCK cc756e682c1a ("ANDROID: android-base.cfg: remove USB_OTG_WAKELOCK") CONFIG_USB_OTG_WAKELOCK is currently somewhat outdated and as such is not applicable to all Android devices. Until it is brought up to date, remove it from the base Android kernel configuration. Change-Id: I4d6a2ba78ddc9210bc949ee2ecc5182a4814715d Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 226eef102434..78c5bf63feb3 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -562,7 +562,6 @@ CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_OPTION=y CONFIG_USB_TRANCEVIBRATOR=y -CONFIG_USB_OTG_WAKELOCK=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_VBUS_DRAW=500 From d06bd5047d17404272ffcc1a1e2efff230dc950e Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Fri, 9 Feb 2018 15:35:43 +0800 Subject: [PATCH 338/427] drm/rockchip: vop: default set to premultiplied alpha mode Change-Id: I006d2d7bda2413d3796a14c23a34fe2beea878a8 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 42ced600c78f..593c5981cb81 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1659,6 +1659,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, SRC_FACTOR_M0(global_alpha_en ? ALPHA_SRC_GLOBAL : ALPHA_ONE); VOP_WIN_SET(vop, win, src_alpha_ctl, val); + VOP_WIN_SET(vop, win, alpha_pre_mul, 1); VOP_WIN_SET(vop, win, alpha_mode, 1); VOP_WIN_SET(vop, win, alpha_en, 1); } else { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index e62efd27a53f..269a5c5cf56a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -380,6 +380,7 @@ struct vop_win_phy { struct vop_reg src_alpha_ctl; struct vop_reg alpha_mode; struct vop_reg alpha_en; + struct vop_reg alpha_pre_mul; struct vop_reg global_alpha_val; struct vop_reg key_color; struct vop_reg key_en; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index cd90ddcb74c4..4c90b77d2c1a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1245,6 +1245,7 @@ static const struct vop_win_phy rk3366_lit_win0_data = { .yrgb_vir = VOP_REG(RK3366_LIT_WIN0_VIR, 0x1fff, 0), .uv_vir = VOP_REG(RK3366_LIT_WIN0_VIR, 0x1fff, 16), + .alpha_pre_mul = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0x1, 2), .alpha_mode = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0x1, 0), .global_alpha_val = VOP_REG(RK3366_LIT_WIN0_ALPHA_CTRL, 0xff, 4), @@ -1264,6 +1265,7 @@ static const struct vop_win_phy rk3366_lit_win1_data = { .yrgb_mst = VOP_REG(RK3366_LIT_WIN1_MST, 0xffffffff, 0), .yrgb_vir = VOP_REG(RK3366_LIT_WIN1_VIR, 0x1fff, 0), + .alpha_pre_mul = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0x1, 2), .alpha_mode = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0x1, 0), .global_alpha_val = VOP_REG(RK3366_LIT_WIN1_ALPHA_CTRL, 0xff, 4), @@ -1471,6 +1473,7 @@ static const struct vop_win_phy px30_win23_data = { .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), + .alpha_pre_mul = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 2), .alpha_mode = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 1), .alpha_en = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0x1, 0), .global_alpha_val = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 4), From 569bb500f837adc7a76cf6864a1aa0249786aa38 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Fri, 9 Feb 2018 14:23:44 +0800 Subject: [PATCH 339/427] arm64: dts: rockchip: rk3326: use extcon specifier for the charger Change-Id: Ie84c6be541c6489ca93cef38f5ad3741851fdb59 Signed-off-by: shengfei Xu --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 1 + arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index be7db00881ab..347cb34619c6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -482,6 +482,7 @@ chrg_finish_cur = <300>; virtual_power = <0>; dc_det_adc = <0>; + extcon = <&u2phy>; }; rk817_codec: rk817-codec { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index d4e51dc87f15..8ff707b7d58a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -573,6 +573,7 @@ chrg_finish_cur = <300>; virtual_power = <0>; dc_det_adc = <0>; + extcon = <&u2phy>; }; rk817_codec: rk817-codec { From bcc83cb2ff7e799128920b3933d06471afbc8bd5 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 6 Feb 2018 09:23:46 +0800 Subject: [PATCH 340/427] drm/bridge: Support rk1000 kernel logo Setting connector port to support kernel logo Change-Id: I594eec0a924ecf1c47c82d61c471dd21c2af1830 Signed-off-by: Algea Cao --- drivers/gpu/drm/bridge/rk1000.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/rk1000.c b/drivers/gpu/drm/bridge/rk1000.c index 1169cab2abfc..1d2cd03ade0c 100644 --- a/drivers/gpu/drm/bridge/rk1000.c +++ b/drivers/gpu/drm/bridge/rk1000.c @@ -311,6 +311,7 @@ static int rk1000_bridge_attach(struct drm_bridge *bridge) bridge->encoder); if (ret) dev_err(rk1000->dev, "rk1000 attach failed ret:%d", ret); + rk1000->connector.port = rk1000->dev->of_node; return ret; } From 4262e671f950b5141db7c5899c1939fb07e94149 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 6 Feb 2018 09:26:14 +0800 Subject: [PATCH 341/427] arm64: dts: rk3368-r88: support rk3368 drm cvbs uboot logo Removing ports so that uboot display subsystem can get rk1000 as panel. Change-Id: If12c30bb7d1bd382ed969534687234aa79b8dd04 Signed-off-by: Algea Cao --- arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index ccc09e7cf30c..61bc28c76115 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -474,14 +474,12 @@ rockchip,data-width = <24>; rockchip,output = "rgb"; rockchip,ctl = <&rk1000_ctl>; - ports { - #address-cells = <1>; - #size-cells = <0>; - tve_in: port@0 { - reg = <0>; - tve_in_lvds: endpoint { - remote-endpoint = <&lvds_out_tve>; - }; + #address-cells = <1>; + #size-cells = <0>; + tve_in: port@0 { + reg = <0>; + tve_in_lvds: endpoint { + remote-endpoint = <&lvds_out_tve>; }; }; }; @@ -674,6 +672,10 @@ status = "okay"; }; +&route_lvds { + status = "okay"; +}; + &hdmi { status = "okay"; #sound-dai-cells = <0>; From 0b86943d0ed30018161959bed79c23c581b926c9 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 6 Feb 2018 09:19:33 +0800 Subject: [PATCH 342/427] mfd: rk1000: Support rk1000 uboot logo Reading rk1000's register to see whether uboot logo was on. Change-Id: Iee6d15213f16ccd59136a5cf4f4017f5cd40ab62 Signed-off-by: Algea Cao --- drivers/mfd/rk1000-core.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/mfd/rk1000-core.c b/drivers/mfd/rk1000-core.c index c003ab05a773..d35a040dc7d8 100644 --- a/drivers/mfd/rk1000-core.c +++ b/drivers/mfd/rk1000-core.c @@ -36,8 +36,6 @@ struct rk1000 { struct clk *mclk; }; -static int cvbsmode = -1; - static const struct mfd_cell rk1000_devs[] = { { .name = "rk1000-tve", @@ -60,23 +58,11 @@ struct regmap_config rk1000_regmap_config = { .volatile_table = &rk1000_ctl_reg_table, }; -static int __init bootloader_cvbs_setup(char *str) -{ - int ret = 0; - - if (str) - ret = kstrtoint(str, 0, &cvbsmode); - - return ret; -} - -early_param("tve.format", bootloader_cvbs_setup); - static int rk1000_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct device_node *rk1000_np; - int ret; + bool uboot_logo; + int ret, val = 0; struct rk1000 *rk1000 = devm_kzalloc(&client->dev, sizeof(*rk1000), GFP_KERNEL); if (!rk1000) @@ -84,13 +70,23 @@ static int rk1000_probe(struct i2c_client *client, rk1000->client = client; rk1000->dev = &client->dev; - rk1000_np = rk1000->dev->of_node; rk1000->regmap = devm_regmap_init_i2c(client, &rk1000_regmap_config); if (IS_ERR(rk1000->regmap)) return PTR_ERR(rk1000->regmap); - if (cvbsmode < 0) { + ret = regmap_read(rk1000->regmap, CTRL_TVE, &val); + + /* + * If rk1000's registers can be read and rk1000 cvbs output is + * enabled, we think uboot logo is on. + */ + if (!ret && val & BIT(6)) + uboot_logo = true; + else + uboot_logo = false; + + if (!uboot_logo) { /********Get reset pin***********/ rk1000->io_reset = devm_gpiod_get_optional(rk1000->dev, "reset", GPIOD_OUT_LOW); @@ -121,7 +117,7 @@ static int rk1000_probe(struct i2c_client *client, regmap_write(rk1000->regmap, CTRL_ADC, ADC_OFF); regmap_write(rk1000->regmap, CTRL_CODEC, CODEC_OFF); regmap_write(rk1000->regmap, CTRL_I2C, I2C_TIMEOUT_PERIOD); - if (cvbsmode < 0) + if (!uboot_logo) regmap_write(rk1000->regmap, CTRL_TVE, TVE_OFF); ret = mfd_add_devices(rk1000->dev, -1, rk1000_devs, From 3c4e6c90408509bbfc52a4fd0eb34b6e784ed100 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 16:05:52 +0800 Subject: [PATCH 343/427] arm64: rockchip_defconfig: remove CONFIG_PM_AUTOSLEEP 6e30a9a158bd ("remove CONFIG_PM_AUTOSLEEP from android-base.cfg") Autosleep is no longer used by Android. Change-Id: I7ff5c40a8cdfbe9e67019bc859eb940fae2b6c4f Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index ffa2cff14d9a..1f810ed5c1cd 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -72,7 +72,6 @@ CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_EFI is not set # CONFIG_COREDUMP is not set CONFIG_COMPAT=y -CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set From e868d4ecb9fb54ea602b090bdbd10d8fbb5ea53c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 16:09:13 +0800 Subject: [PATCH 344/427] ARM: rockchip_defconfig: remove CONFIG_PM_AUTOSLEEP 6e30a9a158bd ("remove CONFIG_PM_AUTOSLEEP from android-base.cfg") Autosleep is no longer used by Android. Change-Id: Ia024dbb6343abd8e1016febc08251dc5dc7badc1 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 78c5bf63feb3..93f4ad05101e 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -72,7 +72,6 @@ CONFIG_VFP=y CONFIG_NEON=y CONFIG_KERNEL_MODE_NEON=y # CONFIG_COREDUMP is not set -CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set From 6716ded4596f9cd41292f0d0f9cdcaffb436614c Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Fri, 9 Feb 2018 16:27:43 +0800 Subject: [PATCH 345/427] arm64: dts: rockchip: add spi1 cs1 for px30 Change-Id: I933b76ed4b312a713e390c130ef6b5c090e3779c Signed-off-by: Huibin Hong --- arch/arm64/boot/dts/rockchip/px30.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index eff77e3531ae..47202fa47822 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -550,7 +550,7 @@ #dma-cells = <2>; dma-names = "tx", "rx"; pinctrl-names = "default"; - pinctrl-0 = <&spi1_clk &spi1_csn &spi1_miso &spi1_mosi>; + pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>; status = "disabled"; }; @@ -1770,11 +1770,16 @@ <3 RK_PB7 RK_FUNC_4 &pcfg_pull_up>; }; - spi1_csn: spi1-csn { + spi1_csn0: spi1-csn0 { rockchip,pins = <3 RK_PB1 RK_FUNC_4 &pcfg_pull_up>; }; + spi1_csn1: spi1-csn1 { + rockchip,pins = + <3 RK_PB2 RK_FUNC_2 &pcfg_pull_up>; + }; + spi1_miso: spi1-miso { rockchip,pins = <3 RK_PB6 RK_FUNC_4 &pcfg_pull_up>; From 6f04df2fa9355f172a5ffcdfb6859d286f24e861 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 16:29:30 +0800 Subject: [PATCH 346/427] arm64: rockchip_defconfig: enable CONFIG_AIO 4ed084e489fd ("Move CONFIG_AIO to android-base.") CONFIG_AIO has legitimate use for the functionfs driver, which is used with adb and mtp. It is now required to be enabled for better performance with those services. Change-Id: I631fac8e56ea16711f0cc05297140dc59c9fb581 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 1f810ed5c1cd..e13c40e26778 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -29,7 +29,6 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y -# CONFIG_AIO is not set CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set From 4b4a117433eebef1676715d3c10325aea4f56c74 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 16:34:23 +0800 Subject: [PATCH 347/427] ARM: rockchip_defconfig: enable CONFIG_AIO 4ed084e489fd ("Move CONFIG_AIO to android-base.") CONFIG_AIO has legitimate use for the functionfs driver, which is used with adb and mtp. It is now required to be enabled for better performance with those services. Change-Id: I52d05c734a25b35e012666b010b2ee5426915094 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 93f4ad05101e..4c3a0ccdde50 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -26,7 +26,6 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y -# CONFIG_AIO is not set CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set From d51654309d931dcb96a562ffa91adef7f9eb6c0c Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Fri, 9 Feb 2018 16:32:10 +0800 Subject: [PATCH 348/427] spi: rockchip: test: remove unused code Change-Id: I7b44f7c3a8e32eaf2c550d915c45a3394816c925 Signed-off-by: Huibin Hong --- drivers/spi/spi-rockchip-test.c | 62 +++------------------------------ 1 file changed, 5 insertions(+), 57 deletions(-) diff --git a/drivers/spi/spi-rockchip-test.c b/drivers/spi/spi-rockchip-test.c index 9b2ac14d33bc..5ae3af5c4b66 100755 --- a/drivers/spi/spi-rockchip-test.c +++ b/drivers/spi/spi-rockchip-test.c @@ -17,6 +17,7 @@ spi_test@00 { compatible = "rockchip,spi_test_bus0_cs0"; reg = <0>; //chip select 0:cs0 1:cs1 + id = <0>; spi-max-frequency = <24000000>; //spi output clock //spi-cpha; not support //spi-cpol; //if the property is here it is 1:clk is high, else 0:clk is low when idle @@ -25,6 +26,7 @@ spi_test@01 { compatible = "rockchip,spi_test_bus0_cs1"; reg = <1>; + id = <1>; spi-max-frequency = <24000000>; spi-cpha; spi-cpol; @@ -36,6 +38,7 @@ * echo write 0 10 255 > /dev/spi_misc_test * echo write 0 10 255 init.rc > /dev/spi_misc_test * echo read 0 10 255 > /dev/spi_misc_test +* echo loop 0 10 255 > /dev/spi_misc_test * echo setspeed 0 1000000 > /dev/spi_misc_test */ @@ -61,7 +64,6 @@ #include #include #include -#include "spi-rockchip-core.h" #define MAX_SPI_DEV_NUM 6 #define SPI_MAX_SPEED_HZ 12000000 @@ -314,9 +316,11 @@ static ssize_t spi_test_write(struct file *file, kfree(txbuf); kfree(rxbuf); } else { + printk("echo id number size > /dev/spi_misc_test\n"); printk("echo write 0 10 255 > /dev/spi_misc_test\n"); printk("echo write 0 10 255 init.rc > /dev/spi_misc_test\n"); printk("echo read 0 10 255 > /dev/spi_misc_test\n"); + printk("echo loop 0 10 255 > /dev/spi_misc_test\n"); printk("echo setspeed 0 1000000 > /dev/spi_misc_test\n"); } @@ -333,60 +337,10 @@ static struct miscdevice spi_test_misc = { .fops = &spi_test_fops, }; -#ifdef CONFIG_OF -static struct dw_spi_chip *rockchip_spi_parse_dt(struct device *dev) -{ - u32 temp; - struct dw_spi_chip *spi_chip_data; - - spi_chip_data = devm_kzalloc(dev, sizeof(*spi_chip_data), GFP_KERNEL); - if (!spi_chip_data) { - dev_err(dev, "memory allocation for spi_chip_data failed\n"); - return ERR_PTR(-ENOMEM); - } - - if (of_property_read_u32(dev->of_node, "poll_mode", &temp)) { - dev_warn(dev, "fail to get poll_mode, default set 0\n"); - spi_chip_data->poll_mode = 0; - } else { - spi_chip_data->poll_mode = temp; - } - - if (of_property_read_u32(dev->of_node, "type", &temp)) { - dev_warn(dev, "fail to get type, default set 0\n"); - spi_chip_data->type = 0; - } else { - spi_chip_data->type = temp; - } - - if (of_property_read_u32(dev->of_node, "enable_dma", &temp)) { - dev_warn(dev, "fail to get enable_dma, default set 0\n"); - spi_chip_data->enable_dma = 0; - } else { - spi_chip_data->enable_dma = temp; - } -#if 0 - if (of_property_read_u32(dev->of_node, "slave-enable", &temp)) { - dev_warn(dev, "fail to get slave-enable, default set 0\n"); - spi_chip_data->slave_enable = 0; - } else { - spi_chip_data->slave_enable = temp; - } -#endif - return spi_chip_data; -} -#else -static struct spi_board_info *rockchip_spi_parse_dt(struct device *dev) -{ - return dev->platform_data; -} -#endif - static int rockchip_spi_test_probe(struct spi_device *spi) { int ret; int id = 0; - struct dw_spi_chip *spi_chip_data = NULL; struct spi_test_data *spi_test_data = NULL; if (!spi) @@ -395,17 +349,12 @@ static int rockchip_spi_test_probe(struct spi_device *spi) if (!spi->dev.of_node) return -ENOMEM; - spi_chip_data = rockchip_spi_parse_dt(&spi->dev); - if (IS_ERR(spi_chip_data)) - return -ENOMEM; - spi_test_data = (struct spi_test_data *)kzalloc(sizeof(struct spi_test_data), GFP_KERNEL); if (!spi_test_data) { dev_err(&spi->dev, "ERR: no memory for spi_test_data\n"); return -ENOMEM; } spi->bits_per_word = 8; - spi->controller_data = spi_chip_data; spi_test_data->spi = spi; spi_test_data->dev = &spi->dev; @@ -425,7 +374,6 @@ static int rockchip_spi_test_probe(struct spi_device *spi) printk("%s:name=%s,bus_num=%d,cs=%d,mode=%d,speed=%d\n", __func__, spi->modalias, spi->master->bus_num, spi->chip_select, spi->mode, spi->max_speed_hz); - printk("%s:poll_mode=%d, type=%d, enable_dma=%d\n", __func__, spi_chip_data->poll_mode, spi_chip_data->type, spi_chip_data->enable_dma); return ret; } From 02dcfc342041b7bd30c63ca17c690d3d58ae27e5 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Fri, 9 Feb 2018 16:51:48 +0800 Subject: [PATCH 349/427] arm64: dts: rockchip: add uart aliases, modify uart1 clk for px30 Change-Id: Ia1accabbb76c1f1e4deb11aae055bec328ec5a61 Signed-off-by: Huibin Hong --- arch/arm64/boot/dts/rockchip/px30.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 47202fa47822..67c7bc29f812 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -27,6 +27,9 @@ serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; @@ -400,7 +403,7 @@ reg = <0x0 0xff158000 0x0 0x100>; interrupts = ; clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; - clock-names = "sclk_uart", "pclk_uart"; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; dmas = <&dmac 2>, <&dmac 3>; From 68b095de9e69571ff760ca372e2f8d685ccb53c8 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Fri, 9 Feb 2018 16:45:13 +0800 Subject: [PATCH 350/427] spi: rockchip: add compatible rockchip,px30-spi for px30 Change-Id: Ibe406477b3912b482d07e5c0e7f8e2e99a51bd4a Signed-off-by: Huibin Hong --- Documentation/devicetree/bindings/spi/spi-rockchip.txt | 5 +++-- drivers/spi/spi-rockchip.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt b/Documentation/devicetree/bindings/spi/spi-rockchip.txt index d2ca153614f9..374c669e8230 100644 --- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt +++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt @@ -6,10 +6,11 @@ and display controllers using the SPI communication interface. Required Properties: - compatible: should be one of the following. - "rockchip,rk3036-spi" for rk3036 SoCS. + "rockchip,px30-spi" for px30 SoCs. + "rockchip,rk3036-spi" for rk3036 SoCs. "rockchip,rk3066-spi" for rk3066 SoCs. "rockchip,rk3188-spi" for rk3188 SoCs. - "rockchip,rk3228-spi" for rk3228 SoCS. + "rockchip,rk3228-spi" for rk3228 SoCs. "rockchip,rk3288-spi" for rk3288 SoCs. "rockchip,rk3368-spi" for rk3368 SoCs. "rockchip,rk3399-spi" for rk3399 SoCs. diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index bd00b5db00c7..e9a2fe324168 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -891,6 +891,7 @@ static const struct dev_pm_ops rockchip_spi_pm = { }; static const struct of_device_id rockchip_spi_dt_match[] = { + { .compatible = "rockchip,px30-spi", }, { .compatible = "rockchip,rk3036-spi", }, { .compatible = "rockchip,rk3066-spi", }, { .compatible = "rockchip,rk3188-spi", }, From 99079676c225d3e89cd5c4993a8d028f7ef9f6ae Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 9 Feb 2018 21:10:20 +0800 Subject: [PATCH 351/427] arm64: dts: rockchip: increase the i2c0 scl frequecny to 400k for rk3326-evb-lp3-v10 Base on the rise time of scl test, the scl frequecny could be increased to 400k. Change-Id: I9af57e13a97f0866ec4f0dd295f9bcf4cbeee304 Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 8ff707b7d58a..f5fd78774776 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -336,6 +336,9 @@ &i2c0 { status = "okay"; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <280>; + i2c-scl-falling-time-ns = <16>; rk817: pmic@20 { compatible = "rockchip,rk817"; From f8c5fa1e6be831e8f659660b9fade5dede313956 Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 9 Feb 2018 21:15:20 +0800 Subject: [PATCH 352/427] arm64: dts: rockchip: increase the i2c1 scl frequecny to 400k for rk3326-evb-lp3-v10 Base on the rise time of scl test, the scl frequecny could be increased to 400k. Change-Id: I17f858b28ed11992411c52e5f83424b0187d097c Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index f5fd78774776..486be0962e04 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -593,6 +593,9 @@ &i2c1 { status = "okay"; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <275>; + i2c-scl-falling-time-ns = <16>; sensor@0f { status = "okay"; From fd186f221be2dd44845673876c23342f5f0f7536 Mon Sep 17 00:00:00 2001 From: William Wu Date: Fri, 9 Feb 2018 20:40:42 +0800 Subject: [PATCH 353/427] CHROMIUM: usb: dwc3: rockchip: reset host controller at resume If we power off the SoC LOGIC rail in S3, it seems that the host controller comes back in an undefined state, such that the Type C PHY can't initialize correctly. We need to toggle the USB3-OTG reset before trying to initialize the PHY, or else it often times out. Note that the TRM suggests we should be asserting this reset for the duration of the PHY initialization, but we're still skeptical about that, and we haven't yet found a case where this seems to have mattered. Besides, this approach is much easier. The dwc3 core is going to reinitialize the controller at suspend/resume anyway (including a "soft reset"), so it should be safe to do this, regardless of whether the system actually powered off the USB logic. For hygiene's sake, it's good to wait some small bit of time in between asserting/de-asserting this reset. Might as well apply this to both instances of this reset. BUG=b:62644399 TEST=suspend/resume scarlet with LOGIC disabled in S3; USB comes back OK also test suspend/resume on kevin for USB regressions Change-Id: I5b5354d0fb9c7ed9d2c9044ddfbb5f7709884fb7 Signed-off-by: Brian Norris Signed-off-by: William Wu Reviewed-on: https://chromium-review.googlesource.com/877404 Reviewed-by: Douglas Anderson --- drivers/usb/dwc3/dwc3-rockchip.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-rockchip.c b/drivers/usb/dwc3/dwc3-rockchip.c index e313a0755f7f..4e113be31618 100644 --- a/drivers/usb/dwc3/dwc3-rockchip.c +++ b/drivers/usb/dwc3/dwc3-rockchip.c @@ -945,6 +945,10 @@ static int dwc3_rockchip_resume(struct device *dev) struct dwc3_rockchip *rockchip = dev_get_drvdata(dev); struct dwc3 *dwc = rockchip->dwc; + reset_control_assert(rockchip->otg_rst); + udelay(1); + reset_control_deassert(rockchip->otg_rst); + rockchip->suspended = false; if (rockchip->edev) From 33e05f0c2188251255ffdc20421feae9fe34ebd8 Mon Sep 17 00:00:00 2001 From: William Wu Date: Fri, 9 Feb 2018 20:43:14 +0800 Subject: [PATCH 354/427] CHROMIUM: phy: rockchip-typec: enable usb3 host after pipe ready If we power off the SoC LOGIC rail in S3, we can find that the Type-C PHY can't initialize correctly after system resume with error log looked like this: phy phy-ff800000.phy.9: phy poweron failed --> -110 dwc3 fe900000.dwc3: failed to initialize core dwc3: probe of fe900000.dwc3 failed with error -110 It's because that the field of usb3tousb2 in GRF_USB3PHY0/1_CON0 is reset to 1 after power off the SoC LOGIC, which means that the pipe interface is blocked between Tpye-C PHY and usb3 controller. And after system resume, the rockchip_usb3_phy_power_on() will call the tcphy_cfg_usb3_to_usb2_only() to clear the usb3tousb2 bit and enable the usb3 host again. If we clear the usb3tousb2 bit before pipe ready, it may cause waiting for pipe ready timeout. Note that the RK3399 TRM suggests that we should keep the whole usb3 controller in reset for the duration of the Type-C PHY initialization. However, it's hard to assert the reset in the current framework of reset. And according to the TRM, it doesn't require that we should clear the usb3tousb2 bit before pipe ready. So let's enable the usb3 host after pipe ready to avoid the Type-C PHY initialization failure. BUG=b:62644399, chromium:783464 TEST=run suspend_stess_test on Scarlet, usb device can work after resume Change-Id: Ie597cbe35568c390460aa2fdbad0e66c6104c8d2 Reviewed-on: https://chromium-review.googlesource.com/896908 Commit-Ready: Brian Norris Tested-by: Brian Norris Reviewed-by: Brian Norris Signed-off-by: William Wu --- drivers/phy/rockchip/phy-rockchip-typec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index 9d00ea40fcc5..133a790163c1 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -877,6 +877,9 @@ static int _rockchip_usb3_phy_power_on(struct rockchip_typec_phy *tcphy) regmap_read(tcphy->grf_regs, reg->offset, &val); if (!(val & BIT(reg->enable_bit))) { tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB); + + /* enable usb3 host */ + tcphy_cfg_usb3_to_usb2_only(tcphy, false); goto unlock_ret; } usleep_range(10, 20); From a250f09aff2de1725b3eee83bfb33f80f8d6c4c2 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 1 Feb 2018 20:25:56 +0800 Subject: [PATCH 355/427] clk: rockchip: rk3128: Add sclk_hsadc_tsp Change-Id: I842869a7ea79730daa6616f1cf2a8f5db7165ceb Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3128.c | 2 ++ include/dt-bindings/clock/rk3128-cru.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c index c5f58e8d15e9..74475bd07a54 100644 --- a/drivers/clk/rockchip/clk-rk3128.c +++ b/drivers/clk/rockchip/clk-rk3128.c @@ -448,6 +448,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { COMPOSITE(SCLK_TSP, "sclk_tsp", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(1), 14, GFLAGS), + GATE(SCLK_HSADC_TSP, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0, + RK2928_CLKGATE_CON(10), 13, GFLAGS), COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(2), 14, 2, MFLAGS, 8, 5, DFLAGS, diff --git a/include/dt-bindings/clock/rk3128-cru.h b/include/dt-bindings/clock/rk3128-cru.h index c1db54acfef3..f775d9e0f7d8 100644 --- a/include/dt-bindings/clock/rk3128-cru.h +++ b/include/dt-bindings/clock/rk3128-cru.h @@ -75,6 +75,7 @@ #define SCLK_CIF_OUT 152 #define SCLK_SFC 153 #define SCLK_USB480M 154 +#define SCLK_HSADC_TSP 155 /* dclk gates */ #define DCLK_VOP 190 From 884b0673a7ba56b82d867669be7db82c6bdecabf Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 1 Feb 2018 20:36:37 +0800 Subject: [PATCH 356/427] clk: rockchip: rk3288: Add TSP clock Change-Id: I02185c5ab7a1072d271cd51161f6d4b05d327673 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3288.c | 8 ++++++-- include/dt-bindings/clock/rk3288-cru.h | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 72797f9479db..4adbace24ff7 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -534,10 +534,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3288_EMMC_CON0, 1), MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3288_EMMC_CON1, 0), - COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0, + COMPOSITE(SCLK_TSPOUT, "sclk_tspout", mux_tspout_p, 0, RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(4), 11, GFLAGS), - COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0, + COMPOSITE(SCLK_TSP, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0, RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(4), 10, GFLAGS), @@ -804,6 +804,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { INVERTER(PCLK_VIP, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS), GATE(PCLK_ISP_IN, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), + + GATE(SCLK_HSADC0_TSP, "clk_hsadc0_tsp", "ext_hsadc0_tsp", 0, RK3288_CLKGATE_CON(8), 9, GFLAGS), + GATE(SCLK_HSADC1_TSP, "clk_hsadc1_tsp", "ext_hsadc0_tsp", 0, RK3288_CLKGATE_CON(8), 10, GFLAGS), + GATE(SCLK_27M_TSP, "clk_27m_tsp", "ext_27m_tsp", 0, RK3288_CLKGATE_CON(8), 11, GFLAGS), }; static const char *const rk3288_critical_clocks[] __initconst = { diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h index 6cb872f1fbee..75df8524a620 100644 --- a/include/dt-bindings/clock/rk3288-cru.h +++ b/include/dt-bindings/clock/rk3288-cru.h @@ -91,6 +91,11 @@ #define SCLK_VIP_OUT 127 #define SCLK_DDRCLK 128 #define SCLK_I2S_SRC 129 +#define SCLK_TSPOUT 130 +#define SCLK_TSP 131 +#define SCLK_HSADC0_TSP 132 +#define SCLK_HSADC1_TSP 133 +#define SCLK_27M_TSP 134 #define SCLK_MAC_PLL 150 #define SCLK_MAC 151 From 319ff3657f05567cfdce5c899491a16696c43918 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 18:56:54 +0800 Subject: [PATCH 357/427] arm64: rockchip_defconfig: enable CONFIG_MEMORY_STATE_TIME f3d9c312b899 ("Implement memory_state_time, used by qcom,cpubw") New driver memory_state_time tracks time spent in different DDR frequency and bandwidth states. Memory drivers such as qcom,cpubw can post updated state to the driver after registering a callback. Processed by a workqueue Bandwidth buckets are read in from device tree in the relevant qualcomm section, can be defined in any quantity and spacing. The data is exposed at /sys/kernel/memory_state_time, able to be read by the Android framework. Functionality is behind a config option CONFIG_MEMORY_STATE_TIME Change-Id: I4391cc3ed42c9f332bce4a7809c6f120e2798dae Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index e13c40e26778..406dc58c712f 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -236,6 +236,7 @@ CONFIG_BLK_DEV_NVME=y CONFIG_ROCKCHIP_SCR=y CONFIG_SRAM=y CONFIG_UID_SYS_STATS=y +CONFIG_MEMORY_STATE_TIME=y CONFIG_USB_CAM_GPIO=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y From 9b3f148373e9766ad58680309c7c6dacf3a7c52f Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 18:59:44 +0800 Subject: [PATCH 358/427] ARM: rockchip_defconfig: enable CONFIG_MEMORY_STATE_TIME f3d9c312b899 ("Implement memory_state_time, used by qcom,cpubw") New driver memory_state_time tracks time spent in different DDR frequency and bandwidth states. Memory drivers such as qcom,cpubw can post updated state to the driver after registering a callback. Processed by a workqueue Bandwidth buckets are read in from device tree in the relevant qualcomm section, can be defined in any quantity and spacing. The data is exposed at /sys/kernel/memory_state_time, able to be read by the Android framework. Functionality is behind a config option CONFIG_MEMORY_STATE_TIME Change-Id: Ic3b0b631efd697713360f193ede440cd9ad3bc29 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 4c3a0ccdde50..3c32488f50b0 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -222,6 +222,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_ROCKCHIP_SCR=y CONFIG_SRAM=y CONFIG_UID_SYS_STATS=y +CONFIG_MEMORY_STATE_TIME=y CONFIG_USB_CAM_GPIO=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y From 9b2724a451ce6c2b3f9bffabb1e566c8469fcd5a Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Wed, 7 Feb 2018 16:36:09 +0800 Subject: [PATCH 359/427] thermal: rockchip: fix channal invertion issue for px30 Change-Id: Ifed5628c18cece0658754095e718da39ac703413 Signed-off-by: Rocky Hao --- drivers/thermal/rockchip_thermal.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 39b19e24a321..4049a4fa5e49 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -222,11 +222,15 @@ struct rockchip_thermal_data { #define GRF_TSADC_TESTBIT_L 0x0e648 #define GRF_TSADC_TESTBIT_H 0x0e64c +#define PX30_GRF_SOC_CON2 0x0408 + #define GRF_SARADC_TESTBIT_ON (0x10001 << 2) #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) #define GRF_TSADC_VCM_EN_L (0x10001 << 7) #define GRF_TSADC_VCM_EN_H (0x10001 << 7) +#define GRF_CON_TSADC_CH_INV (0x10001 << 1) + #define MIN_TEMP (-40000) #define MAX_TEMP (125000) @@ -635,6 +639,14 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs, regs + TSADCV2_AUTO_CON); } +static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs, + enum tshut_polarity tshut_polarity) +{ + rk_tsadcv2_initialize(grf, regs, tshut_polarity); + if (!IS_ERR(grf)) + regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV); +} + static void rk_tsadcv2_irq_ack(void __iomem *regs) { u32 val; @@ -879,7 +891,7 @@ static const struct rockchip_tsadc_chip px30_tsadc_data = { .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ .tshut_temp = 95000, - .initialize = rk_tsadcv2_initialize, + .initialize = rk_tsadcv4_initialize, .irq_ack = rk_tsadcv3_irq_ack, .control = rk_tsadcv3_control, .get_temp = rk_tsadcv2_get_temp, From 69441faf9e83bc1ef97e49696f32d6808c868b57 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Sat, 10 Feb 2018 14:38:53 +0800 Subject: [PATCH 360/427] mfd: rk808: rk809 chip name register is same as rk817 Change-Id: I22f5735ab3272a53d2e97012f452c340f16b0bff Signed-off-by: shengfei Xu --- drivers/mfd/rk808.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 09a2260906d2..5077d1836117 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -947,7 +947,8 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - if (of_device_is_compatible(np, "rockchip,rk817")) { + if (of_device_is_compatible(np, "rockchip,rk817") || + of_device_is_compatible(np, "rockchip,rk809")) { pmic_id_msb = RK817_ID_MSB; pmic_id_lsb = RK817_ID_LSB; } From 16bb8bd923d10b70b442a769267b56daa6264f89 Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Fri, 9 Feb 2018 16:12:20 +0800 Subject: [PATCH 361/427] arm64: dts: rockchip: px30: modify the isp reg range Change-Id: I3326908e0445c1230b73169b9d9b34a31658d0b2 Signed-off-by: Zhong Yichong --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 67c7bc29f812..15c6eda185db 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1217,7 +1217,7 @@ rk_isp: rk_isp@ff4a0000 { compatible = "rockchip,px30-isp", "rockchip,isp"; - reg = <0x0 0xff4a0000 0x0 0x4000>; + reg = <0x0 0xff4a0000 0x0 0x8000>; interrupts = ; clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>, <&cru SCLK_ISP>, <&cru SCLK_ISP>, <&cru PCLK_ISP>, <&cru SCLK_CIF_OUT>, <&cru SCLK_CIF_OUT>, <&cru PCLK_MIPICSIPHY>; From f943a72c3537544ca67ea8ec23e9749b9b7328ea Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Fri, 9 Feb 2018 17:29:47 +0800 Subject: [PATCH 362/427] arm64: dts: rockchip: px30: modify isp mipiphy count from 0 to 1 Change-Id: I878c8b6ee15885662c215b52143cd73474dd8cbf Signed-off-by: Zhong Yichong --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 15c6eda185db..a0d425ff5499 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1228,7 +1228,7 @@ power-domains = <&power PX30_PD_VI>; pinctrl-names = "default"; pinctrl-0 = <&cif_clkout_m0>; - rockchip,isp,mipiphy = <0>; + rockchip,isp,mipiphy = <1>; rockchip,isp,csiphy,reg = <0xff2f0000 0x4000>; rockchip,grf = <&grf>; rockchip,cru = <&cru>; From 0bef3afae981ee00cac329b72f06f9b2d3385b69 Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Fri, 9 Feb 2018 16:20:16 +0800 Subject: [PATCH 363/427] camera: rockchip: camsys_drv: disable cru reset of rk3326 isp now Because it will cause CPU hangs on, so disable the reset temporarily. Change-Id: I612be4b47145fd1ebf8d8e5d44270f26151768fa Signed-off-by: Zhong Yichong --- drivers/media/video/rk_camsys/camsys_soc_rk3326.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/rk_camsys/camsys_soc_rk3326.c b/drivers/media/video/rk_camsys/camsys_soc_rk3326.c index c65e855ce468..f3a18326eb4e 100644 --- a/drivers/media/video/rk_camsys/camsys_soc_rk3326.c +++ b/drivers/media/video/rk_camsys/camsys_soc_rk3326.c @@ -194,6 +194,7 @@ int camsys_rk3326_cfg } case Isp_SoftRst: {/* ddl@rock-chips.com: v0.d.0 */ +#if 0 unsigned long reset; reset = (unsigned long)cfg_para; @@ -206,8 +207,10 @@ int camsys_rk3326_cfg VI_IRCL)); camsys_trace(2, "Isp self soft rst: %ld", reset); break; +#else + break; +#endif } - default: { camsys_warn("cfg_cmd: 0x%x isn't support", cfg_cmd); From 80f0ef45dbe0b52da59b9a66c1bf40f1bec63558 Mon Sep 17 00:00:00 2001 From: Zhong Yichong Date: Fri, 9 Feb 2018 16:17:06 +0800 Subject: [PATCH 364/427] arm64: dts: rockchip: rk3326 evb: enable isp Change-Id: I0a41db448bbb51afcaa4b538cf0aefac25e7c762 Signed-off-by: Zhong Yichong --- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 486be0962e04..79dd072d12d4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -628,6 +628,10 @@ }; }; +&i2c2 { + status = "okay"; +}; + &i2s1_2ch { status = "okay"; #sound-dai-cells = <0>; @@ -643,6 +647,10 @@ vccio5-supply = <&vcc_3v0>; }; +&isp_mmu { + status = "okay"; +}; + &lvds { status = "disabled"; @@ -701,14 +709,18 @@ status = "okay"; }; -&route_dsi { - status = "disabled"; +&rk_isp { + status = "okay"; }; &rk_rga { status = "okay"; }; +&route_dsi { + status = "disabled"; +}; + &route_lvds { status = "disabled"; }; From 5f1c036a659a6f723a45926b016ca655b01bfecc Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Sat, 10 Feb 2018 17:20:06 +0800 Subject: [PATCH 365/427] drm/bridge: synopsys: dw-hdmi: fix kernel logo flash when output YCbCr422 mode On rockchip platform, hdmi input format is YCbCr444 when output mode is YCbCr422. Then the value of HDMI_TX_INVID0 on YCbCr422 is same as the value of YCbCr444, both is 0x09/0x0b. This make enc_out_bus_format stroed in struct hdmi_data is wrong, which is MEDIA_BUS_FMT_YUV8_1X24 or MEDIA_BUS_FMT_YUV10_1X30. When android set enc_out_bus_format to YCbCr422, dw_hdmi_setup will be called and logo will flash. This patch use colorspace restored in HDMI_FC_AVICONF0 to distinguish them. Change-Id: I6b913951b58fb47628617c11d6059bc1be4e370a Signed-off-by: Zheng Yang --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index cf4b7be4fd08..a7f2e381a5bd 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3024,12 +3024,16 @@ static void dw_hdmi_attatch_properties(struct dw_hdmi *hdmi) case 0x09: if (colorspace == HDMI_COLORSPACE_YUV420) color = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + else if (colorspace == HDMI_COLORSPACE_YUV422) + color = MEDIA_BUS_FMT_UYVY8_1X16; else color = MEDIA_BUS_FMT_YUV8_1X24; break; case 0x0b: if (colorspace == HDMI_COLORSPACE_YUV420) color = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + else if (colorspace == HDMI_COLORSPACE_YUV422) + color = MEDIA_BUS_FMT_UYVY10_1X20; else color = MEDIA_BUS_FMT_YUV10_1X30; break; From aed92d3f61beae86a81381f22dddf5b532e02651 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Sun, 11 Feb 2018 09:45:57 +0800 Subject: [PATCH 366/427] clk: rockchip: px30: Fix clk_i2s0_rx parent Change-Id: Ia523234cf5b210bbfe51cbf075943e7f44123ca9 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 0fdd71978fa5..2928b57b1d07 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -154,6 +154,7 @@ PNAME(mux_i2s0_rx_out_p) = { "clk_i2s0_rx", "xin12m", "clk_i2s0_tx"}; PNAME(mux_i2s1_out_p) = { "clk_i2s1", "xin12m"}; PNAME(mux_i2s2_out_p) = { "clk_i2s2", "xin12m"}; PNAME(mux_i2s0_tx_rx_p) = { "clk_i2s0_tx_mux", "clk_i2s0_rx_mux"}; +PNAME(mux_i2s0_rx_tx_p) = { "clk_i2s0_rx_mux", "clk_i2s0_tx_mux"}; PNAME(mux_uart_src_p) = { "gpll", "xin24m", "usb480m", "npll" }; PNAME(mux_uart1_p) = { "clk_uart1_src", "clk_uart1_np5", "clk_uart1_frac" }; PNAME(mux_uart2_p) = { "clk_uart2_src", "clk_uart2_np5", "clk_uart2_frac" }; @@ -656,7 +657,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKSEL_CON(59), 0, PX30_CLKGATE_CON(17), 1, GFLAGS, &px30_i2s0_rx_fracmux), - COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT, + COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_rx_tx_p, CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(58), 12, 1, MFLAGS, PX30_CLKGATE_CON(17), 2, GFLAGS), COMPOSITE_NODIV(0, "clk_i2s0_rx_out_pre", mux_i2s0_rx_out_p, 0, From 424a08f4cb07123d6e355a1b529862f2523f15ea Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Sat, 10 Feb 2018 11:06:43 +0800 Subject: [PATCH 367/427] drm/rockchip: px30 vop: delete win2 Change-Id: If36214c7f57c96d7a06e81db383300cff0669681 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 4c90b77d2c1a..7935777e4c56 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1486,10 +1486,12 @@ static const struct vop_win_data px30_vop_big_win_data[] = { { .base = 0x00, .phy = &rk3366_lit_win1_data, .type = DRM_PLANE_TYPE_CURSOR, .feature = WIN_FEATURE_AFBDC }, - { .base = 0xe0, .phy = &px30_win23_data, - .type = DRM_PLANE_TYPE_OVERLAY, - .area = rk3368_area_data, - .area_size = ARRAY_SIZE(rk3368_area_data), }, + /* + * { .base = 0xe0, .phy = &px30_win23_data, + * .type = DRM_PLANE_TYPE_OVERLAY, + * .area = rk3368_area_data, + * .area_size = ARRAY_SIZE(rk3368_area_data), }, + */ }; static const struct vop_win_data px30_vop_lit_win_data[] = { From ce0ec8d27b704c51409ac331e929951a519bdb01 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Sun, 11 Feb 2018 16:54:27 +0800 Subject: [PATCH 368/427] drm/rockchip: vop: alpha_pre_mul mode depend on user space Change-Id: Iaada438902ddddbbd00890c53a58cc49af3c3d3e Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 6 ++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 16 +++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index b61acb058745..82a444318d29 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1138,6 +1138,12 @@ static int rockchip_drm_create_properties(struct drm_device *dev) return -ENOMEM; private->global_alpha_prop = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "BLEND_MODE", 0, 1); + if (!prop) + return -ENOMEM; + private->blend_mode_prop = prop; + return drm_mode_create_tv_properties(dev, 0, NULL); } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 239c08c342ca..2e274a77ed92 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -176,6 +176,7 @@ struct rockchip_drm_private { struct drm_property *eotf_prop; struct drm_property *color_space_prop; struct drm_property *global_alpha_prop; + struct drm_property *blend_mode_prop; void *backlight; struct drm_fb_helper *fbdev_helper; struct drm_gem_object *fbdev_bo; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 593c5981cb81..3e6798b4b821 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -168,6 +168,7 @@ struct vop_plane_state { unsigned int csc_mode; bool enable; int global_alpha; + int blend_mode; }; struct vop_win { @@ -1659,7 +1660,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, SRC_FACTOR_M0(global_alpha_en ? ALPHA_SRC_GLOBAL : ALPHA_ONE); VOP_WIN_SET(vop, win, src_alpha_ctl, val); - VOP_WIN_SET(vop, win, alpha_pre_mul, 1); + VOP_WIN_SET(vop, win, alpha_pre_mul, + vop_plane_state->blend_mode); VOP_WIN_SET(vop, win, alpha_mode, 1); VOP_WIN_SET(vop, win, alpha_en, 1); } else { @@ -1782,6 +1784,11 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane, return 0; } + if (property == private->blend_mode_prop) { + plane_state->blend_mode = val; + return 0; + } + DRM_ERROR("failed to set vop plane property\n"); return -EINVAL; } @@ -1820,6 +1827,11 @@ static int vop_atomic_plane_get_property(struct drm_plane *plane, return 0; } + if (property == private->blend_mode_prop) { + *val = plane_state->blend_mode; + return 0; + } + DRM_ERROR("failed to get vop plane property\n"); return -EINVAL; } @@ -3653,6 +3665,8 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win, if (VOP_WIN_SUPPORT(vop, win, global_alpha_val)) drm_object_attach_property(&win->base.base, private->global_alpha_prop, 0xff); + drm_object_attach_property(&win->base.base, + private->blend_mode_prop, 0); return 0; } From f457f16cd2ba8176fb984a1b6c58d472c5f76877 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Sun, 11 Feb 2018 17:33:16 +0800 Subject: [PATCH 369/427] clk: rockchip: px30: Fix clk_gmac_rmii_sel parent Change-Id: Idf1bd416a3879048afd3763d4a6d056c34171bbb Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 2928b57b1d07..35bb637404ea 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -169,7 +169,7 @@ PNAME(mux_sdio_p) = { "clk_sdio_div", "clk_sdio_div50" }; PNAME(mux_emmc_p) = { "clk_emmc_div", "clk_emmc_div50" }; PNAME(mux_sdmmc_p) = { "clk_sdmmc_div", "clk_sdmmc_div50" }; PNAME(mux_gmac_p) = { "clk_gmac_src", "gmac_clkin" }; -PNAME(mux_gmac_rmii_sel_p) = { "clk_gmac_rx_tx_div2", "clk_gmac_rx_tx_div20" }; +PNAME(mux_gmac_rmii_sel_p) = { "clk_gmac_rx_tx_div20", "clk_gmac_rx_tx_div2" }; PNAME(mux_rtc32k_pmu_p) = { "xin32k", "pmu_pvtm_32k", "clk_rtc32k_frac", }; PNAME(mux_wifi_pmu_p) = { "xin24m", "clk_wifi_pmu_src" }; PNAME(mux_uart0_pmu_p) = { "clk_uart0_pmu_src", "clk_uart0_np5", "clk_uart0_frac" }; From 0cb664eb7614e23361aed02891ea43610b404d56 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 9 Feb 2018 15:13:26 +0800 Subject: [PATCH 370/427] clk: rockchip: px30: Remove clk_gpu_divnp5 Change-Id: I67f47f5fdd7873c22b1349e3aeb80b7157c7844c Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 35bb637404ea..ab6bd4b1dda6 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -136,7 +136,6 @@ PNAME(mux_armclk_p) = { "apll_core", "gpll_core" }; PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; PNAME(mux_ddrstdby_p) = { "clk_ddrphy1x", "clk_stdby_2wrap" }; PNAME(mux_4plls_p) = { "gpll", "cpll", "usb480m", "npll" }; -PNAME(mux_clk_gpu_p) = { "clk_gpu_div", "clk_gpu_divnp5" }; PNAME(mux_cpll_npll_p) = { "cpll", "npll" }; PNAME(mux_gpll_cpll_p) = { "gpll", "cpll" }; PNAME(mux_gpll_npll_p) = { "gpll", "npll" }; @@ -342,16 +341,12 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE_NODIV(0, "clk_gpu_src", mux_4plls_p, 0, PX30_CLKSEL_CON(1), 6, 2, MFLAGS, PX30_CLKGATE_CON(0), 8, GFLAGS), - COMPOSITE_NOMUX(0, "clk_gpu_div", "clk_gpu_src", 0, + COMPOSITE_NOMUX(0, "clk_gpu_div", "clk_gpu_src", CLK_SET_RATE_PARENT, PX30_CLKSEL_CON(1), 0, 4, DFLAGS, PX30_CLKGATE_CON(0), 12, GFLAGS), - COMPOSITE_NOMUX_DIVTBL(0, "clk_gpu_divnp5", "clk_gpu_src", 0, - PX30_CLKSEL_CON(1), 8, 4, DFLAGS | CLK_DIVIDER_ALLOW_ZERO, div_np5_t, - PX30_CLKGATE_CON(0), 9, GFLAGS), - COMPOSITE_NODIV(0, "clk_gpu_pre", mux_clk_gpu_p, CLK_SET_RATE_PARENT, - PX30_CLKSEL_CON(1), 15, 1, MFLAGS, + GATE(ACLK_GPU, "clk_gpu_pre", "clk_gpu_div", 0, PX30_CLKGATE_CON(0), 10, GFLAGS), - COMPOSITE_NOMUX(ACLK_GPU, "aclk_gpu", "clk_gpu_pre", CLK_SET_RATE_PARENT, + COMPOSITE_NOMUX(0, "aclk_gpu", "clk_gpu_pre", CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(1), 13, 2, DFLAGS, PX30_CLKGATE_CON(17), 10, GFLAGS), GATE(0, "aclk_gpu_niu", "aclk_gpu", CLK_IGNORE_UNUSED, @@ -1019,7 +1014,6 @@ static const char *const px30_critical_clocks[] __initconst = { "aclk_peri_pre", "hclk_peri_pre", "aclk_gpu_niu", - "clk_gpu_divnp5", "pclk_top_pre", }; From 093bfc848c068d98ebddd5bf5ee583f98f45e82d Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 8 Feb 2018 19:18:52 +0800 Subject: [PATCH 371/427] clk: rockchip: rk3328: Fix clk_cif_src parent Change-Id: I0ea209224880b8c51a385ed46827bb0d8f7dd219 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3328.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c index 7e83b3dffa16..cfd99943c981 100644 --- a/drivers/clk/rockchip/clk-rk3328.c +++ b/drivers/clk/rockchip/clk-rk3328.c @@ -148,7 +148,7 @@ static const struct rockchip_cpuclk_reg_data rk3328_cpuclk_data = { }; PNAME(mux_pll_p) = { "xin24m" }; - +PNAME(mux_hdmiphy_gpll_p) = { "hdmiphy", "gpll" }; PNAME(mux_2plls_p) = { "cpll", "gpll" }; PNAME(mux_gpll_cpll_p) = { "gpll", "cpll" }; PNAME(mux_cpll_gpll_apll_p) = { "cpll", "gpll", "apll" }; @@ -592,7 +592,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { GATE(SCLK_HDMI_SFC, "clk_hdmi_sfc", "xin24m", 0, RK3328_CLKGATE_CON(5), 4, GFLAGS), - COMPOSITE_NODIV(0, "clk_cif_src", mux_2plls_p, 0, + COMPOSITE_NODIV(0, "clk_cif_src", mux_hdmiphy_gpll_p, 0, RK3328_CLKSEL_CON(42), 7, 1, MFLAGS, RK3328_CLKGATE_CON(5), 3, GFLAGS), COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cif_out", mux_sclk_cif_p, CLK_SET_RATE_PARENT, From 2a8ce270ad7f161a2c6473985c78118c8a5d8738 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Sun, 11 Feb 2018 11:27:50 +0800 Subject: [PATCH 372/427] arm64: dts: rockchip: remove the hdmi-cec pinctrl for rk3399 excavator As the edp_hpd pinctrl is reused by hdmi-cec. So the rk3399 will hit the pinctrl register failed on bootup. Says: the failed log: [0.927577] rockchip-pinctrl pinctrl: pin gpio4-23 already requested by ff940000.hdmi; cannot claim for ff970000.edp [0.928519 ] rockchip-pinctrl pinctrl: pin-151 (ff970000.edp) status -22 [0.929112] rockchip-pinctrl pinctrl: could not request pin 151 (gpio4-23) from group edp-hpd on device rockchip-pinctr That will cause the edp can't work on rk3399 SoCs. Fixes: commit 6e4eaff822fc ("arm64: dts: rockchip: add HDMI cec support for rk3399") Change-Id: I8ba20db55025e33c082beda5160e0398f1681766 Signed-off-by: Caesar Wang --- .../arm64/boot/dts/rockchip/rk3399-sapphire-excavator-linux.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator-linux.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator-linux.dts index 7ba30e807913..dc549b2bf67d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator-linux.dts @@ -218,6 +218,8 @@ }; &hdmi { + /* remove the hdmi_cec, reused by edp_hpd */ + pinctrl-0 = <&hdmi_i2c_xfer>; #address-cells = <1>; #size-cells = <0>; #sound-dai-cells = <0>; From 5db5490025755753ef3be771b730e6c55cc8754b Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Sun, 11 Feb 2018 11:17:26 +0800 Subject: [PATCH 373/427] drivers: input: sensors: update accel sensor mma7660 driver Change-Id: Id3cf0cf3a14a07010524d0de58dc523bfcb3b735 Signed-off-by: Zorro Liu --- drivers/input/sensors/accel/mma7660.c | 203 +++++++++++--------------- 1 file changed, 87 insertions(+), 116 deletions(-) diff --git a/drivers/input/sensors/accel/mma7660.c b/drivers/input/sensors/accel/mma7660.c index 59f3060bb402..77dad66141cb 100644 --- a/drivers/input/sensors/accel/mma7660.c +++ b/drivers/input/sensors/accel/mma7660.c @@ -31,129 +31,95 @@ #endif #include - -#define MMA7660_ENABLE 1 - -#define MMA7660_REG_X_OUT 0x0 -#define MMA7660_REG_Y_OUT 0x1 -#define MMA7660_REG_Z_OUT 0x2 -#define MMA7660_REG_TILT 0x3 -#define MMA7660_REG_SRST 0x4 -#define MMA7660_REG_SPCNT 0x5 -#define MMA7660_REG_INTSU 0x6 -#define MMA7660_REG_MODE 0x7 -#define MMA7660_REG_SR 0x8 -#define MMA7660_REG_PDET 0x9 -#define MMA7660_REG_PD 0xa - - -#define MMA7660_RANGE 1500000 - -/* LIS3DH */ -#define MMA7660_PRECISION 6 -#define MMA7660_BOUNDARY (0x1 << (MMA7660_PRECISION - 1)) -#define MMA7660_GRAVITY_STEP (MMA7660_RANGE / MMA7660_BOUNDARY) - -#define MMA7660_COUNT_AVERAGE 2 - -struct sensor_axis_average { - int x_average; - int y_average; - int z_average; - int count; -}; - -static struct sensor_axis_average axis_average; +#define MMA7660_ENABLE 1 +#define MMA7660_REG_X_OUT 0x0 +#define MMA7660_REG_Y_OUT 0x1 +#define MMA7660_REG_Z_OUT 0x2 +#define MMA7660_REG_TILT 0x3 +#define MMA7660_REG_SRST 0x4 +#define MMA7660_REG_SPCNT 0x5 +#define MMA7660_REG_INTSU 0x6 +#define MMA7660_REG_MODE 0x7 +#define MMA7660_REG_SR 0x8 +#define MMA7660_REG_PDET 0x9 +#define MMA7660_REG_PD 0xa +#define MMA7660_PRECISION 6 /****************operate according to sensor chip:start************/ static int sensor_active(struct i2c_client *client, int enable, int rate) { struct sensor_private_data *sensor = - (struct sensor_private_data *) i2c_get_clientdata(client); + (struct sensor_private_data *)i2c_get_clientdata(client); int result = 0; int status = 0; - + sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg); - - //register setting according to chip datasheet - if(enable) - { - status = MMA7660_ENABLE; //mma7660 + + if (enable) { + status = MMA7660_ENABLE; sensor->ops->ctrl_data |= status; - } - else - { - status = ~MMA7660_ENABLE; //mma7660 + } else { + status = ~MMA7660_ENABLE; sensor->ops->ctrl_data &= status; } - DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable); result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data); - if(result) - printk("%s:fail to active sensor\n",__func__); - - return result; + if (result) + dev_err(&client->dev, "%s:fail to active sensor\n", __func__); + return result; } static int sensor_init(struct i2c_client *client) { struct sensor_private_data *sensor = - (struct sensor_private_data *) i2c_get_clientdata(client); + (struct sensor_private_data *)i2c_get_clientdata(client); int result = 0; - - result = sensor->ops->active(client,0,0); - if(result) - { - printk("%s:line=%d,error\n",__func__,__LINE__); + + result = sensor->ops->active(client, 0, 0); + if (result) { + dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__); return result; } - + sensor->status_cur = SENSOR_OFF; - DBG("%s:MMA7660_REG_TILT=0x%x\n",__func__,sensor_read_reg(client, MMA7660_REG_TILT)); - - result = sensor_write_reg(client, MMA7660_REG_SR, (0x01<<5)| 0x02); //32 Samples/Second Active and Auto-Sleep Mode - if(result) - { - printk("%s:line=%d,error\n",__func__,__LINE__); + /*120 Samples/Second Active and Auto-Sleep Mode */ + result = sensor_write_reg(client, MMA7660_REG_SR, 0x01 << 5); + if (result) { + dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__); return result; } - if(sensor->pdata->irq_enable) //open interrupt - { - result = sensor_write_reg(client, MMA7660_REG_INTSU, 1<<4);//enable int,GINT=1 - if(result) - { - printk("%s:line=%d,error\n",__func__,__LINE__); + if (sensor->pdata->irq_enable) { + result = sensor_write_reg(client, MMA7660_REG_INTSU, 1 << 4); + if (result) { + dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__); return result; } } - - sensor->ops->ctrl_data = 1<<6; //Interrupt output INT is push-pull + + sensor->ops->ctrl_data = 1 << 6; result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data); - if(result) - { - printk("%s:line=%d,error\n",__func__,__LINE__); + if (result) { + dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__); return result; } - - memset(&axis_average, 0, sizeof(struct sensor_axis_average)); - return result; } - static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte) { - s64 result; + int result = (int)low_byte; - result = (int)low_byte; - result *= 768; + if (low_byte & 0x20) + result = ((~result & 0x1f) + 1) * (-768); + else + result = (result & 0x1f) * 768; - return (int)result; + return result; } static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis) @@ -172,43 +138,58 @@ static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *a return 0; } -#define GSENSOR_MIN 2 static int sensor_report_value(struct i2c_client *client) { struct sensor_private_data *sensor = - (struct sensor_private_data *) i2c_get_clientdata(client); + (struct sensor_private_data *)i2c_get_clientdata(client); struct sensor_platform_data *pdata = sensor->pdata; int ret = 0; - int x,y,z; + int x, y, z; struct sensor_axis axis; - char buffer[3] = {0}; + char buffer[3] = {0}; char value = 0; - - if(sensor->ops->read_len < 3) //sensor->ops->read_len = 3 - { - printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len); + static int flag; + + if (sensor->ops->read_len < 3) { + dev_err(&client->dev, "%s:lenth is error,len=%d\n", __func__, sensor->ops->read_len); return -1; } - + memset(buffer, 0, 3); - - /* Data bytes from hardware xL, xH, yL, yH, zL, zH */ + + /* Data bytes from hardware xL, xH, yL, yH, zL, zH */ do { *buffer = sensor->ops->read_reg; ret = sensor_rx_data(client, buffer, sensor->ops->read_len); if (ret < 0) - return ret; + return ret; } while (0); - - //this gsensor need 6 bytes buffer - x = sensor_convert_data(sensor->client, 0, buffer[0]); //buffer[1]:high bit + x = sensor_convert_data(sensor->client, 0, buffer[0]); y = sensor_convert_data(sensor->client, 0, buffer[1]); - z = sensor_convert_data(sensor->client, 0, buffer[2]); + z = sensor_convert_data(sensor->client, 0, buffer[2]); - axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z; - axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z; - axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z; + axis.x = (pdata->orientation[0]) * x + (pdata->orientation[1]) * y + (pdata->orientation[2]) * z; + axis.y = (pdata->orientation[3]) * x + (pdata->orientation[4]) * y + (pdata->orientation[5]) * z; + axis.z = (pdata->orientation[6]) * x + (pdata->orientation[7]) * y + (pdata->orientation[8]) * z; + + /* + *input dev will ignore report data if data value is the same with last_value, + *sample rate will not enough by this way, so just avoid this case + */ + if ((sensor->axis.x == axis.x) && (sensor->axis.y == axis.y) && (sensor->axis.z == axis.z)) { + if (flag) { + flag = 0; + axis.x += 1; + axis.y += 1; + axis.z += 1; + } else { + flag = 1; + axis.x -= 1; + axis.y -= 1; + axis.z -= 1; + } + } gsensor_report_value(client, &axis); @@ -216,17 +197,12 @@ static int sensor_report_value(struct i2c_client *client) sensor->axis = axis; mutex_unlock(&sensor->data_mutex); - if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register - { - + if (sensor->pdata->irq_enable && sensor->ops->int_status_reg >= 0) value = sensor_read_reg(client, sensor->ops->int_status_reg); - DBG("%s:sensor int status :0x%x\n",__func__,value); - } - + return ret; } - struct sensor_operate gsensor_mma7660_ops = { .name = "mma7660", .type = SENSOR_TYPE_ACCEL, @@ -238,7 +214,7 @@ struct sensor_operate gsensor_mma7660_ops = { .precision = MMA7660_PRECISION, .ctrl_reg = MMA7660_REG_MODE, .int_status_reg = SENSOR_UNKNOW_DATA, - .range = {-24576, 24576}, + .range = {-24576, 24576}, .trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT, .active = sensor_active, .init = sensor_init, @@ -253,26 +229,21 @@ static struct sensor_operate *gsensor_get_ops(void) return &gsensor_mma7660_ops; } - static int __init gsensor_mma7660_init(void) { struct sensor_operate *ops = gsensor_get_ops(); - int result = 0; int type = ops->type; - result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops); - return result; + + return sensor_register_slave(type, NULL, NULL, gsensor_get_ops); } static void __exit gsensor_mma7660_exit(void) { struct sensor_operate *ops = gsensor_get_ops(); int type = ops->type; + sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops); } - module_init(gsensor_mma7660_init); module_exit(gsensor_mma7660_exit); - - - From d55db1d3bafee99f9a9ec8752a40ac215e129cf7 Mon Sep 17 00:00:00 2001 From: Zorro Liu Date: Sun, 11 Feb 2018 11:18:07 +0800 Subject: [PATCH 374/427] arm64: dts: rockchip: modify gsensor layout value of px30-evb-ddr3-v10 board Change-Id: I7ecdf9db002e3754189e345e27efbb249146539b Signed-off-by: Zorro Liu --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index f928d78a4c5b..67c7e8a6dae5 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -529,7 +529,7 @@ irq-gpio = <&gpio0 RK_PB7 IRQ_TYPE_LEVEL_LOW>; irq_enable = <0>; poll_delay_ms = <30>; - layout = <6>; + layout = <2>; reprobe_en = <1>; }; }; From 1dd2b51cdf60d5850640023ab4fc70933b8576e0 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Feb 2018 20:56:50 +0800 Subject: [PATCH 375/427] net/wireless/rockchip_wlan: fix compile warning Change-Id: Ife9d64914e2986a07a649064ee0141d83fea69e2 Signed-off-by: Tao Huang --- .../rockchip_wlan/rtl8188fu/core/rtw_mlme_ext.c | 4 ++-- .../rockchip_wlan/rtl8188fu/core/rtw_security.c | 8 ++++---- .../rtl8188fu/hal/rtl8188f/rtl8188f_hal_init.c | 2 +- .../wireless/rockchip_wlan/rtl8189es/core/rtw_iol.c | 3 ++- .../rockchip_wlan/rtl8189es/core/rtw_mlme_ext.c | 4 ++-- .../rockchip_wlan/rtl8189es/core/rtw_security.c | 8 ++++---- .../rtl8189es/os_dep/linux/ioctl_cfg80211.c | 10 +++++----- .../rockchip_wlan/rtl8189fs/core/rtw_mlme_ext.c | 4 ++-- .../rockchip_wlan/rtl8189fs/core/rtw_security.c | 8 ++++---- .../rtl8189fs/hal/rtl8188f/rtl8188f_hal_init.c | 2 +- .../rockchip_wlan/rtl8723bs/core/rtw_mlme_ext.c | 4 ++-- .../rockchip_wlan/rtl8723bs/core/rtw_security.c | 8 ++++---- .../wireless/rockchip_wlan/rtl8723bs/hal/hal_mp.c | 5 ++--- .../rtl8723bs/hal/rtl8723b/rtl8723b_hal_init.c | 2 +- .../rockchip_wlan/rtl8723bu/core/rtw_mlme_ext.c | 4 ++-- .../rockchip_wlan/rtl8723bu/core/rtw_security.c | 8 ++++---- .../wireless/rockchip_wlan/rtl8723bu/hal/hal_mp.c | 5 ++--- .../rtl8723bu/hal/rtl8723b/rtl8723b_hal_init.c | 2 +- .../wireless/rockchip_wlan/rtl8723cs/hal/hal_mp.c | 5 ++--- .../wireless/rockchip_wlan/rtl8723ds/core/rtw_mi.c | 2 +- .../rtl8723ds/hal/btc/halbtc8723d1ant.c | 2 +- .../rtl8723ds/hal/rtl8723d/rtl8723d_hal_init.c | 12 ++++++------ .../rtl8822be/hal/btc/halbtc8822b2ant.c | 4 ++-- 23 files changed, 57 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_mlme_ext.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_mlme_ext.c index bbf78ecace6e..623571f6eb56 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_mlme_ext.c @@ -12248,10 +12248,10 @@ void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1); else issue_del_ba(padapter, psta->hwaddr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; + psta->recvreorder_ctrl[i].enable = _FALSE; if (ret != _FAIL) psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); + rtw_reset_continual_no_rx_packet(psta, i); } } } diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_security.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_security.c index 0729501759e7..8dac771ca080 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_security.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/core/rtw_security.c @@ -1598,8 +1598,8 @@ _func_enter_; for (j = 0; j < 8; j++) pframe[payload_index+j] = mic[j]; //message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, @@ -1984,8 +1984,8 @@ _func_enter_; for (j = 0; j < 8; j++) message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, diff --git a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/rtl8188f_hal_init.c b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/rtl8188f_hal_init.c index 87bae2f60760..77f7b40ea150 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/rtl8188f_hal_init.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/rtl8188f/rtl8188f_hal_init.c @@ -2643,7 +2643,7 @@ hal_EfusePgPacketWrite1ByteHeader( if (IS_HARDWARE_TYPE_8723BE(pAdapter)) efuse_OneByteWrite(pAdapter, 0x1FF, 00, FALSE); /* increase current */ - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); PHY_SetMacReg(pAdapter, EFUSE_TEST, BIT26, 0); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_iol.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_iol.c index 3524e1c5a5ed..b9c7f48abb23 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_iol.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_iol.c @@ -258,7 +258,8 @@ void rtw_IOL_cmd_buf_dump(ADAPTER *Adapter,int buf_len,u8 *pbuf) for(i=0;i< buf_len;i++){ printk("%02x-",*(pbuf+i)); - if(j%32 ==0) printk("\n");j++; + if(j%32 ==0) printk("\n"); + j++; } printk("\n"); printk("============= ioreg_cmd len = %d =============== \n",buf_len); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_mlme_ext.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_mlme_ext.c index c0da30555367..9c08cd870da7 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_mlme_ext.c @@ -12136,10 +12136,10 @@ void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1); else issue_del_ba(padapter, psta->hwaddr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; + psta->recvreorder_ctrl[i].enable = _FALSE; if (ret != _FAIL) psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); + rtw_reset_continual_no_rx_packet(psta, i); } } } diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_security.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_security.c index 0729501759e7..8dac771ca080 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_security.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/core/rtw_security.c @@ -1598,8 +1598,8 @@ _func_enter_; for (j = 0; j < 8; j++) pframe[payload_index+j] = mic[j]; //message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, @@ -1984,8 +1984,8 @@ _func_enter_; for (j = 0; j < 8; j++) message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/ioctl_cfg80211.c index e5abfd194910..e47fbc7f7506 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/ioctl_cfg80211.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189es/os_dep/linux/ioctl_cfg80211.c @@ -5368,11 +5368,11 @@ static int _cfg80211_rtw_mgmt_tx(_adapter *padapter, u8 tx_ch, const u8 *buf, si }else #endif //CONFIG_CONCURRENT_MODE //if (tx_ch != pmlmeext->cur_channel) { - if(tx_ch != rtw_get_oper_ch(padapter)) { - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED )) - pmlmeext->cur_channel = tx_ch; - set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - } + if(tx_ch != rtw_get_oper_ch(padapter)) { + if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED )) + pmlmeext->cur_channel = tx_ch; + set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + } //starting alloc mgmt frame to dump it if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_mlme_ext.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_mlme_ext.c index afbc8c282792..3c13f6d8b20f 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_mlme_ext.c @@ -12153,10 +12153,10 @@ void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1); else issue_del_ba(padapter, psta->hwaddr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; + psta->recvreorder_ctrl[i].enable = _FALSE; if (ret != _FAIL) psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); + rtw_reset_continual_no_rx_packet(psta, i); } } } diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_security.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_security.c index 0729501759e7..8dac771ca080 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_security.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/core/rtw_security.c @@ -1598,8 +1598,8 @@ _func_enter_; for (j = 0; j < 8; j++) pframe[payload_index+j] = mic[j]; //message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, @@ -1984,8 +1984,8 @@ _func_enter_; for (j = 0; j < 8; j++) message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, diff --git a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/rtl8188f_hal_init.c b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/rtl8188f_hal_init.c index f5c0c8dfa5e6..d8b7b631ebe6 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/rtl8188f_hal_init.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8189fs/hal/rtl8188f/rtl8188f_hal_init.c @@ -2639,7 +2639,7 @@ hal_EfusePgPacketWrite1ByteHeader( if (IS_HARDWARE_TYPE_8723BE(pAdapter)) efuse_OneByteWrite(pAdapter, 0x1FF, 00, FALSE); /* increase current */ - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); PHY_SetMacReg(pAdapter, EFUSE_TEST, BIT26, 0); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_mlme_ext.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_mlme_ext.c index 455e3b47b340..b255b42182a8 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_mlme_ext.c @@ -12217,10 +12217,10 @@ void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1); else issue_del_ba(padapter, psta->hwaddr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; + psta->recvreorder_ctrl[i].enable = _FALSE; if (ret != _FAIL) psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); + rtw_reset_continual_no_rx_packet(psta, i); } } } diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_security.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_security.c index 0729501759e7..8dac771ca080 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_security.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/core/rtw_security.c @@ -1598,8 +1598,8 @@ _func_enter_; for (j = 0; j < 8; j++) pframe[payload_index+j] = mic[j]; //message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, @@ -1984,8 +1984,8 @@ _func_enter_; for (j = 0; j < 8; j++) message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/hal_mp.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/hal_mp.c index e30c6a1b2947..69e9249b869c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/hal_mp.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/hal_mp.c @@ -970,6 +970,7 @@ void mpt_SetRFPath_8812A(PADAPTER pAdapter) void mpt_SetRFPath_8723B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 p = 0, i = 0; u32 ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.MptCtx); PDM_ODM_T pDM_Odm = &pHalData->odmpriv; @@ -984,7 +985,6 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u8 p = 0, i = 0; case ANTENNA_A: /*/ Actually path S1 (Wi-Fi)*/ { pMptCtx->MptRfPath = ODM_RF_PATH_A; @@ -1068,6 +1068,7 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) void mpt_SetRFPath_8703B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u1Byte p = 0, i = 0; u4Byte ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.MptCtx); PDM_ODM_T pDM_Odm = &pHalData->odmpriv; @@ -1082,8 +1083,6 @@ void mpt_SetRFPath_8703B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u1Byte p = 0, i = 0; - case ANTENNA_A: /* Actually path S1 (Wi-Fi) */ { pMptCtx->MptRfPath = ODM_RF_PATH_A; diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/rtl8723b_hal_init.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/rtl8723b_hal_init.c index 2a3f4b8cd48e..fd5f5f62a147 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/rtl8723b_hal_init.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/rtl8723b_hal_init.c @@ -2660,7 +2660,7 @@ hal_EfusePgPacketWrite1ByteHeader( if (IS_HARDWARE_TYPE_8723BE(pAdapter)) efuse_OneByteWrite(pAdapter, 0x1FF, 00, FALSE); /* increase current */ - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); PHY_SetMacReg(pAdapter, EFUSE_TEST, BIT26, 0); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_mlme_ext.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_mlme_ext.c index 455e3b47b340..b255b42182a8 100755 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_mlme_ext.c @@ -12217,10 +12217,10 @@ void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1); else issue_del_ba(padapter, psta->hwaddr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; + psta->recvreorder_ctrl[i].enable = _FALSE; if (ret != _FAIL) psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); + rtw_reset_continual_no_rx_packet(psta, i); } } } diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_security.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_security.c index 0729501759e7..8dac771ca080 100755 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_security.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/core/rtw_security.c @@ -1598,8 +1598,8 @@ _func_enter_; for (j = 0; j < 8; j++) pframe[payload_index+j] = mic[j]; //message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, @@ -1984,8 +1984,8 @@ _func_enter_; for (j = 0; j < 8; j++) message[payload_index+j] = mic[j]; - payload_index = hdrlen + 8; - for (i=0; i< num_blocks; i++) + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) { construct_ctr_preload( ctr_preload, diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/hal_mp.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/hal_mp.c index e30c6a1b2947..69e9249b869c 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/hal_mp.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/hal_mp.c @@ -970,6 +970,7 @@ void mpt_SetRFPath_8812A(PADAPTER pAdapter) void mpt_SetRFPath_8723B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 p = 0, i = 0; u32 ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.MptCtx); PDM_ODM_T pDM_Odm = &pHalData->odmpriv; @@ -984,7 +985,6 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u8 p = 0, i = 0; case ANTENNA_A: /*/ Actually path S1 (Wi-Fi)*/ { pMptCtx->MptRfPath = ODM_RF_PATH_A; @@ -1068,6 +1068,7 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) void mpt_SetRFPath_8703B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u1Byte p = 0, i = 0; u4Byte ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.MptCtx); PDM_ODM_T pDM_Odm = &pHalData->odmpriv; @@ -1082,8 +1083,6 @@ void mpt_SetRFPath_8703B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u1Byte p = 0, i = 0; - case ANTENNA_A: /* Actually path S1 (Wi-Fi) */ { pMptCtx->MptRfPath = ODM_RF_PATH_A; diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/rtl8723b_hal_init.c b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/rtl8723b_hal_init.c index 2a3f4b8cd48e..fd5f5f62a147 100755 --- a/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/rtl8723b_hal_init.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723bu/hal/rtl8723b/rtl8723b_hal_init.c @@ -2660,7 +2660,7 @@ hal_EfusePgPacketWrite1ByteHeader( if (IS_HARDWARE_TYPE_8723BE(pAdapter)) efuse_OneByteWrite(pAdapter, 0x1FF, 00, FALSE); /* increase current */ - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); PHY_SetMacReg(pAdapter, EFUSE_TEST, BIT26, 0); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_mp.c b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_mp.c index 8ddb33e746ab..fd235670d759 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_mp.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/hal_mp.c @@ -1059,6 +1059,7 @@ void mpt_SetRFPath_8812A(PADAPTER pAdapter) void mpt_SetRFPath_8723B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 p = 0, i = 0; u32 ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; @@ -1073,7 +1074,6 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u8 p = 0, i = 0; case ANTENNA_A: { /*/ Actually path S1 (Wi-Fi)*/ pMptCtx->mpt_rf_path = ODM_RF_PATH_A; phy_set_bb_reg(pAdapter, rS0S1_PathSwitch, BIT9 | BIT8 | BIT7, 0x0); @@ -1149,6 +1149,7 @@ void mpt_SetRFPath_8723B(PADAPTER pAdapter) void mpt_SetRFPath_8703B(PADAPTER pAdapter) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u1Byte p = 0, i = 0; u4Byte ulAntennaTx, ulAntennaRx; PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; @@ -1163,8 +1164,6 @@ void mpt_SetRFPath_8703B(PADAPTER pAdapter) } switch (pAdapter->mppriv.antenna_tx) { - u1Byte p = 0, i = 0; - case ANTENNA_A: { /* Actually path S1 (Wi-Fi) */ pMptCtx->mpt_rf_path = ODM_RF_PATH_A; phy_set_bb_reg(pAdapter, rS0S1_PathSwitch, BIT9 | BIT8 | BIT7, 0x0); diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/core/rtw_mi.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/core/rtw_mi.c index 5bc17c3d13a6..641908aaef5e 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/core/rtw_mi.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/core/rtw_mi.c @@ -662,7 +662,7 @@ static void _rtw_mi_stop_drv_threads(_adapter *adapter, bool exclude_self) if ((iface) && (iface->bup == _TRUE)) if ((exclude_self) && (iface == adapter)) continue; - rtw_stop_drv_threads(iface); + rtw_stop_drv_threads(iface); } } void rtw_mi_stop_drv_threads(_adapter *adapter) diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8723d1ant.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8723d1ant.c index f607d772b4e0..1fae248f02c4 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8723d1ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/btc/halbtc8723d1ant.c @@ -6338,7 +6338,7 @@ void ex_halbtc8723d1ant_periodical(IN struct btc_coexist *btcoexist) if ((coex_sta->specific_pkt_period_cnt == 0) && (coex_sta->wifi_is_high_pri_task)) coex_sta->wifi_is_high_pri_task = FALSE; - special_pkt_finish = TRUE; + special_pkt_finish = TRUE; } if (!coex_sta->bt_disabled) { diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/rtl8723d/rtl8723d_hal_init.c b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/rtl8723d/rtl8723d_hal_init.c index 65f75f322d36..5161a90e4833 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/rtl8723d/rtl8723d_hal_init.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8723ds/hal/rtl8723d/rtl8723d_hal_init.c @@ -5032,12 +5032,12 @@ u8 SetHwReg8723D(PADAPTER padapter, u8 variable, u8 *val) /* ulContent |= CAM_VALID; */ } else ulContent = 0; - /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT * ucIndex + i; - ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; - /* write content 0 is equall to mark invalid */ - rtw_write32(padapter, WCAMI, ulContent); /* delay_ms(40); */ - rtw_write32(padapter, RWCAM, ulCommand); /* delay_ms(40); */ + /* polling bit, and No Write enable, and address */ + ulCommand = CAM_CONTENT_COUNT * ucIndex + i; + ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; + /* write content 0 is equall to mark invalid */ + rtw_write32(padapter, WCAMI, ulContent); /* delay_ms(40); */ + rtw_write32(padapter, RWCAM, ulCommand); /* delay_ms(40); */ } } break; diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c index c35140199ed1..9018797c2190 100644 --- a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c +++ b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/btc/halbtc8822b2ant.c @@ -1735,8 +1735,8 @@ void halbtc8822b2ant_set_ext_ant_switch(IN struct btc_coexist *btcoexist, /* Ext switch buffer mux */ btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x1991, 0x3, 0x0); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcbe, 0x8, 0x0); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x1991, 0x3, 0x0); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcbe, 0x8, 0x0); switch (ctrl_type) { From 7adc50bef2c77d9caad22ae52beed521e885df18 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 18:09:19 +0800 Subject: [PATCH 376/427] arm64: rockchip_defconfig: remove CONFIG_ANDROID_LOW_MEMORY_KILLER e8f5f841b764 ("remove CONFIG_ANDROID_LOW_MEMORY_KILLER requirement") Kernel configuration options should include either CONFIG_ANDROID_LOW_MEMORY_KILLER for in-kernel lowmemorykiller driver to be used or a combination of CONFIG_MEMCG and CONFIG_MEMCG_SWAP if userspace lmkd is preferred. It is not currently possible to express this logical requirement in the config fragment so the CONFIG_ANDROID_LOW_MEMORY_KILLER requirement is simply removed for now. Change-Id: I69b9682029a50f4579f3ba11e6a9a497c5a51c28 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 406dc58c712f..af02def3d32d 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -13,6 +13,8 @@ CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_SCHEDTUNE=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_NAMESPACES=y @@ -693,7 +695,6 @@ CONFIG_STAGING=y CONFIG_INV_MPU_IIO=y CONFIG_ASHMEM=y CONFIG_ANDROID_TIMED_GPIO=y -CONFIG_ANDROID_LOW_MEMORY_KILLER=y CONFIG_SYNC=y CONFIG_SW_SYNC=y CONFIG_SW_SYNC_USER=y From aa349fbf38defc84de8ab06900f0abbd927865ea Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 18:15:16 +0800 Subject: [PATCH 377/427] ARM: rockchip_defconfig: remove CONFIG_ANDROID_LOW_MEMORY_KILLER e8f5f841b764 ("remove CONFIG_ANDROID_LOW_MEMORY_KILLER requirement") Kernel configuration options should include either CONFIG_ANDROID_LOW_MEMORY_KILLER for in-kernel lowmemorykiller driver to be used or a combination of CONFIG_MEMCG and CONFIG_MEMCG_SWAP if userspace lmkd is preferred. It is not currently possible to express this logical requirement in the config fragment so the CONFIG_ANDROID_LOW_MEMORY_KILLER requirement is simply removed for now. Change-Id: I9cea0552a285ac635fc44f4b45762988e423d7db Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 3c32488f50b0..28eb935ba761 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -13,6 +13,8 @@ CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_NAMESPACES=y @@ -596,7 +598,6 @@ CONFIG_STAGING=y CONFIG_INV_MPU_IIO=y CONFIG_ASHMEM=y CONFIG_ANDROID_TIMED_GPIO=y -CONFIG_ANDROID_LOW_MEMORY_KILLER=y CONFIG_SYNC=y CONFIG_SW_SYNC=y CONFIG_SW_SYNC_USER=y From ea18c3d20d3d2611dee7cb11e13833bc051974c2 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 19:10:48 +0800 Subject: [PATCH 378/427] Revert "Revert "arm64: rockchip_defconfig: enable CONFIG_IKCONFIG"" This reverts commit 95bc3a89353211d19407de338fb3a3f02389394b. 8588d88f1a37 ("ANDROID: android-base.cfg: add CONFIG_IKCONFIG option") This adds CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC options, which are a requirement for the O release. Change-Id: Id02fde91ed902f266ff5c81ec04e2427a2877847 Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index af02def3d32d..e2b0eadf19bd 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -7,6 +7,8 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=19 CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y From badf2c491820399c58bd233c6b66a5ea7ad50497 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 19:17:25 +0800 Subject: [PATCH 379/427] arm64: rockchip_defconfig: bump CONFIG_ANDROID_VERSION to 0x08000000 Change-Id: Iafd493187f579ec4f5d202a496548f70be7a868a Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index e2b0eadf19bd..6e839475fc9a 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -718,6 +718,7 @@ CONFIG_RK3368_SCPI_PROTOCOL=y CONFIG_ROCKCHIP_IOMMU=y CONFIG_RK_IOMMU=y CONFIG_RK_IOVMM=y +CONFIG_ANDROID_VERSION=0x08000000 CONFIG_ROCKCHIP_PM_DOMAINS=y CONFIG_ROCKCHIP_PVTM=y CONFIG_ROCKCHIP_SUSPEND_MODE=y From 4f332329790686d30d3bab19260ce5909bf80f52 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 19:21:13 +0800 Subject: [PATCH 380/427] Revert "Revert "ARM: rockchip_defconfig: enable CONFIG_IKCONFIG"" This reverts commit cbd1d90f723ab029e3326c0e085ea050691294ec. 8588d88f1a37 ("ANDROID: android-base.cfg: add CONFIG_IKCONFIG option") This adds CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC options, which are a requirement for the O release. Change-Id: I438ade881219034618afb4cd5174bf750a79d319 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 28eb935ba761..0ca0c6bb75c6 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -8,6 +8,8 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=19 CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y From 75df0e02ac216cf759c3e0f5d14942fa7c409216 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 9 Feb 2018 19:23:20 +0800 Subject: [PATCH 381/427] ARM: rockchip_defconfig: bump CONFIG_ANDROID_VERSION to 0x08000000 Change-Id: Ia66100f8d828aa0ae3a7c3c66906c51d07548b92 Signed-off-by: Tao Huang --- arch/arm/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 0ca0c6bb75c6..5be4e054c38f 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -613,6 +613,7 @@ CONFIG_FIQ_DEBUGGER_TRUST_ZONE=y CONFIG_RK_CONSOLE_THREAD=y CONFIG_COMMON_CLK_RK808=y CONFIG_ROCKCHIP_IOMMU=y +CONFIG_ANDROID_VERSION=0x08000000 CONFIG_ROCKCHIP_PM_DOMAINS=y CONFIG_ROCKCHIP_PVTM=y CONFIG_ROCKCHIP_SUSPEND_MODE=y From f1da8a190e8f80a71b169ed5e5d7311fd53c9046 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sun, 11 Feb 2018 20:20:51 +0800 Subject: [PATCH 382/427] sound/soc/codecs/rk817_codec: fix compile warning sound/soc/codecs/rk817_codec.c:405:14: warning: duplicate const declaration specifier [-Wduplicate-decl-specifier] Change-Id: I572b1778f29a48b0756ac60488ce2311cc372f8b Signed-off-by: Tao Huang --- sound/soc/codecs/rk817_codec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index c1f862966ab8..2ec16c291c5a 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -402,16 +402,16 @@ static const char * const rk817_call_path_mode[] = { static const char * const rk817_modem_input_mode[] = {"OFF", "ON"}; -static const SOC_ENUM_SINGLE_DECL(rk817_playback_path_type, +static SOC_ENUM_SINGLE_DECL(rk817_playback_path_type, 0, 0, rk817_playback_path_mode); -static const SOC_ENUM_SINGLE_DECL(rk817_capture_path_type, +static SOC_ENUM_SINGLE_DECL(rk817_capture_path_type, 0, 0, rk817_capture_path_mode); -static const SOC_ENUM_SINGLE_DECL(rk817_call_path_type, +static SOC_ENUM_SINGLE_DECL(rk817_call_path_type, 0, 0, rk817_call_path_mode); -static const SOC_ENUM_SINGLE_DECL(rk817_modem_input_type, +static SOC_ENUM_SINGLE_DECL(rk817_modem_input_type, 0, 0, rk817_modem_input_mode); static int rk817_playback_path_get(struct snd_kcontrol *kcontrol, From d1c247b6002120885cbd0d234931b93a6d04851c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sun, 11 Feb 2018 20:29:43 +0800 Subject: [PATCH 383/427] sound/soc/codecs/rt5651: fix compile warning sound/soc/codecs/rt5651.c:351:14: warning: duplicate const declaration specifier [-Wduplicate-decl-specifier] Change-Id: I25ac1012398c7742c7b66d6a57f4956b96ba0aa4 Signed-off-by: Tao Huang --- sound/soc/codecs/rt5651.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 7de785087958..d50ee82bc904 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -348,8 +348,7 @@ static SOC_ENUM_SINGLE_DECL(rt5651_if2_adc_enum, RT5651_DIG_INF_DATA, static const char * const rt5651_asrc_mode[] = {"Disable", "Enable"}; -static const SOC_ENUM_SINGLE_DECL(rt5651_asrc_enum, 0, 0, - rt5651_asrc_mode); +static SOC_ENUM_SINGLE_DECL(rt5651_asrc_enum, 0, 0, rt5651_asrc_mode); static const struct snd_kcontrol_new rt5651_snd_controls[] = { /* Headphone Output Volume */ From 2e983151865a6db1d619a909d85858e8807a6c22 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sun, 11 Feb 2018 20:56:13 +0800 Subject: [PATCH 384/427] arm64: rockchip_defconfig: enable CONFIG_CRYPTO_CRC32_ARM64 Change-Id: I70e8ba303d5c3b0210912a31e3175425c1f1a63f Signed-off-by: Tao Huang --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 6e839475fc9a..0b8a3e5598ba 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -814,3 +814,4 @@ CONFIG_CRYPTO_SHA2_ARM64_CE=y CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_CRC32_ARM64=y From 8b8065853a5a9369589068faa2c9ceed86b23a16 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 11 Feb 2018 20:18:53 +0800 Subject: [PATCH 385/427] arm64: dts: rockchip: px30: fixup pdm pinctrl Change-Id: I5a3978a486c63dae718b46be142eed263788e5f3 Signed-off-by: Sugar Zhang --- arch/arm64/boot/dts/rockchip/px30.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index a0d425ff5499..94f2438f1048 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1812,7 +1812,7 @@ pdm_sdi0m0: pdm-sdi0m0 { rockchip,pins = - <3 RK_PD3 RK_FUNC_4 &pcfg_pull_none>; + <3 RK_PD3 RK_FUNC_2 &pcfg_pull_none>; }; pdm_sdi0m1: pdm-sdi0m1 { @@ -1832,7 +1832,7 @@ pdm_sdi3: pdm-sdi3 { rockchip,pins = - <3 RK_PD2 RK_FUNC_4 &pcfg_pull_none>; + <3 RK_PD2 RK_FUNC_2 &pcfg_pull_none>; }; pdm_clk0m0_sleep: pdm-clk0m0-sleep { From 84c9e0030afae741218c3d3873f9c35e91a751df Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 11 Feb 2018 20:24:05 +0800 Subject: [PATCH 386/427] arm64: configs: rockchip_defconfig: enable pdm interface Change-Id: I3d6b75d3e08bf542e8b0da014fd4a6b263fac124 Signed-off-by: Sugar Zhang --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 0b8a3e5598ba..0887a4ecfa73 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -545,6 +545,7 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y CONFIG_SND_SOC_ROCKCHIP=y +CONFIG_SND_SOC_ROCKCHIP_PDM=y CONFIG_SND_SOC_ROCKCHIP_SPDIF=y CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG=y CONFIG_SND_SOC_ROCKCHIP_HDMI_DP=y From 67217a757ad1bff5e19c059f9a590bf2009b5e57 Mon Sep 17 00:00:00 2001 From: William Wu Date: Sun, 11 Feb 2018 17:19:49 +0800 Subject: [PATCH 387/427] arm64: dts: rockchip: use spdifm2_tx for rk3328-evb-android Change-Id: I6d13fb703deffccb87bc311733afb88c1c90bbdd Signed-off-by: William Wu --- arch/arm64/boot/dts/rockchip/rk3328-evb-android.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb-android.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb-android.dts index fc990cb83880..181d840dacef 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-evb-android.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-evb-android.dts @@ -541,7 +541,7 @@ &spdif { #sound-dai-cells = <0>; pinctrl-names = "default"; - pinctrl-0 = <&spdifm0_tx>; + pinctrl-0 = <&spdifm2_tx>; status = "okay"; }; From ad46e68846cb76abcfe013f5d3ac9f13801e592e Mon Sep 17 00:00:00 2001 From: Wen Nuan Date: Sun, 11 Feb 2018 16:53:03 +0800 Subject: [PATCH 388/427] phy: rockchip: mipi-dphy-tx1rx1: add mipi-dphy TX1RX1 channel for RK3288 This patch adds the function of mipi-dphy TX1RX1 for RK3288, the mipi-dphy TX1RX1 is matched when "txrx_base_addr" is valid. Change-Id: I01640925157a7082e942188b29f6bbf1318cf3d5 Signed-off-by: Wen Nuan --- .../bindings/media/rockchip-mipi-dphy.txt | 4 +- .../platform/rockchip/isp1/mipi_dphy_sy.c | 231 +++++++++++++----- 2 files changed, 174 insertions(+), 61 deletions(-) diff --git a/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt index 0571d7f35867..55c01726782e 100644 --- a/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt +++ b/Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt @@ -11,10 +11,12 @@ Required properties: MIPI RX0 D-PHY use registers in "general register files", it should be a child of the GRF. -MIPI TXRX D-PHY have its own registers, it must have a reg property. +MIPI TX1RX1 D-PHY have its own registers, it must have a reg property. Optional properties: - reg: offset and length of the register set for the device. +- rockchip,grf: MIPI TX1RX1 D-PHY not only has its own register but also + the GRF, so it is only necessary for MIPI TX1RX1 D-PHY. port node ------------------- diff --git a/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c index bdbd0c68944d..d39f6a5e756d 100644 --- a/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c +++ b/drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c @@ -68,7 +68,21 @@ #define LANE1_HS_RX_CONTROL 0x54 #define LANE2_HS_RX_CONTROL 0x84 #define LANE3_HS_RX_CONTROL 0x94 -#define HS_RX_DATA_LANES_THS_SETTLE__CONTROL 0x75 +#define HS_RX_DATA_LANES_THS_SETTLE_CONTROL 0x75 + +/* + * CSI HOST + */ +#define CSIHOST_PHY_TEST_CTRL0 0x30 +#define CSIHOST_PHY_TEST_CTRL1 0x34 +#define CSIHOST_PHY_SHUTDOWNZ 0x08 +#define CSIHOST_DPHY_RSTZ 0x0c + +#define PHY_TESTEN_ADDR (0x1 << 16) +#define PHY_TESTEN_DATA (0x0 << 16) +#define PHY_TESTCLK (0x1 << 1) +#define PHY_TESTCLR (0x1 << 0) +#define THS_SETTLE_COUNTER_THRESHOLD 0x04 #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) @@ -185,6 +199,8 @@ struct hsfreq_range { u8 cfg_bit; }; +struct mipidphy_priv; + struct dphy_drv_data { const char * const *clks; int num_clks; @@ -221,6 +237,8 @@ struct mipidphy_priv { struct mipidphy_sensor sensors[MAX_DPHY_SENSORS]; int num_sensors; bool is_streaming; + void __iomem *txrx_base_addr; + int (*stream_on)(struct mipidphy_priv *priv, struct v4l2_subdev *sd); }; static inline struct mipidphy_priv *to_dphy_priv(struct v4l2_subdev *subdev) @@ -228,7 +246,8 @@ static inline struct mipidphy_priv *to_dphy_priv(struct v4l2_subdev *subdev) return container_of(subdev, struct mipidphy_priv, sd); } -static inline void write_reg(struct mipidphy_priv *priv, int index, u8 value) +static inline void write_grf_reg(struct mipidphy_priv *priv, + int index, u8 value) { const struct dphy_reg *reg = &priv->grf_regs[index]; unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift); @@ -237,21 +256,38 @@ static inline void write_reg(struct mipidphy_priv *priv, int index, u8 value) regmap_write(priv->regmap_grf, reg->offset, val); } -static void mipidphy_wr_reg(struct mipidphy_priv *priv, - u8 test_code, u8 test_data) +static void mipidphy0_wr_reg(struct mipidphy_priv *priv, + u8 test_code, u8 test_data) { /* * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content * is latched internally as the current test code. Test data is * programmed internally by rising edge on TESTCLK. */ - write_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); - write_reg(priv, GRF_DPHY_RX0_TESTDIN, test_code); - write_reg(priv, GRF_DPHY_RX0_TESTEN, 1); - write_reg(priv, GRF_DPHY_RX0_TESTCLK, 0); - write_reg(priv, GRF_DPHY_RX0_TESTEN, 0); - write_reg(priv, GRF_DPHY_RX0_TESTDIN, test_data); - write_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); + write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_code); + write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 1); + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 0); + write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 0); + write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_data); + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); +} + +static void mipidphy1_wr_reg(struct mipidphy_priv *priv, unsigned char addr, + unsigned char data) +{ + /* + * TESTEN =1,TESTDIN=addr + * TESTCLK=0 + * TESTEN =0,TESTDIN=data + * TESTCLK=1 + */ + writel((PHY_TESTEN_ADDR | addr), + priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL1); + writel(0x00, priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL0); + writel((PHY_TESTEN_DATA | data), + priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL1); + writel(PHY_TESTCLK, priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL0); } static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd) @@ -316,12 +352,7 @@ static int mipidphy_get_sensor_data_rate(struct v4l2_subdev *sd) static int mipidphy_s_stream_start(struct v4l2_subdev *sd) { struct mipidphy_priv *priv = to_dphy_priv(sd); - const struct dphy_drv_data *drv_data = priv->drv_data; - const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; - int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; - struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); - struct mipidphy_sensor *sensor = sd_to_sensor(priv, sensor_sd); - int i, ret, hsfreq = 0; + int ret = 0; if (priv->is_streaming) return 0; @@ -330,44 +361,7 @@ static int mipidphy_s_stream_start(struct v4l2_subdev *sd) if (ret < 0) return ret; - for (i = 0; i < num_hsfreq_ranges; i++) { - if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) { - hsfreq = hsfreq_ranges[i].cfg_bit; - break; - } - } - - write_reg(priv, GRF_DPHY_RX0_FORCERXMODE, 0); - write_reg(priv, GRF_DPHY_RX0_FORCETXSTOPMODE, 0); - /* Disable lan turn around, which is ignored in receive mode */ - write_reg(priv, GRF_DPHY_RX0_TURNREQUEST, 0); - write_reg(priv, GRF_DPHY_RX0_TURNDISABLE, 0xf); - - write_reg(priv, GRF_DPHY_RX0_ENABLE, GENMASK(sensor->lanes - 1, 0)); - - /* dphy start */ - write_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); - write_reg(priv, GRF_DPHY_RX0_TESTCLR, 1); - usleep_range(100, 150); - write_reg(priv, GRF_DPHY_RX0_TESTCLR, 0); - usleep_range(100, 150); - - /* set clock lane */ - /* HS hsfreq_range & lane 0 settle bypass */ - mipidphy_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0); - /* HS RX Control of lane0 */ - mipidphy_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq << 1); - /* HS RX Control of lane1 */ - mipidphy_wr_reg(priv, LANE1_HS_RX_CONTROL, 0); - /* HS RX Control of lane2 */ - mipidphy_wr_reg(priv, LANE2_HS_RX_CONTROL, 0); - /* HS RX Control of lane3 */ - mipidphy_wr_reg(priv, LANE3_HS_RX_CONTROL, 0); - /* HS RX Data Lanes Settle State Time Control */ - mipidphy_wr_reg(priv, HS_RX_DATA_LANES_THS_SETTLE__CONTROL, 0x04); - - /* Normal operation */ - mipidphy_wr_reg(priv, 0x0, 0); + priv->stream_on(priv, sd); priv->is_streaming = true; @@ -521,6 +515,112 @@ static const char * const rk3288_mipidphy_clks[] = { "pclk", }; +static int mipidphy_rx_stream_on(struct mipidphy_priv *priv, + struct v4l2_subdev *sd) +{ + struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); + struct mipidphy_sensor *sensor = sd_to_sensor(priv, sensor_sd); + const struct dphy_drv_data *drv_data = priv->drv_data; + const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; + int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; + int i, hsfreq = 0; + + for (i = 0; i < num_hsfreq_ranges; i++) { + if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) { + hsfreq = hsfreq_ranges[i].cfg_bit; + break; + } + } + write_grf_reg(priv, GRF_CON_ISP_DPHY_SEL, 0); + write_grf_reg(priv, GRF_DPHY_RX0_FORCERXMODE, 0); + write_grf_reg(priv, GRF_DPHY_RX0_FORCETXSTOPMODE, 0); + /* Disable lan turn around, which is ignored in receive mode */ + write_grf_reg(priv, GRF_DPHY_RX0_TURNREQUEST, 0); + write_grf_reg(priv, GRF_DPHY_RX0_TURNDISABLE, 0xf); + + write_grf_reg(priv, GRF_DPHY_RX0_ENABLE, GENMASK(sensor->lanes - 1, 0)); + + /* dphy start */ + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1); + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 1); + usleep_range(100, 150); + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 0); + usleep_range(100, 150); + + /* set clock lane */ + /* HS hsfreq_range & lane 0 settle bypass */ + mipidphy0_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0); + /* HS RX Control of lane0 */ + mipidphy0_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq << 1); + /* HS RX Control of lane1 */ + mipidphy0_wr_reg(priv, LANE1_HS_RX_CONTROL, 0); + /* HS RX Control of lane2 */ + mipidphy0_wr_reg(priv, LANE2_HS_RX_CONTROL, 0); + /* HS RX Control of lane3 */ + mipidphy0_wr_reg(priv, LANE3_HS_RX_CONTROL, 0); + /* HS RX Data Lanes Settle State Time Control */ + mipidphy0_wr_reg(priv, HS_RX_DATA_LANES_THS_SETTLE_CONTROL, + THS_SETTLE_COUNTER_THRESHOLD); + + /* Normal operation */ + mipidphy0_wr_reg(priv, 0x0, 0); + + return 0; +} + +static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv, + struct v4l2_subdev *sd) +{ + struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); + struct mipidphy_sensor *sensor = sd_to_sensor(priv, sensor_sd); + const struct dphy_drv_data *drv_data = priv->drv_data; + const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; + int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; + int i, hsfreq = 0; + + for (i = 0; i < num_hsfreq_ranges; i++) { + if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) { + hsfreq = hsfreq_ranges[i].cfg_bit; + break; + } + } + write_grf_reg(priv, GRF_CON_ISP_DPHY_SEL, 1); + write_grf_reg(priv, GRF_DSI_CSI_TESTBUS_SEL, 1); + write_grf_reg(priv, GRF_DPHY_RX1_SRC_SEL, 1); + write_grf_reg(priv, GRF_DPHY_TX1RX1_MASTERSLAVEZ, 0); + write_grf_reg(priv, GRF_DPHY_TX1RX1_BASEDIR, 1); + /* Disable lan turn around, which is ignored in receive mode */ + write_grf_reg(priv, GRF_DPHY_TX1RX1_FORCERXMODE, 0); + write_grf_reg(priv, GRF_DPHY_TX1RX1_FORCETXSTOPMODE, 0); + write_grf_reg(priv, GRF_DPHY_TX1RX1_TURNREQUEST, 0); + write_grf_reg(priv, GRF_DPHY_TX1RX1_TURNDISABLE, 0xf); + write_grf_reg(priv, GRF_DPHY_TX1RX1_ENABLE, + GENMASK(sensor->lanes - 1, 0)); + /* dphy start */ + writel(0, priv->txrx_base_addr + CSIHOST_PHY_SHUTDOWNZ); + writel(0, priv->txrx_base_addr + CSIHOST_DPHY_RSTZ); + writel(PHY_TESTCLK, priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL0); + writel(PHY_TESTCLR, priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL0); + usleep_range(100, 150); + writel(PHY_TESTCLK, priv->txrx_base_addr + CSIHOST_PHY_TEST_CTRL0); + usleep_range(100, 150); + + /* set clock lane */ + mipidphy1_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0); + mipidphy1_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq << 1); + mipidphy1_wr_reg(priv, LANE1_HS_RX_CONTROL, 0); + mipidphy1_wr_reg(priv, LANE2_HS_RX_CONTROL, 0); + mipidphy1_wr_reg(priv, LANE3_HS_RX_CONTROL, 0); + /* HS RX Data Lanes Settle State Time Control */ + mipidphy1_wr_reg(priv, HS_RX_DATA_LANES_THS_SETTLE_CONTROL, + THS_SETTLE_COUNTER_THRESHOLD); + + /* Normal operation */ + mipidphy1_wr_reg(priv, 0x0, 0); + + return 0; +} + static const struct dphy_drv_data rk3288_mipidphy_drv_data = { .clks = rk3288_mipidphy_clks, .num_clks = ARRAY_SIZE(rk3288_mipidphy_clks), @@ -620,8 +720,8 @@ v4l2_async_notifier_operations rockchip_mipidphy_async_ops = { }; static int rockchip_mipidphy_fwnode_parse(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd) + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) { struct sensor_async_subdev *s_asd = container_of(asd, struct sensor_async_subdev, asd); @@ -671,7 +771,7 @@ static int rockchip_mipidphy_media_init(struct mipidphy_priv *priv) MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; ret = media_entity_init(&priv->sd.entity, - MIPI_DPHY_SY_PADS_NUM, priv->pads, 0); + MIPI_DPHY_SY_PADS_NUM, priv->pads, 0); if (ret < 0) return ret; @@ -704,6 +804,7 @@ static int rockchip_mipidphy_probe(struct platform_device *pdev) struct v4l2_subdev *sd; struct mipidphy_priv *priv; struct regmap *grf; + struct resource *res; const struct of_device_id *of_id; const struct dphy_drv_data *drv_data; int i, ret; @@ -719,8 +820,12 @@ static int rockchip_mipidphy_probe(struct platform_device *pdev) grf = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(grf)) { - dev_err(dev, "Can't find GRF syscon\n"); - return -ENODEV; + grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(grf)) { + dev_err(dev, "Can't find GRF syscon\n"); + return -ENODEV; + } } priv->regmap_grf = grf; @@ -736,6 +841,12 @@ static int rockchip_mipidphy_probe(struct platform_device *pdev) priv->grf_regs = drv_data->regs; priv->drv_data = drv_data; + priv->stream_on = mipidphy_txrx_stream_on; + priv->txrx_base_addr = NULL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->txrx_base_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->txrx_base_addr)) + priv->stream_on = mipidphy_rx_stream_on; sd = &priv->sd; v4l2_subdev_init(sd, &mipidphy_subdev_ops); From 2ae8d516c3d98fad344ceba9b37c3a006482c085 Mon Sep 17 00:00:00 2001 From: Wen Nuan Date: Sun, 11 Feb 2018 17:02:42 +0800 Subject: [PATCH 389/427] ARM: dts: rockchip: rk3288: Add dts mipi-dphy TXRX1 node for rk3288 Change-Id: I0b6122b2b34ae0f24f0d4a1111c1bbe6018cac4e Signed-off-by: Wen Nuan --- arch/arm/boot/dts/rk3288.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index e3b526f03339..b37d1954d27c 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1452,6 +1452,15 @@ }; }; + mipi_phy_tx1rx1: mipi-phy-tx1rx1@ff968000 { + compatible = "rockchip,rk3288-mipi-dphy"; + reg = <0x0 0xff968000 0x0 0x4000>; + rockchip,grf = <&grf>; + clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_CSI>; + clock-names = "dphy-ref", "pclk"; + status = "disabled"; + }; + edp: dp@ff970000 { compatible = "rockchip,rk3288-dp"; reg = <0x0 0xff970000 0x0 0x4000>; From 0be7b88d66a64d6d734ea025f9f8aeacbbe588d0 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Tue, 13 Feb 2018 09:59:38 +0800 Subject: [PATCH 390/427] drivers/input/touchscreen/cy8c_touchpad: fix compile warning drivers/input/touchscreen/cy8c_touchpad.c:77:20: warning: xfer_msg[1].flags is used uninitialized in this function [-Wuninitialized] Change-Id: I2d1f199f098b38af92037e2ebbd63c05fc4a1f35 Signed-off-by: Tao Huang --- drivers/input/touchscreen/cy8c_touchpad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/cy8c_touchpad.c b/drivers/input/touchscreen/cy8c_touchpad.c index 87a1962ae566..8088cb918c79 100644 --- a/drivers/input/touchscreen/cy8c_touchpad.c +++ b/drivers/input/touchscreen/cy8c_touchpad.c @@ -74,7 +74,7 @@ static u32 i2c_cy8ctouch_read(struct cy8c_touch *ts, u8 *buf, u32 num) xfer_msg[1].addr = client->addr; xfer_msg[1].len = num; - xfer_msg[1].flags |= I2C_M_RD; + xfer_msg[1].flags = I2C_M_RD; xfer_msg[1].buf = buf; ret = i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg)); From 375c137b919009ea9934adf3c2e624591bd2bc52 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Tue, 13 Feb 2018 10:28:02 +0800 Subject: [PATCH 391/427] drivers/regulator/syr82x: fix compile warning drivers/regulator/syr82x.c:451:3: warning: this if clause does not guard... [-Wmisleading-indentation] Change-Id: Ibdb1f6f903d1e0dece7b58aa3ec89d075e6d5b79 Signed-off-by: Tao Huang --- drivers/regulator/syr82x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/syr82x.c b/drivers/regulator/syr82x.c index 40af7e507a2e..4f7b0892a3bc 100755 --- a/drivers/regulator/syr82x.c +++ b/drivers/regulator/syr82x.c @@ -450,12 +450,12 @@ static int syr82x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id * config.driver_data = syr82x; if (syr82x->dev->of_node) config.of_node = pdev->of_node[0]; - if (reg_data && reg_data->constraints.name) - rail_name = reg_data->constraints.name; - else - rail_name = regulators[0].name; - reg_data->supply_regulator = rail_name; - + if (reg_data && reg_data->constraints.name) + rail_name = reg_data->constraints.name; + else + rail_name = regulators[0].name; + reg_data->supply_regulator = rail_name; + config.init_data =reg_data; sy_rdev = regulator_register(®ulators[0],&config); if (IS_ERR(sy_rdev)) { From 2fcb17dc9944a31a295ba632949a553b6e891e7d Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Tue, 13 Feb 2018 10:40:32 +0800 Subject: [PATCH 392/427] regulator: rk808: rk809: the sw1 enable bit intercnvert with sw2 Change-Id: I240ac375005e0521c808c09b3f7f07e9899bda63 Signed-off-by: shengfei Xu --- drivers/regulator/rk808-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index f1bbb6c1bc9e..f24dd35d6ed1 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -1455,11 +1455,11 @@ static const struct regulator_desc rk809_reg[] = { .owner = THIS_MODULE, }, RK817_DESC_SWITCH(RK809_ID_SW1, "SWITCH_REG1", "vcc8", - RK817_POWER_EN_REG(3), ENABLE_MASK(2), - ENABLE_MASK(2), DISABLE_VAL(2)), - RK817_DESC_SWITCH(RK809_ID_SW2, "SWITCH_REG2", "vcc9", RK817_POWER_EN_REG(3), ENABLE_MASK(3), ENABLE_MASK(3), DISABLE_VAL(3)), + RK817_DESC_SWITCH(RK809_ID_SW2, "SWITCH_REG2", "vcc9", + RK817_POWER_EN_REG(3), ENABLE_MASK(2), + ENABLE_MASK(2), DISABLE_VAL(2)), }; static int rk808_regulator_dt_parse_pdata(struct device *dev, From 6e0e7a80faffb9651f09c2aa945b8ad6deb7023c Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 13 Feb 2018 15:01:18 +0800 Subject: [PATCH 393/427] MALI: bifrost: Avoid GPU voltage domain keeping the initial voltage If there is only one opp whose frequency is equal to the initial value in opp table list, the GPU voltage domain will keep the initial voltage, it may be too large. Change-Id: If2ae1c876de185d810e05296b1b9e98855c3ef48 Signed-off-by: Finley Xiao --- .../arm/bifrost/backend/gpu/mali_kbase_devfreq.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c index e280322e223d..b9c6f616ddff 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -103,6 +103,16 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) */ if (kbdev->current_nominal_freq == nominal_freq) { *target_freq = nominal_freq; +#ifdef CONFIG_REGULATOR + if (kbdev->current_voltage == voltage) + return 0; + err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + if (err) { + dev_err(dev, "Failed to set voltage (%d)\n", err); + return err; + } + kbdev->current_voltage = voltage; +#endif return 0; } @@ -318,6 +328,11 @@ int kbase_devfreq_init(struct kbase_device *kbdev) kbdev->current_freq = clk_get_rate(kbdev->clock); kbdev->current_nominal_freq = kbdev->current_freq; +#ifdef CONFIG_REGULATOR + if (kbdev->regulator) + kbdev->current_voltage = + regulator_get_voltage(kbdev->regulator); +#endif dp = &kbdev->devfreq_profile; From f09c78549e24d693e40d7008066dbb4671252e4c Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 13 Feb 2018 15:07:24 +0800 Subject: [PATCH 394/427] MALI: bifrost: support sharing regulator with other devices If the regulator is shared between several devices then the lowest request voltage that meets the system constraints will be used. Change-Id: Icb6afcb571bddd6709d352dfad8fc2da80567bc0 Signed-off-by: Finley Xiao --- drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c index b9c6f616ddff..ba42acabf9fe 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -106,7 +106,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) #ifdef CONFIG_REGULATOR if (kbdev->current_voltage == voltage) return 0; - err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + err = regulator_set_voltage(kbdev->regulator, voltage, INT_MAX); if (err) { dev_err(dev, "Failed to set voltage (%d)\n", err); return err; @@ -120,7 +120,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) #ifdef CONFIG_REGULATOR if (kbdev->regulator && kbdev->current_voltage != voltage && kbdev->current_freq < freq) { - err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + err = regulator_set_voltage(kbdev->regulator, voltage, INT_MAX); if (err) { dev_err(dev, "Failed to increase voltage (%d)\n", err); return err; @@ -138,7 +138,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) #ifdef CONFIG_REGULATOR if (kbdev->regulator && kbdev->current_voltage != voltage && kbdev->current_freq > freq) { - err = regulator_set_voltage(kbdev->regulator, voltage, voltage); + err = regulator_set_voltage(kbdev->regulator, voltage, INT_MAX); if (err) { dev_err(dev, "Failed to decrease voltage (%d)\n", err); return err; From dd6270d4daa649ad5c6ef323bad222a665185a8b Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 13 Feb 2018 16:19:44 +0800 Subject: [PATCH 395/427] clk: rockchip: px30: Fix gpu frequency overflowing It needs to contains rate and mux clk for gpu composite clk, so that the clk_composite_set_rate_and_parent function can be called. Change-Id: I9818df2adbbcf40f616d2ca230cd83ea1ef2c14f Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index ab6bd4b1dda6..2173f0609c4d 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -338,15 +338,12 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { PX30_CLKGATE_CON(17), 4, GFLAGS), /* PD_GPU */ - COMPOSITE_NODIV(0, "clk_gpu_src", mux_4plls_p, 0, - PX30_CLKSEL_CON(1), 6, 2, MFLAGS, + COMPOSITE(0, "clk_gpu_src", mux_4plls_p, 0, + PX30_CLKSEL_CON(1), 6, 2, MFLAGS, 0, 4, DFLAGS, PX30_CLKGATE_CON(0), 8, GFLAGS), - COMPOSITE_NOMUX(0, "clk_gpu_div", "clk_gpu_src", CLK_SET_RATE_PARENT, - PX30_CLKSEL_CON(1), 0, 4, DFLAGS, - PX30_CLKGATE_CON(0), 12, GFLAGS), - GATE(ACLK_GPU, "clk_gpu_pre", "clk_gpu_div", 0, + GATE(ACLK_GPU, "clk_gpu", "clk_gpu_src", 0, PX30_CLKGATE_CON(0), 10, GFLAGS), - COMPOSITE_NOMUX(0, "aclk_gpu", "clk_gpu_pre", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(0, "aclk_gpu", "clk_gpu", CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(1), 13, 2, DFLAGS, PX30_CLKGATE_CON(17), 10, GFLAGS), GATE(0, "aclk_gpu_niu", "aclk_gpu", CLK_IGNORE_UNUSED, From 0813f9a09adb449a0ab131d1df15ce0be4224f83 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 13 Feb 2018 16:53:49 +0800 Subject: [PATCH 396/427] arm64: dts: rockchip: px30: Change clock id for gpu Change-Id: I04ccacc3f60c7a1e4b0fa854680564963ec110fd Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30.dtsi | 4 ++-- drivers/clk/rockchip/clk-px30.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 94f2438f1048..15163b1adcdb 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -234,7 +234,7 @@ }; pd_gpu@PX30_PD_GPU { reg = ; - clocks = <&cru ACLK_GPU>; + clocks = <&cru SCLK_GPU>; pm_qos = <&qos_gpu>; }; }; @@ -966,7 +966,7 @@ ; interrupt-names = "GPU", "MMU", "JOB"; - clocks = <&cru ACLK_GPU>; + clocks = <&cru SCLK_GPU>; clock-names = "clk_mali"; power-domains = <&power PX30_PD_GPU>; operating-points-v2 = <&gpu_opp_table>; diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 2173f0609c4d..19d981fa17ce 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -341,7 +341,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { COMPOSITE(0, "clk_gpu_src", mux_4plls_p, 0, PX30_CLKSEL_CON(1), 6, 2, MFLAGS, 0, 4, DFLAGS, PX30_CLKGATE_CON(0), 8, GFLAGS), - GATE(ACLK_GPU, "clk_gpu", "clk_gpu_src", 0, + GATE(SCLK_GPU, "clk_gpu", "clk_gpu_src", 0, PX30_CLKGATE_CON(0), 10, GFLAGS), COMPOSITE_NOMUX(0, "aclk_gpu", "clk_gpu", CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(1), 13, 2, DFLAGS, From d9c3f985e41392ea196dc9ecf5f315f5fade8816 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 13 Feb 2018 17:57:25 +0800 Subject: [PATCH 397/427] arm64: dts: rockchip: px30: xin32k use the fixed clk If xin32k use the rk808_clkout1, rk808 init is too late, xin32k enable count and prepare count is not match with it's child clk. Change-Id: Iec5d1f91b2289b18f41b4d915e6859154a5b7635 Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 2 +- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 2 +- arch/arm64/boot/dts/rockchip/px30.dtsi | 7 +++++++ arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 2 +- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 67c7e8a6dae5..1ca9a099c332 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -291,7 +291,7 @@ rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vcc5v0_sys>; vcc2-supply = <&vcc5v0_sys>; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 21bfae817f48..1d40733013ce 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -291,7 +291,7 @@ rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vcc5v0_sys>; vcc2-supply = <&vcc5v0_sys>; diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 15163b1adcdb..0188fd40bf58 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -153,6 +153,13 @@ clock-output-names = "xin24m"; }; + xin32k: xin32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + }; + pmu: power-management@ff000000 { compatible = "rockchip,px30-pmu", "syscon", "simple-mfd"; reg = <0x0 0xff000000 0x0 0x1000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 347cb34619c6..3c4873d1f361 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -256,7 +256,7 @@ rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vccsys>; vcc2-supply = <&vccsys>; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 79dd072d12d4..e2e5b6a2ab6f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -350,7 +350,7 @@ rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vccsys>; vcc2-supply = <&vccsys>; From fda77d7005ab14286146a6dcd8a0d60c1b69e13f Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 21 Feb 2018 11:22:21 +0800 Subject: [PATCH 398/427] clk: rockchip: px30: Add clock id for aclk_bus_src and aclk_peri_src Change-Id: I3467b4f799a6f5402eed3d20e4bd2c02ae30c92f Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 4 ++-- include/dt-bindings/clock/px30-cru.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 19d981fa17ce..91afa26d6568 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -483,7 +483,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { * Clock-Architecture Diagram 7 */ - COMPOSITE_NODIV(0, "aclk_peri_src", mux_gpll_cpll_p, 0, + COMPOSITE_NODIV(ACLK_PERI_SRC, "aclk_peri_src", mux_gpll_cpll_p, 0, PX30_CLKSEL_CON(14), 15, 1, MFLAGS, PX30_CLKGATE_CON(5), 7, GFLAGS), COMPOSITE_NOMUX(ACLK_PERI_PRE, "aclk_peri_pre", "aclk_peri_src", CLK_IGNORE_UNUSED, @@ -601,7 +601,7 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = { */ /* PD_BUS */ - COMPOSITE_NODIV(0, "aclk_bus_src", mux_gpll_cpll_p, CLK_IGNORE_UNUSED, + COMPOSITE_NODIV(ACLK_BUS_SRC, "aclk_bus_src", mux_gpll_cpll_p, CLK_IGNORE_UNUSED, PX30_CLKSEL_CON(23), 15, 1, MFLAGS, PX30_CLKGATE_CON(8), 6, GFLAGS), COMPOSITE_NOMUX(HCLK_BUS_PRE, "hclk_bus_pre", "aclk_bus_src", CLK_IGNORE_UNUSED, diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h index ca6761ae29fb..0e405d9cdd39 100644 --- a/include/dt-bindings/clock/px30-cru.h +++ b/include/dt-bindings/clock/px30-cru.h @@ -119,6 +119,8 @@ #define ACLK_GIC 184 #define ACLK_DCF 186 #define ACLK_DMAC 187 +#define ACLK_BUS_SRC 188 +#define ACLK_PERI_SRC 189 /* hclk gates */ #define HCLK_BUS_PRE 240 From 73403cf5b2cea690ea39982cc22a856215e50f60 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 21 Feb 2018 17:53:56 +0800 Subject: [PATCH 399/427] clk: rockchip: px30: fix gpll enable_cnt and prepare_cnt error The gpll clock has not yet been created when its children do enable and prepare in cru critical talbe, so move its children into pmucru critical talbe that the gpll clock has been created before its children do enable and prepare. Change-Id: If5243326bf1d3c926bb1bb12e56e4b9fc9282762 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-px30.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 91afa26d6568..5c2d69ffa8a3 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -1004,7 +1004,7 @@ static struct rockchip_clk_branch px30_clk_pmu_branches[] __initdata = { GATE(0, "pclk_cru_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 8, GFLAGS), }; -static const char *const px30_critical_clocks[] __initconst = { +static const char *const px30_pmucru_critical_clocks[] __initconst = { "aclk_bus_pre", "pclk_bus_pre", "hclk_bus_pre", @@ -1012,9 +1012,6 @@ static const char *const px30_critical_clocks[] __initconst = { "hclk_peri_pre", "aclk_gpu_niu", "pclk_top_pre", -}; - -static const char *const px30_pmucru_critical_clocks[] __initconst = { "pclk_pmu_pre", }; @@ -1083,8 +1080,6 @@ static void __init px30_clk_init(struct device_node *np) PX30_GRF_SOC_STATUS0); rockchip_clk_register_branches(ctx, px30_clk_branches, ARRAY_SIZE(px30_clk_branches)); - rockchip_clk_protect_critical(px30_critical_clocks, - ARRAY_SIZE(px30_critical_clocks)); rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), From 2c1c86dca03672433064faf67976c01a3b25e7f1 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Sat, 10 Feb 2018 19:05:57 +0800 Subject: [PATCH 400/427] power: rk817: fix the battery charging but dispaly soc not up Change-Id: I3153dad46c959670f11dd91c7cbd687f4136c171 Signed-off-by: shengfei Xu --- drivers/power/rk817_battery.c | 154 +++++++++++++++++++++++++++++----- 1 file changed, 135 insertions(+), 19 deletions(-) diff --git a/drivers/power/rk817_battery.c b/drivers/power/rk817_battery.c index aa9163d62c40..ab3ef6a2599c 100644 --- a/drivers/power/rk817_battery.c +++ b/drivers/power/rk817_battery.c @@ -37,7 +37,7 @@ #include #include -static int dbg_enable; +static int dbg_enable = 1; module_param_named(dbg_level, dbg_enable, int, 0644); @@ -495,6 +495,19 @@ struct rk817_battery_device { int zero_linek; u64 zero_drop_sec; u64 shtd_drop_sec; + + int powerpatch_res; + int zero_voltage_avg; + int zero_current_avg; + int zero_vsys; + int zero_dead_voltage; + int zero_dead_soc; + int zero_dead_cap; + int zero_batvol_to_ocv; + int zero_batocv_to_soc; + int zero_batocv_to_cap; + int zero_xsoc; + int sm_remain_cap; int sm_linek; int sm_chrg_dsoc; @@ -1330,16 +1343,27 @@ static void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery) { int linek; int diff, delta; + int current_avg = rk817_bat_get_avg_current(battery); delta = abs(battery->dsoc - battery->rsoc); diff = delta * 3;/* speed:3/4 */ - if (battery->dsoc < battery->rsoc) - linek = -1000 * diff / DIV(delta + diff); - else if (battery->dsoc > battery->rsoc) - linek = -1000 * (delta + diff) / DIV(diff); - else - linek = -1000; + if (current_avg > 0) { + if (battery->dsoc < battery->rsoc) + linek = 1000 * diff / DIV(delta + diff); + else if (battery->dsoc > battery->rsoc) + linek = 1000 * (delta + diff) / DIV(diff); + else + linek = 1000; + } else { + if (battery->dsoc < battery->rsoc) + linek = -1000 * diff / DIV(delta + diff); + else if (battery->dsoc > battery->rsoc) + linek = -1000 * (delta + diff) / DIV(diff); + else + linek = -1000; + } + battery->dbg_meet_soc = (battery->dsoc >= battery->rsoc) ? (battery->dsoc - diff) : (battery->rsoc - diff); @@ -1403,6 +1427,7 @@ static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery) battery->is_initialized = is_rk817_bat_initialized(battery); battery->is_ocv_calib = is_rk817_bat_ocv_valid(battery); + pre_soc *= 1000; if (battery->is_halt) { BAT_INFO("system halt last time... cap: pre=%d, now=%d\n", pre_cap, now_cap); @@ -1448,7 +1473,7 @@ static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery) } } finish: - battery->dsoc = pre_soc * 1000; + battery->dsoc = pre_soc; battery->nac = pre_cap; if (battery->nac < 0) battery->nac = 0; @@ -1784,8 +1809,8 @@ static void rk817_bat_power_supply_changed(struct rk817_battery_device *battery) { static int old_soc = -1; - if (battery->dsoc > 100) - battery->dsoc = 100; + if (battery->dsoc > 100 * 1000) + battery->dsoc = 100 * 1000; else if (battery->dsoc < 0) battery->dsoc = 0; @@ -1828,8 +1853,6 @@ static void rk817_battery_debug_info(struct rk817_battery_device *battery) rk817_bat_get_ocv_current(battery); rk817_bat_get_ocv_current0(battery); rk817_bat_get_pwron_current(battery); - rk817_bat_init_coulomb_cap(battery, 500); - rk817_bat_update_qmax(battery, 1000); rk817_bat_get_ocv_count(battery); rk817_bat_save_dsoc(battery, battery->dsoc); DBG("capactiy = %d\n", rk817_bat_get_capacity_mah(battery)); @@ -1919,7 +1942,31 @@ static void rk817_bat_calc_smooth_dischrg(struct rk817_battery_device *battery) static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) { - int ydsoc = 0, delta_cap = 0, old_cap = 0; + int ydsoc = 0, delta_cap = 0, old_cap = 0, tmp_soc; + int linek; + int diff, delta; + int current_avg = rk817_bat_get_avg_current(battery); + + delta = abs(battery->dsoc - battery->rsoc); + diff = delta * 3;/* speed:3/4 */ + + if (current_avg > 0) { + if (battery->dsoc < battery->rsoc) + linek = 1000 * diff / DIV(delta + diff); + else if (battery->dsoc > battery->rsoc) + linek = 1000 * (delta + diff) / DIV(diff); + else + linek = 1000; + } else { + if (battery->dsoc < battery->rsoc) + linek = -1000 * diff / DIV(delta + diff); + else if (battery->dsoc > battery->rsoc) + linek = -1000 * (delta + diff) / DIV(diff); + else + linek = -1000; + } + + battery->sm_linek = linek; battery->remain_cap = rk817_bat_get_capacity_uah(battery); @@ -1931,7 +1978,7 @@ static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) /* from charge to discharge: * remain_cap may be above sm_remain_cap, delta_cap <= 0 */ - delta_cap = battery->sm_remain_cap - battery->remain_cap; + delta_cap = battery->remain_cap - battery->sm_remain_cap; DBG("smooth: sm_remain_cap = %d, remain_cap = %d\n", battery->sm_remain_cap, battery->remain_cap); DBG("smooth: delta_cap = %d, dsoc = %d\n", @@ -1943,7 +1990,7 @@ static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) } /* discharge: sm_linek < 0, if delate_cap <0, ydsoc > 0 */ - ydsoc = battery->sm_linek * (delta_cap / DIV(battery->fcc)) / 10; + ydsoc = battery->sm_linek * abs(delta_cap / DIV(battery->fcc)) / 10; DBG("smooth: ydsoc = %d, fcc = %d\n", ydsoc, battery->fcc); if (ydsoc == 0) { @@ -1961,8 +2008,26 @@ static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) * from charge status to dischrage */ battery->smooth_soc += ydsoc; - if (ydsoc < 0) + if (ydsoc < 0) { rk817_bat_calc_smooth_dischrg(battery); + } else { + if (battery->smooth_soc < 0) + battery->smooth_soc = 0; + + tmp_soc = battery->smooth_soc / 1000; + + if (tmp_soc != battery->dsoc / 1000) { + if (battery->smooth_soc < battery->dsoc) + return; + if (battery->smooth_soc > battery->dsoc + 1000) + battery->dsoc += 1000; + else + battery->dsoc = battery->smooth_soc; + if (battery->dsoc <= 0) + battery->dsoc = 0; + } + } + DBG("smooth: smooth_soc = %d, dsoc = %d\n", battery->smooth_soc, battery->dsoc); DBG("smooth: delta_cap = %d, dsoc = %d\n", @@ -1991,6 +2056,10 @@ static void rk817_bat_calc_zero_linek(struct rk817_battery_device *battery) powerpatch_res = (voltage_avg - vsys) * 1000 / current_avg; + battery->zero_voltage_avg = voltage_avg; + battery->zero_current_avg = current_avg; + battery->zero_vsys = vsys; + DBG("Zero: voltage_avg = %d, Vsys = %d\n", voltage_avg, vsys); DBG("Zero: powerpatch_res = %d\n", powerpatch_res); DBG("ZERO0: shtd_vol: poweroff_vol(usr) = %d\n" @@ -2022,6 +2091,16 @@ static void rk817_bat_calc_zero_linek(struct rk817_battery_device *battery) /* xsoc: available rsoc */ xsoc = ocv_soc - dead_soc; + battery->zero_dead_voltage = dead_voltage; + battery->zero_dead_soc = dead_soc; + battery->zero_dead_cap = dead_cap; + + battery->zero_batvol_to_ocv = ocv_voltage; + battery->zero_batocv_to_soc = ocv_soc; + battery->zero_batocv_to_cap = ocv_cap; + + battery->zero_xsoc = xsoc; + DBG("Zero: xsoc = %d\n", xsoc); /* min_gap_xsoc: reserve xsoc */ if (abs(current_avg) > ZERO_LOAD_LVL1) @@ -2152,6 +2231,20 @@ static void rk817_bat_zero_algo_prepare(struct rk817_battery_device *battery) static void rk817_bat_calc_zero_algorithm(struct rk817_battery_device *battery) { + int tmp_soc; + + tmp_soc = battery->zero_dsoc / 1000; + + if (tmp_soc == battery->dsoc / 1000) + return; + + if (battery->zero_dsoc > battery->dsoc) + return; + + if (battery->zero_dsoc < battery->dsoc - 1000) + battery->dsoc -= 1000; + else + battery->dsoc = battery->zero_dsoc; } static void rk817_bat_zero_algorithm(struct rk817_battery_device *battery) @@ -2160,12 +2253,34 @@ static void rk817_bat_zero_algorithm(struct rk817_battery_device *battery) battery->zero_timeout_cnt++; delta_cap = battery->zero_remain_cap - battery->remain_cap; - delta_soc = battery->zero_linek * (delta_cap / DIV(battery->fcc)) / 10; + delta_soc = battery->zero_linek * delta_cap / DIV(battery->fcc) / 10; - DBG("Zero: zero_remain_cap = %d, remain_cap = %d\n", + DBG("zero algorithm start\n"); + DBG("DEAD: dead_voltage: %d\n" + "dead_soc: %d\n" + "dead_cap: %d\n" + "powoff_vol: %d\n", + battery->zero_dead_voltage, + battery->zero_dead_soc, + battery->zero_dead_cap, + battery->pdata->pwroff_vol); + DBG("DEAD: bat_voltage: %d\n" + "bat_current: %d\n" + "batvol_to_ocv: %d\n" + "batocv_to_soc: %d\n" + "batocv_to_cap: %d\n", + battery->zero_voltage_avg, + battery->zero_current_avg, + battery->zero_batvol_to_ocv, + battery->zero_batocv_to_soc, + battery->zero_batocv_to_cap); + DBG("DEAD: Xsoc: %d, zero_reserve_dsoc: %d\n", + battery->zero_xsoc, battery->pdata->zero_reserve_dsoc); + DBG("CAP: zero_remain_cap = %d, remain_cap = %d\n", battery->zero_remain_cap, battery->remain_cap); DBG("Zero: zero_delta_cap = %d, zero_link = %d, delta_soc = %d\n", delta_cap, battery->zero_linek, delta_soc); + DBG("zero algorithm end\n"); if ((delta_soc >= MIN_ZERO_DSOC_ACCURACY) || (battery->zero_timeout_cnt > MIN_ZERO_OVERCNT) || @@ -2174,6 +2289,7 @@ static void rk817_bat_zero_algorithm(struct rk817_battery_device *battery) battery->zero_timeout_cnt = 0; battery->zero_dsoc -= delta_soc; rk817_bat_calc_zero_algorithm(battery); + DBG("Zero: dsoc: %d\n", battery->dsoc); rk817_bat_calc_zero_linek(battery); } } @@ -2315,7 +2431,7 @@ static int rk817_battery_probe(struct platform_device *pdev) rk817_battery_debug_info(battery); rk817_bat_update_info(battery); - + rk817_bat_output_info(battery); battery->bat_monitor_wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk817-bat-monitor-wq"); INIT_DELAYED_WORK(&battery->bat_delay_work, rk817_battery_work); From 14aba8d3783b8a3d24ee486982dc730a478e0e2a Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 22 Feb 2018 10:52:05 +0800 Subject: [PATCH 401/427] clk: rockchip: Fix cpu frequency overflowing If change parent to alternate parent and the old parent clock speed is less than the clock speed of the alternate parent, add dividers first and then select alternate parent. If change parent to primary parent, select primary parent first and then remove dividers. Change-Id: Ib82de9a936effe5c885639799f3bb5629dc89f8d Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-cpu.c | 42 ++++++++++++---------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 4d9f38de342b..675f10cc0ed4 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -158,30 +158,21 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, alt_div = reg_data->div_core_mask; } - /* - * Change parents and add dividers in a single transaction. - * - * NOTE: we do this in a single transaction so we're never - * dividing the primary parent by the extra dividers that were - * needed for the alt. - */ pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n", __func__, alt_div, alt_prate, ndata->old_rate); + /* add dividers */ writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, - reg_data->div_core_shift) | - HIWORD_UPDATE(reg_data->mux_core_alt, - reg_data->mux_core_mask, - reg_data->mux_core_shift), - cpuclk->reg_base + reg_data->core_reg); - } else { - /* select alternate parent */ - writel(HIWORD_UPDATE(reg_data->mux_core_alt, - reg_data->mux_core_mask, - reg_data->mux_core_shift), + reg_data->div_core_shift), cpuclk->reg_base + reg_data->core_reg); } + /* select alternate parent */ + writel(HIWORD_UPDATE(reg_data->mux_core_alt, + reg_data->mux_core_mask, + reg_data->mux_core_shift), + cpuclk->reg_base + reg_data->core_reg); + spin_unlock_irqrestore(cpuclk->lock, flags); return 0; } @@ -206,18 +197,15 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, if (ndata->old_rate < ndata->new_rate) rockchip_cpuclk_set_dividers(cpuclk, rate); - /* - * post-rate change event, re-mux to primary parent and remove dividers. - * - * NOTE: we do this in a single transaction so we're never dividing the - * primary parent by the extra dividers that were needed for the alt. - */ + /* re-mux to primary parent */ + writel(HIWORD_UPDATE(reg_data->mux_core_main, + reg_data->mux_core_mask, + reg_data->mux_core_shift), + cpuclk->reg_base + reg_data->core_reg); + /* remove dividers */ writel(HIWORD_UPDATE(0, reg_data->div_core_mask, - reg_data->div_core_shift) | - HIWORD_UPDATE(reg_data->mux_core_main, - reg_data->mux_core_mask, - reg_data->mux_core_shift), + reg_data->div_core_shift), cpuclk->reg_base + reg_data->core_reg); if (ndata->old_rate > ndata->new_rate) From 99cb28c225c625eb5c3f987971574e767f98f67c Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Thu, 22 Feb 2018 10:05:19 +0800 Subject: [PATCH 402/427] arm64: dts: rockchip: allow to disable vcc3v3_lcd on px30-evb board remove the 'regulator-always-on' property from vcc3v3_lcd Change-Id: I056601ed575b993065c17d245195bd376808bbed Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 3 +-- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 1ca9a099c332..93acddb1d032 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -158,7 +158,7 @@ panel@0 { compatible = "sitronix,st7703", "simple-panel-dsi"; reg = <0>; - //power-supply = <&vcc3v3_lcd>; + power-supply = <&vcc3v3_lcd>; backlight = <&backlight>; prepare-delay-ms = <2>; reset-delay-ms = <1>; @@ -486,7 +486,6 @@ }; vcc3v3_lcd: SWITCH_REG1 { - regulator-always-on; regulator-boot-on; regulator-name = "vcc3v3_lcd"; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 1d40733013ce..0db2c6a6de4d 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -158,7 +158,7 @@ panel@0 { compatible = "sitronix,st7703", "simple-panel-dsi"; reg = <0>; - //power-supply = <&vcc3v3_lcd>; + power-supply = <&vcc3v3_lcd>; backlight = <&backlight>; prepare-delay-ms = <2>; reset-delay-ms = <1>; @@ -487,7 +487,6 @@ }; vcc3v3_lcd: SWITCH_REG1 { - regulator-always-on; regulator-boot-on; regulator-name = "vcc3v3_lcd"; }; From f64e967ae6892cf8cb202099e85301947be3c85c Mon Sep 17 00:00:00 2001 From: XiaoDong Huang Date: Thu, 22 Feb 2018 16:28:36 +0800 Subject: [PATCH 403/427] arm64: dts: rockchip: px30: adjust suspend voltage 1. adjust vdd_logic to 950000uV. 2. adjust vdd_arm to 950000uV. 3. set vdd_10 on. 4. set vcc3v0_pmu on. Change-Id: I1af72ccbc615f6bdcb59f51ac6ea54e8c3bfe2af Signed-off-by: XiaoDong Huang --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 8 ++++---- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 8 ++++---- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 8 ++++---- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 93acddb1d032..46eb2248afa2 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -314,7 +314,7 @@ regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -328,7 +328,7 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -388,7 +388,7 @@ regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -401,7 +401,7 @@ regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 0db2c6a6de4d..12cb22de3640 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -314,7 +314,7 @@ regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -328,7 +328,7 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -389,7 +389,7 @@ regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -402,7 +402,7 @@ regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 3c4873d1f361..60b63a7ad8b3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -279,7 +279,7 @@ regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -293,7 +293,7 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -353,7 +353,7 @@ regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -366,7 +366,7 @@ regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index e2e5b6a2ab6f..bbae0dd14e71 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -373,7 +373,7 @@ regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -387,7 +387,7 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -447,7 +447,7 @@ regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -460,7 +460,7 @@ regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; From 9c8f6bbf418b3f7e7425f116a84e603aebbb1cab Mon Sep 17 00:00:00 2001 From: Evgeniy Didin Date: Fri, 23 Feb 2018 09:43:41 +0800 Subject: [PATCH 404/427] FROMLIST: mmc: dw_mmc: Fix the DTO timeout overflow calculation for 32-bit systems In commit 9d9491a7da2a ("mmc: dw_mmc: Fix the DTO timeout calculation") have been made changes which cause multiply overflow for 32-bit systems. The broken timeout calculations caused false interrupt latency warnings and stacktrace splat (such as below) when accessing the SD Card. | Running : 4M-check-reassembly-tcp-cmykw2-rotatew2.out -v0 -w1 | - Info: Finished target initialization. | mmcblk0: error -110 transferring data, sector 320544, nr 2048, cmd response | 0x900, card status 0x0 | mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req 400000Hz, actual | 396825HZ div = 63) | mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req 25000000Hz, actual | 25000000HZ div = 1) | ------------[ cut here ]------------ | softirq: huh, entered softirq 6 TASKLET 6f6a9412 with preempt_count 00000101, | exited with 00000100? | WARNING: CPU: 2 PID: 0 at ../lib/scatterlist.c:652 sg_miter_next+0x28/0x20c | Modules linked in: | CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.15.0 #57 | | Stack Trace: | arc_unwind_core.constprop.1+0xd0/0xf4 | dump_stack+0x68/0x80 | warn_slowpath_null+0x4e/0xec | sg_miter_next+0x28/0x20c | dw_mci_read_data_pio+0x44/0x190 | dw_mmc f000a000.mmc: Unexpected interrupt latency | dw_mci_interrupt+0x3ee/0x530 | __handle_irq_event_percpu+0x56/0x150 | handle_irq_event+0x34/0x78 | handle_level_irq+0x8e/0x120 | generic_handle_irq+0x1c/0x2c | idu_cascade_isr+0x30/0x6c | __handle_domain_irq+0x72/0xc8 | ret_from_exception+0x0/0x8 |---[ end trace 2a58c9af6c25fe51 ]--- Lets cast this multiply to u64 type which prevents overflow. Tested-by: Vineet Gupta Fixes: 9d9491a7da2a ("mmc: dw_mmc: Fix the DTO timeout calculation") Reported-by: Vineet Gupta # ARC STAR 9001306872 HSDK, sdio: board crashes when copying big files Signed-off-by: Evgeniy Didin CC: Alexey Brodkin CC: Eugeniy Paltsev CC: Douglas Anderson CC: Ulf Hansson CC: linux-kernel@vger.kernel.org CC: linux-snps-arc@lists.infradead.org Cc: Reviewed-by: Shawn Lin Change-Id: Ib7614b17116e53debe738787fc26a04beba5f388 Signed-off-by: Shawn Lin --- drivers/mmc/host/dw_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 8730e2e8bc77..6e3ea0856e7b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1768,8 +1768,8 @@ static void dw_mci_set_drto(struct dw_mci *host) drto_div = (mci_readl(host, CLKDIV) & 0xff) * 2; if (drto_div == 0) drto_div = 1; - drto_ms = DIV_ROUND_UP(MSEC_PER_SEC * drto_clks * drto_div, - host->bus_hz); + drto_ms = DIV_ROUND_UP_ULL(MSEC_PER_SEC * drto_clks * drto_div, + host->bus_hz); /* add a bit spare time */ drto_ms += 10; From bc6e99f24320fd3e323996756970b848be0f3af3 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 23 Feb 2018 09:46:54 +0800 Subject: [PATCH 405/427] mmc: dw_mmc: Fix the CTO timeout overflow calculation for 32-bit systems Just follow the convention of fixing for DTO timeout. Change-Id: I753b5a6f2ab409e58c83a59212592f3b430b018a Signed-off-by: Shawn Lin --- drivers/mmc/host/dw_mmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 6e3ea0856e7b..d4fc22974d3d 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -376,7 +376,8 @@ static inline void dw_mci_set_cto(struct dw_mci *host) cto_div = (mci_readl(host, CLKDIV) & 0xff) * 2; if (cto_div == 0) cto_div = 1; - cto_ms = DIV_ROUND_UP(MSEC_PER_SEC * cto_clks * cto_div, host->bus_hz); + cto_ms = DIV_ROUND_UP_ULL(MSEC_PER_SEC * cto_clks * cto_div, + host->bus_hz); /* add a bit spare time */ cto_ms += 10; From 921df26c80f0be8a102298bf413dd572d98dc4aa Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 23 Feb 2018 10:42:56 +0800 Subject: [PATCH 406/427] f2fs: fix out-of-bounds read in update_free_nid_bitmap test_bit will access with unsigned long, which cause this bug. Workaround by enlarge free_nid_bitmap. BUG: KASAN: slab-out-of-bounds in update_free_nid_bitmap+0x98/0x16c Read of size 8 at addr ffffffc06275c9ff by task init/195 CPU: 3 PID: 195 Comm: init Not tainted 4.4.114 #55 Hardware name: Rockchip rk3326 evb board (DT) Call trace: dump_backtrace+0x0/0x244 show_stack+0x14/0x1c dump_stack+0xa4/0xcc print_address_description+0xa4/0x308 kasan_report+0x258/0x29c __asan_load8+0x78/0x80 update_free_nid_bitmap+0x98/0x16c build_node_manager+0x884/0x950 f2fs_fill_super+0x14bc/0x1ca8 mount_bdev+0x174/0x208 f2fs_mount+0x14/0x1c mount_fs+0xbc/0x1b0 vfs_kern_mount+0xbc/0x1c8 do_mount+0xcf0/0xe68 SyS_mount+0x94/0xe0 el0_svc_naked+0x24/0x28 Change-Id: I9167447ded0a8c2da1b80cdc671615c9108c02be Signed-off-by: Tao Huang --- fs/f2fs/node.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 964c99655942..53ee675c5c32 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -2731,7 +2731,8 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi) struct f2fs_nm_info *nm_i = NM_I(sbi); nm_i->free_nid_bitmap = kvzalloc(nm_i->nat_blocks * - NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL); + NAT_ENTRY_BITMAP_SIZE + + sizeof(unsigned long), GFP_KERNEL); if (!nm_i->free_nid_bitmap) return -ENOMEM; From 7e99010694f5e7b2388903f361c9411daa5d0f41 Mon Sep 17 00:00:00 2001 From: Weiguo Hu Date: Sat, 10 Feb 2018 11:42:55 +0800 Subject: [PATCH 407/427] net: phy: rockchip: do phy reset once in no link status This solve failed to linkup for very few chip This can reduce udp package lost rate sometimes Change-Id: I684d9ea974e56478e7906c6e79c4c8505c042823 Signed-off-by: Weiguo Hu --- drivers/net/phy/rockchip.c | 65 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/drivers/net/phy/rockchip.c b/drivers/net/phy/rockchip.c index b63b3448aaa4..4ee9fa5c2e34 100644 --- a/drivers/net/phy/rockchip.c +++ b/drivers/net/phy/rockchip.c @@ -57,6 +57,8 @@ #define PHY_ABNORMAL_THRESHOLD 15 +#define ENABLE_PHY_FIXUP_RESET + struct rk_int_phy_priv { int restore_reg0; int restore_a3_config; @@ -64,6 +66,8 @@ struct rk_int_phy_priv { int a3_config_set; int txrx_counters_done_count; int last_speed; + int last_state; + int reset; }; static int rockchip_integrated_phy_init_tstmode(struct phy_device *phydev) @@ -192,42 +196,15 @@ static int rockchip_integrated_phy_adjust_a3_config(struct phy_device *phydev, static void rockchip_integrated_phy_link_change_notify(struct phy_device *phydev) { - int speed = SPEED_10; struct rk_int_phy_priv *priv = phydev->priv; - if (phydev->autoneg == AUTONEG_ENABLE) { - int reg = phy_read(phydev, MII_SPECIAL_CONTROL_STATUS); - - if (reg < 0) { - phydev_err(phydev, "phy_read err: %d.\n", reg); - return; - } - - if (reg & MII_SPEED_100) - speed = SPEED_100; - else if (reg & MII_SPEED_10) - speed = SPEED_10; - } else { - int bmcr = phy_read(phydev, MII_BMCR); - - if (bmcr < 0) { - phydev_err(phydev, "phy_read err: %d.\n", bmcr); - return; - } - - if (bmcr & BMCR_SPEED100) - speed = SPEED_100; - else - speed = SPEED_10; - } - /* * If mode switch happens from 10BT to 100BT, all DSP/AFE * registers are set to default values. So any AFE/DSP * registers have to be re-initialized in this case. */ if (phydev->link && - speed == SPEED_100 && + phydev->speed == SPEED_100 && priv->last_speed == SPEED_10) { int ret = rockchip_integrated_phy_analog_init(phydev); @@ -237,7 +214,7 @@ void rockchip_integrated_phy_link_change_notify(struct phy_device *phydev) } if (phydev->link) - priv->last_speed = speed; + priv->last_speed = phydev->speed; } static int rockchip_set_polarity(struct phy_device *phydev, int polarity) @@ -398,6 +375,30 @@ static int rockchip_integrated_phy_fixup_100M(struct phy_device *phydev) return 0; } +#ifdef ENABLE_PHY_FIXUP_RESET +static int rockchip_integrated_phy_fixup_reset(struct phy_device *phydev) +{ + int ret; + struct rk_int_phy_priv *priv = phydev->priv; + + /* reset phy once + * solve failed to linkup for very few chip + * reduce udp package lost rate sometimes + */ + if (priv->last_state == PHY_NOLINK && phydev->state == PHY_NOLINK) { + if (++priv->reset == 2) { + phydev_dbg(phydev, "%s\n", __func__); + ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + } + + priv->last_state = phydev->state; + return 0; +} +#endif + static int rockchip_integrated_phy_read_status(struct phy_device *phydev) { int ret; @@ -414,6 +415,12 @@ static int rockchip_integrated_phy_read_status(struct phy_device *phydev) if (ret) return ret; +#ifdef ENABLE_PHY_FIXUP_RESET + ret = rockchip_integrated_phy_fixup_reset(phydev); + if (ret) + return ret; +#endif + return 0; } From ad85bca9e82371fc2e1b03fa337aeaeeabeeb302 Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Fri, 9 Feb 2018 11:08:07 +0800 Subject: [PATCH 408/427] ASoC: rockchip: rk817-codec: add some functions distinguish MIC input differential or single-ended disable DAC_D_HPF add pdm support Change-Id: Id2befb3f817c9eaf273e1120036cf013db463639 Signed-off-by: Binyuan Lan --- .../bindings/sound/rockchip,rk817-codec.txt | 30 ++++- sound/soc/codecs/rk817_codec.c | 124 ++++++++++++++---- sound/soc/codecs/rk817_codec.h | 48 +++++-- 3 files changed, 163 insertions(+), 39 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt index 95f9430b1757..1831cd671ec4 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt @@ -5,7 +5,29 @@ Required properties: - compatible: "rockchip,rk817-codec" - clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. - clock-names: should be "mclk". - +- spk-volume: DAC L/R volume digital setting for Speaker +- hp-volume: DAC L/R volume digital setting for Headphone + * + * DDAC L/R volume setting + * 0db~-95db,0.375db/step,for example: + * 0: 0dB + * 10: -3.75dB + * 125: -46dB + * 255: -95dB + * +- capture-volume: ADC L/R volume digital setting for Microphone + * + * DADC L/R volume setting + * 0db~-95db,0.375db/step,for example: + * 0: 0dB + * 10: -3.75dB + * 125: -46dB + * 255: -95dB + * +- mic-in-differential: + Boolean. Indicate MIC input are differential, rather than single-ended. +- pdmdata-out-enable: + Boolean. Indicate pdmdata output is enable or disable. Example for rk817 codec: @@ -19,13 +41,17 @@ rk817: pmic@20 { ........ - rk817_codec: rk817-codec { + rk817_codec: codec { #sound-dai-cells = <0>; compatible = "rockchip,rk817-codec"; clocks = <&cru SCLK_I2S_8CH_OUT>; clock-names = "mclk"; pinctrl-names = "default"; pinctrl-0 = <&i2s_8ch_mclk>; + hp-volume = <3>; + spk-volume = <3>; + capture-volume = <0>; + mic-in-differential; status = "okay"; }; diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 2ec16c291c5a..915019ad2a76 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -44,21 +44,21 @@ module_param_named(dbg_level, dbg_enable, int, 0644); /* * DDAC L/R volume setting + * 0db~-95db,0.375db/step,for example: * 0: 0dB - * 0x0a:-3.75dB + * 0x0a: -3.75dB * 0x7d: -46dB * 0xff: -95dB - * Step: 0.375dB */ #define OUT_VOLUME (0x03) /* * DADC L/R volume setting + * 0db~-95db,0.375db/step,for example: * 0: 0dB - * 0x0a:-3.75dB + * 0x0a: -3.75dB * 0x7d: -46dB * 0xff: -95dB - * Step: 0.375dB */ #define CAPTURE_VOLUME (0x0) @@ -75,6 +75,9 @@ struct rk817_codec_priv { unsigned int hp_volume; unsigned int capture_volume; + bool mic_in_differential; + bool pdmdata_out_enable; + long int playback_path; long int capture_path; }; @@ -227,8 +230,8 @@ static struct rk817_reg_val_typ playback_power_up_list[] = { {RK817_CODEC_AREF_RTCFG1, 0x40}, {RK817_CODEC_DDAC_POPD_DACST, 0x02}, {RK817_CODEC_DDAC_SR_LMT0, 0x02}, - /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f},*/ - /*APLL*/ + /* {RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f}, */ + /* APLL */ {RK817_CODEC_APLL_CFG0, 0x04}, {RK817_CODEC_APLL_CFG1, 0x58}, {RK817_CODEC_APLL_CFG2, 0x2d}, @@ -242,6 +245,7 @@ static struct rk817_reg_val_typ playback_power_up_list[] = { {RK817_CODEC_DI2S_RXCR1, 0x00}, {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, {RK817_CODEC_DTOP_VUCTIME, 0xf4}, + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00}, {RK817_CODEC_DDAC_VOLL, 0x0a}, {RK817_CODEC_DDAC_VOLR, 0x0a}, @@ -251,7 +255,7 @@ static struct rk817_reg_val_typ playback_power_up_list[] = { ARRAY_SIZE(playback_power_up_list) static struct rk817_reg_val_typ playback_power_down_list[] = { - {RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa1}, + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x01}, {RK817_CODEC_ADAC_CFG1, 0x0f}, /* HP */ {RK817_CODEC_AHP_CFG0, 0xe0}, @@ -267,7 +271,7 @@ static struct rk817_reg_val_typ capture_power_up_list[] = { {RK817_CODEC_AREF_RTCFG1, 0x40}, {RK817_CODEC_DDAC_SR_LMT0, 0x02}, {RK817_CODEC_DADC_SR_ACL0, 0x02}, - /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0xff},*/ + /* {RK817_CODEC_DTOP_DIGEN_CLKE, 0xff}, */ {RK817_CODEC_APLL_CFG0, 0x04}, {RK817_CODEC_APLL_CFG1, 0x58}, {RK817_CODEC_APLL_CFG2, 0x2d}, @@ -287,7 +291,7 @@ static struct rk817_reg_val_typ capture_power_up_list[] = { {RK817_CODEC_AMIC_CFG0, 0x0f}, {RK817_CODEC_DI2S_TXCR3_TXCMD, 0x88}, {RK817_CODEC_DDAC_POPD_DACST, 0x02}, - /* 0x29: -18db to 27db*/ + /* 0x29: -18db to 27db */ {RK817_CODEC_DMIC_PGA_GAIN, 0xaa}, }; @@ -310,10 +314,10 @@ static int rk817_codec_power_up(int type) codec = rk817->codec; - dev_info(codec->dev, "%s : power up %s %s %s\n", __func__, - type & RK817_CODEC_PLAYBACK ? "playback" : "", - type & RK817_CODEC_CAPTURE ? "capture" : "", - type & RK817_CODEC_INCALL ? "incall" : ""); + DBG("%s : power up %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); if (type & RK817_CODEC_PLAYBACK) { snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, @@ -321,7 +325,6 @@ static int rk817_codec_power_up(int type) for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) { snd_soc_write(codec, playback_power_up_list[i].reg, playback_power_up_list[i].value); - usleep_range(1000, 1100); } } @@ -331,8 +334,19 @@ static int rk817_codec_power_up(int type) for (i = 0; i < RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) { snd_soc_write(codec, capture_power_up_list[i].reg, capture_power_up_list[i].value); - usleep_range(1000, 1100); } + + if (rk817->mic_in_differential) + snd_soc_update_bits(codec, RK817_CODEC_AMIC_CFG0, + MIC_DIFF_MASK, MIC_DIFF_EN); + else + snd_soc_update_bits(codec, RK817_CODEC_AMIC_CFG0, + MIC_DIFF_MASK, MIC_DIFF_DIS); + + if (rk817->pdmdata_out_enable) + snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM, + PDM_EN_MASK, PDM_EN_ENABLE); + snd_soc_write(codec, RK817_CODEC_DADC_VOLL, rk817->capture_volume); snd_soc_write(codec, RK817_CODEC_DADC_VOLR, @@ -350,10 +364,10 @@ static int rk817_codec_power_down(int type) codec = rk817->codec; - dev_info(codec->dev, "%s : power down %s %s %s\n", __func__, - type & RK817_CODEC_PLAYBACK ? "playback" : "", - type & RK817_CODEC_CAPTURE ? "capture" : "", - type & RK817_CODEC_INCALL ? "incall" : ""); + DBG("%s : power down %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); /* mute output for pop noise */ if ((type & RK817_CODEC_PLAYBACK) || @@ -449,7 +463,9 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, switch (rk817->playback_path) { case OFF: - if (pre_path != OFF) + if (pre_path != OFF && (pre_path != HP_PATH && + pre_path != HP_NO_MIC && pre_path != RING_HP && + pre_path != RING_HP_NO_MIC)) rk817_codec_power_down(RK817_CODEC_PLAYBACK); break; case RCV: @@ -457,15 +473,15 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, case RING_SPK: if (pre_path == OFF) rk817_codec_power_up(RK817_CODEC_PLAYBACK); - /* power on dac ibias/l/r*/ + /* power on dac ibias/l/r */ snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, PWD_DACBIAS_ON | PWD_DACD_ON | PWD_DACL_ON | PWD_DACR_ON); - /* CLASS D mode*/ + /* CLASS D mode */ snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); - /* CLASS D enable*/ + /* CLASS D enable */ snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); - /* restart CLASS D, OCPP/N*/ + /* restart CLASS D, OCPP/N */ snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume); @@ -479,9 +495,9 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, rk817_codec_power_up(RK817_CODEC_PLAYBACK); /* HP_CP_EN , CP 2.3V */ snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); - /* power on HP two stage opamp ,HP amplitude 0db*/ + /* power on HP two stage opamp ,HP amplitude 0db */ snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); - /* power on dac ibias/l/r*/ + /* power on dac ibias/l/r */ snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, PWD_DACBIAS_ON | PWD_DACD_DOWN | PWD_DACL_ON | PWD_DACR_ON); @@ -497,6 +513,21 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, case RING_SPK_HP: if (pre_path == OFF) rk817_codec_power_up(RK817_CODEC_PLAYBACK); + /* HP_CP_EN , CP 2.3V */ + snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); + /* power on HP two stage opamp ,HP amplitude 0db */ + snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); + + /* power on dac ibias/l/r */ + snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_ON | PWD_DACD_ON | + PWD_DACL_ON | PWD_DACR_ON); + /* CLASS D mode */ + snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); + /* CLASS D enable */ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); + /* restart CLASS D, OCPP/N */ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); @@ -550,10 +581,26 @@ static int rk817_capture_path_put(struct snd_kcontrol *kcontrol, case MAIN_MIC: if (pre_path == MIC_OFF) rk817_codec_power_up(RK817_CODEC_CAPTURE); + + if (!rk817->mic_in_differential) { + snd_soc_write(codec, RK817_CODEC_DADC_VOLR, 0xff); + snd_soc_update_bits(codec, RK817_CODEC_AADC_CFG0, + ADC_R_PWD_MASK, ADC_R_PWD_EN); + snd_soc_update_bits(codec, RK817_CODEC_AMIC_CFG0, + PWD_PGA_R_MASK, PWD_PGA_R_EN); + } break; case HANDS_FREE_MIC: if (pre_path == MIC_OFF) rk817_codec_power_up(RK817_CODEC_CAPTURE); + + if (!rk817->mic_in_differential) { + snd_soc_write(codec, RK817_CODEC_DADC_VOLL, 0xff); + snd_soc_update_bits(codec, RK817_CODEC_AADC_CFG0, + ADC_L_PWD_MASK, ADC_L_PWD_EN); + snd_soc_update_bits(codec, RK817_CODEC_AMIC_CFG0, + PWD_PGA_L_MASK, PWD_PGA_L_EN); + } break; case BT_SCO_MIC: break; @@ -641,7 +688,16 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, static int rk817_digital_mute(struct snd_soc_dai *dai, int mute) { - DBG("%s immediately return for mid\n", __func__); + struct snd_soc_codec *codec = dai->codec; + + DBG("%s %d\n", __func__, mute); + if (mute) + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_ENABLE); + else + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_DISABLE); + return 0; } @@ -766,9 +822,9 @@ static int rk817_codec_parse_dt_property(struct device *dev, return -ENODEV; } - node = of_get_child_by_name(dev->parent->of_node, "rk817-codec"); + node = of_get_child_by_name(dev->parent->of_node, "codec"); if (!node) { - dev_err(dev, "%s() Can not get child: rk817-codec\n", + dev_err(dev, "%s() Can not get child: codec\n", __func__); return -ENODEV; } @@ -778,6 +834,8 @@ static int rk817_codec_parse_dt_property(struct device *dev, DBG("%s() Can not read property skp-volume\n", __func__); rk817->spk_volume = OUT_VOLUME; } + if (rk817->spk_volume < 3) + rk817->spk_volume = 3; ret = of_property_read_u32(node, "hp-volume", &rk817->hp_volume); @@ -786,6 +844,8 @@ static int rk817_codec_parse_dt_property(struct device *dev, __func__); rk817->hp_volume = OUT_VOLUME; } + if (rk817->hp_volume < 3) + rk817->hp_volume = 3; ret = of_property_read_u32(node, "capture-volume", &rk817->capture_volume); @@ -795,6 +855,12 @@ static int rk817_codec_parse_dt_property(struct device *dev, rk817->capture_volume = CAPTURE_VOLUME; } + rk817->mic_in_differential = + of_property_read_bool(node, "mic-in-differential"); + + rk817->pdmdata_out_enable = + of_property_read_bool(node, "pdmdata-out-enable"); + return 0; } diff --git a/sound/soc/codecs/rk817_codec.h b/sound/soc/codecs/rk817_codec.h index cdf56a087308..7f17cd9b7d2b 100644 --- a/sound/soc/codecs/rk817_codec.h +++ b/sound/soc/codecs/rk817_codec.h @@ -75,7 +75,7 @@ #define RK817_CODEC_DI2S_TXCR2 (RK817_CODEC_BASE + 0x4e) #define RK817_CODEC_DI2S_TXCR3_TXCMD (RK817_CODEC_BASE + 0x4f) -/*RK817_CODEC_DTOP_DIGEN_CLKE*/ +/* RK817_CODEC_DTOP_DIGEN_CLKE */ #define ADC_DIG_CLK_MASK (0xf << 4) #define ADC_DIG_CLK_SFT 4 #define ADC_DIG_CLK_DIS (0x0 << 4) @@ -86,11 +86,16 @@ #define DAC_DIG_CLK_DIS (0x0 << 0) #define DAC_DIG_CLK_EN (0xf << 0) -/*RK817_CODEC_APLL_CFG5*/ +/* RK817_CODEC_APLL_CFG5 */ #define PLL_PW_DOWN (0x01 << 0) #define PLL_PW_UP (0x00 << 0) -/*RK817_CODEC_DI2S_CKM*/ +/* RK817_CODEC_DI2S_CKM */ +#define PDM_EN_MASK (0x1 << 3) +#define PDM_EN_SFT 3 +#define PDM_EN_DISABLE (0x0 << 3) +#define PDM_EN_ENABLE (0x1 << 3) + #define SCK_EN_ENABLE (0x1 << 2) #define SCK_EN_DISABLE (0x0 << 2) @@ -99,22 +104,22 @@ #define RK817_I2S_MODE_MST (0x1 << 0) #define RK817_I2S_MODE_SLV (0x0 << 0) -/*RK817_CODEC_DDAC_MUTE_MIXCTL*/ +/* RK817_CODEC_DDAC_MUTE_MIXCTL */ #define DACMT_ENABLE (0x1 << 0) #define DACMT_DISABLE (0x0 << 0) -/*RK817_CODEC_DI2S_RXCR2*/ +/* RK817_CODEC_DI2S_RXCR2 */ #define VDW_RX_24BITS (0x17) #define VDW_RX_16BITS (0x0f) -/*RK817_CODEC_DI2S_TXCR2*/ +/* RK817_CODEC_DI2S_TXCR2 */ #define VDW_TX_24BITS (0x17) #define VDW_TX_16BITS (0x0f) -/*RK817_CODEC_AHP_CFG1*/ +/* RK817_CODEC_AHP_CFG1 */ #define HP_ANTIPOP_ENABLE (0x1 << 4) #define HP_ANTIPOP_DISABLE (0x0 << 4) -/*RK817_CODEC_ADAC_CFG1*/ +/* RK817_CODEC_ADAC_CFG1 */ #define PWD_DACBIAS_MASK (0x1 << 3) #define PWD_DACBIAS_SFT 3 #define PWD_DACBIAS_DOWN (0x1 << 3) @@ -135,6 +140,33 @@ #define PWD_DACR_DOWN (0x1 << 0) #define PWD_DACR_ON (0x0 << 0) +/* RK817_CODEC_AADC_CFG0 */ +#define ADC_L_PWD_MASK (0x1 << 7) +#define ADC_L_PWD_SFT 7 +#define ADC_L_PWD_DIS (0x0 << 7) +#define ADC_L_PWD_EN (0x1 << 7) + +#define ADC_R_PWD_MASK (0x1 << 6) +#define ADC_R_PWD_SFT 6 +#define ADC_R_PWD_DIS (0x0 << 6) +#define ADC_R_PWD_EN (0x1 << 6) + +/* RK817_CODEC_AMIC_CFG0 */ +#define MIC_DIFF_MASK (0x1 << 7) +#define MIC_DIFF_SFT 7 +#define MIC_DIFF_DIS (0x0 << 7) +#define MIC_DIFF_EN (0x1 << 7) + +#define PWD_PGA_L_MASK (0x1 << 5) +#define PWD_PGA_L_SFT 5 +#define PWD_PGA_L_DIS (0x0 << 5) +#define PWD_PGA_L_EN (0x1 << 5) + +#define PWD_PGA_R_MASK (0x1 << 4) +#define PWD_PGA_R_SFT 4 +#define PWD_PGA_R_DIS (0x0 << 4) +#define PWD_PGA_R_EN (0x1 << 4) + enum { RK817_HIFI, RK817_VOICE, From be138b5dc666240d7d69a661a37764e36f4e1eac Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sat, 10 Feb 2018 16:43:00 +0800 Subject: [PATCH 409/427] arm64: dts: rockchip: set hp/spk volume for 3326 Change-Id: If466d0cacc5c9247c1858775508a410943d78ce2 Signed-off-by: Binyuan Lan --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 5 ++++- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index 60b63a7ad8b3..a281d7ba418d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -485,13 +485,16 @@ extcon = <&u2phy>; }; - rk817_codec: rk817-codec { + rk817_codec: codec { #sound-dai-cells = <0>; compatible = "rockchip,rk817-codec"; clocks = <&cru SCLK_I2S1_OUT>; clock-names = "mclk"; pinctrl-names = "default"; pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; + mic-in-differential; status = "okay"; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index bbae0dd14e71..4eca86b5aaa3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -579,13 +579,15 @@ extcon = <&u2phy>; }; - rk817_codec: rk817-codec { + rk817_codec: codec { #sound-dai-cells = <0>; compatible = "rockchip,rk817-codec"; clocks = <&cru SCLK_I2S1_OUT>; clock-names = "mclk"; pinctrl-names = "default"; pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; status = "okay"; }; }; From 31328fc2b3f315d4bbc72b4d883b108b764db52f Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sat, 3 Feb 2018 00:59:30 +0800 Subject: [PATCH 410/427] arm64: dts: rockchip: add rk809 codec for px30 Change-Id: Icdc8f3694fc2dc962b779173d1e25d6a0bf5a57e Signed-off-by: Binyuan Lan --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 38 +++++++++++++++++++ .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 38 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 46eb2248afa2..52877cbbef2d 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -94,6 +94,27 @@ default-brightness-level = <200>; }; + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,rk809-codec"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Mic Jack", "MICBIAS1", + "IN1P", "Mic Jack", + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR"; + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk809_codec>; + }; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk809 1>;*/ @@ -496,6 +517,18 @@ regulator-name = "vcc5v0_host"; }; }; + + rk809_codec: codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk809-codec", "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; + status = "okay"; + }; }; }; @@ -533,6 +566,11 @@ }; }; +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + &io_domains { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 12cb22de3640..bd91bba06c82 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -94,6 +94,27 @@ default-brightness-level = <200>; }; + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,rk809-codec"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Mic Jack", "MICBIAS1", + "IN1P", "Mic Jack", + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR"; + simple-audio-card,cpu { + sound-dai = <&i2s1_2ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk809_codec>; + }; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk809 1>;*/ @@ -497,6 +518,18 @@ regulator-name = "vcc5v0_host"; }; }; + + rk809_codec: codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk809-codec", "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; + status = "okay"; + }; }; }; @@ -543,6 +576,11 @@ vccio5-supply = <&vcc_3v0>; }; +&i2s1_2ch { + status = "okay"; + #sound-dai-cells = <0>; +}; + &mipi_dphy { status = "okay"; }; From cbac12bed5bbc9ef2fcfe0acf88f112090433301 Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sat, 3 Feb 2018 11:48:54 +0800 Subject: [PATCH 411/427] arm64: dts: rockchip: add headset detect for px30 Change-Id: I640389607f7ef7be4e966b78afefcb9052b83214 Signed-off-by: Binyuan Lan --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 16 +++++++++++++++- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 52877cbbef2d..c12b5bca62ef 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -115,6 +115,14 @@ }; }; + rk_headset { + compatible = "rockchip_headset"; + headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + io-channels = <&saradc 1>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk809 1>;*/ @@ -590,10 +598,16 @@ }; &pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + pmic { pmic_int: pmic_int { rockchip,pins = - <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index bd91bba06c82..b9f2c9e30108 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -115,6 +115,14 @@ }; }; + rk_headset { + compatible = "rockchip_headset"; + headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + io-channels = <&saradc 1>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; /*clocks = <&rk809 1>;*/ @@ -590,10 +598,16 @@ }; &pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + pmic { pmic_int: pmic_int { rockchip,pins = - <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; }; }; From fa89f964b5c28df7bd7097f12f9c41e4b4260603 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 23 Feb 2018 11:27:22 +0800 Subject: [PATCH 412/427] power: rk817: add pr_fmt() macro Make the printks look a bit nicer by adding a prefix. Change-Id: Id268a55a1681c6805e7c3f5929350891e92df816 Signed-off-by: Tao Huang --- drivers/power/rk817_battery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/rk817_battery.c b/drivers/power/rk817_battery.c index ab3ef6a2599c..1c4d00d07359 100644 --- a/drivers/power/rk817_battery.c +++ b/drivers/power/rk817_battery.c @@ -15,6 +15,8 @@ * */ +#define pr_fmt(fmt) "rk817-bat: " fmt + #include #include #include @@ -48,7 +50,7 @@ module_param_named(dbg_level, dbg_enable, int, 0644); } \ } while (0) -#define BAT_INFO(fmt, args...) pr_info("rk817-bat: "fmt, ##args) +#define BAT_INFO(fmt, args...) pr_info(fmt, ##args) #define DRIVER_VERSION "1.00" #define SFT_SET_KB 1 From 76c2aced00b4fe3a750268f21d7a23a196b164d0 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 8 Feb 2018 21:24:28 +0800 Subject: [PATCH 413/427] arm64: dts: rockchip: rk3328: Avoid showing blurred screen If show logo in uboot, can't change vop clocks. Change-Id: Ia149b452e16dedcafaa15bfa5d5dc989b06737ff Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index cfb645b45dd9..c7316fdd582f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -1075,8 +1075,7 @@ <&cru SCLK_RTC32K>, <&cru SCLK_UART0>, <&cru SCLK_UART1>, <&cru SCLK_UART2>, <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, - <&cru ACLK_VIO_PRE>, <&cru ACLK_RGA_PRE>, - <&cru ACLK_VOP_PRE>, <&cru ACLK_RKVDEC_PRE>, + <&cru ACLK_RGA_PRE>, <&cru ACLK_RKVDEC_PRE>, <&cru ACLK_RKVENC>, <&cru ACLK_VPU_PRE>, <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>, <&cru SCLK_VENC_CORE>, <&cru SCLK_VENC_DSP>, @@ -1105,7 +1104,6 @@ <24000000>, <24000000>, <15000000>, <15000000>, <100000000>, <100000000>, - <100000000>, <100000000>, <50000000>, <100000000>, <100000000>, <100000000>, <50000000>, <50000000>, From 87d7e43c428bcc0c1bd36365cd53e4f7a8cf4e93 Mon Sep 17 00:00:00 2001 From: Jung Zhao Date: Sat, 24 Feb 2018 09:10:45 +0800 Subject: [PATCH 414/427] video: rockchip: vpu: fix shutdown crash bug now shutdown function just wait for vpu finishing his work, and do nothing else. Change-Id: I54f227768314edd85154705d07054bd493e350aa Signed-off-by: Jung Zhao --- .../video/rockchip/vcodec/vcodec_service.c | 40 ++----------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c index f30777925b03..9236c5e93215 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c @@ -769,24 +769,6 @@ static void vpu_service_session_clear(struct vpu_subdev_data *data, } } -static void vpu_service_clear(struct vpu_subdev_data *data) -{ - struct vpu_reg *reg, *n; - struct vpu_session *session, *s; - struct vpu_service_info *pservice = data->pservice; - - list_for_each_entry_safe(reg, n, &pservice->waiting, status_link) { - reg_deinit(reg->data, reg); - } - - /* wake up session wait event to prevent the timeout hw reset - * during reboot procedure. - */ - list_for_each_entry_safe(session, s, - &pservice->session, list_session) - wake_up(&session->wait); -} - #if VCODEC_CLOCK_ENABLE static void set_div_clk(struct clk *clock, int divide) { @@ -3503,13 +3485,15 @@ static void vcodec_shutdown(struct platform_device *pdev) { struct vpu_subdev_data *data = platform_get_drvdata(pdev); struct vpu_service_info *pservice = data->pservice; - struct device_node *np = pdev->dev.of_node; int val; int ret; - int i; dev_info(&pdev->dev, "vcodec shutdown"); + /* + * just wait for hardware finishing his work + * and do nothing else. + */ mutex_lock(&pservice->shutdown_lock); atomic_set(&pservice->service_on, 0); mutex_unlock(&pservice->shutdown_lock); @@ -3521,22 +3505,6 @@ static void vcodec_shutdown(struct platform_device *pdev) dev_err(&pdev->dev, "wait total running time out\n"); data->pservice->curr_mode = VCODEC_RUNNING_MODE_NONE; - vpu_service_clear(data); - if (of_property_read_bool(np, "subcnt")) { - for (i = 0; i < pservice->subcnt; i++) { - struct device_node *sub_np; - struct platform_device *sub_pdev; - - sub_np = of_parse_phandle(np, "rockchip,sub", i); - sub_pdev = of_find_device_by_node(sub_np); - vcodec_subdev_remove(platform_get_drvdata(sub_pdev)); - } - - } else { - vcodec_subdev_remove(data); - } - - pm_runtime_disable(&pdev->dev); } MODULE_DEVICE_TABLE(of, vcodec_service_dt_ids); From 7b2618e5e614156e5fff2a9975733ecd046eb707 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Fri, 23 Feb 2018 17:15:28 +0800 Subject: [PATCH 415/427] phy: rockchip: inno-hdmi: manual power down RK3328 post-PLL with no uboot logo For 3328, inno hdmi phy post pll is enabled by default, it's need to manual power down post pll if uboot logo is not shown. Change-Id: Ia175ff0aad006be950b8bc13e1cf2ecb4f00e04c Signed-off-by: Zheng Yang --- .../phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c index f8f48b9b04ab..ca50c8f58c50 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c @@ -726,25 +726,6 @@ inno_hdmi_phy_rk3228_pre_pll_update(struct inno_hdmi_phy *inno, return 0; } -static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) -{ - /* - * Use phy internal register control - * rxsense/poweron/pllpd/pdataen signal. - */ - inno_write(inno, 0x01, 0x07); - inno_write(inno, 0x02, 0x91); - - /* - * reg0xc8 default value is 0xc0, if phy had been set in uboot, - * the value of bit[7:6] will be zero. - */ - if ((inno_read(inno, 0xc8) & 0xc0) == 0) { - dev_info(inno->dev, "phy had been powered up\n"); - inno->phy->power_count = 1; - } -} - static int inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, const struct post_pll_config *cfg, @@ -838,6 +819,28 @@ static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno) inno_update_bits(inno, 0xaa, 1, 1); } +static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) +{ + /* + * Use phy internal register control + * rxsense/poweron/pllpd/pdataen signal. + */ + inno_write(inno, 0x01, 0x07); + inno_write(inno, 0x02, 0x91); + + /* + * reg0xc8 default value is 0xc0, if phy had been set in uboot, + * the value of bit[7:6] will be zero. + */ + if ((inno_read(inno, 0xc8) & 0xc0) == 0) { + dev_info(inno->dev, "phy had been powered up\n"); + inno->phy->power_count = 1; + } else { + /* manual power down post-PLL */ + inno_hdmi_phy_rk3328_power_off(inno); + } +} + static int inno_hdmi_phy_rk3328_pre_pll_update(struct inno_hdmi_phy *inno, const struct pre_pll_config *cfg) From 1097ca8f2c51726c67ad4df56cc39ce89490ff8c Mon Sep 17 00:00:00 2001 From: Xinhuang Li Date: Mon, 5 Feb 2018 11:11:54 +0800 Subject: [PATCH 416/427] ARM: dts: rockchip: rk3229-evb-android: enable iep&iep_mmu Change-Id: Id1f4bd5726a5d15e977a11b83c1849cef80de47b Signed-off-by: Xinhuang Li --- arch/arm/boot/dts/rk3229-evb-android.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/rk3229-evb-android.dts b/arch/arm/boot/dts/rk3229-evb-android.dts index dab8caec98f9..19174ef8aec2 100644 --- a/arch/arm/boot/dts/rk3229-evb-android.dts +++ b/arch/arm/boot/dts/rk3229-evb-android.dts @@ -236,6 +236,14 @@ #sound-dai-cells = <0>; }; +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + &pinctrl { keys { pwr_key: pwr-key { From 55f42a9aed64f18d3dc52b77ec7d5123a9c985f6 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Sun, 11 Feb 2018 15:31:38 +0800 Subject: [PATCH 417/427] arm64: dts: rockchip: the boost and otg may be disabed for rk3326 board Change-Id: I3a320614d13fe87156e8f85815a5eb89157a3c1f Signed-off-by: shengfei Xu --- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 1 - arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index a281d7ba418d..ebbf0e3ebd6d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -447,7 +447,6 @@ }; otg_switch: OTG_SWITCH { - regulator-always-on; regulator-boot-on; regulator-name = "otg_switch"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 4eca86b5aaa3..38840d7c4d75 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -541,7 +541,6 @@ }; otg_switch: OTG_SWITCH { - regulator-always-on; regulator-boot-on; regulator-name = "otg_switch"; }; From 87dbd10b5f2b5481454ea4e29e240ac1a2d848a3 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Sun, 11 Feb 2018 19:08:34 +0800 Subject: [PATCH 418/427] power: rk817: fix the OTG mode judgement Change-Id: I23ecea8b26aa2aff0101bb5237fe89ad2b00fb9c Signed-off-by: shengfei Xu --- drivers/power/rk817_charger.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/rk817_charger.c b/drivers/power/rk817_charger.c index 2378f5b449be..cc250925d5f4 100644 --- a/drivers/power/rk817_charger.c +++ b/drivers/power/rk817_charger.c @@ -52,6 +52,8 @@ module_param_named(dbg_level, dbg_enable, int, 0644); #define OTG_SLP_DISABLE 0x00 #define OTG_ENABLE 0x33 #define OTG_DISABLE 0x30 +#define OTG_MODE 0x03 +#define OTG_MODE_ON 0x03 #define DEFAULT_INPUT_VOLTAGE 4500 #define DEFAULT_INPUT_CURRENT 2000 #define DEFAULT_CHRG_VOLTAGE 4200 @@ -500,7 +502,8 @@ static int rk817_charge_field_write(struct rk817_charger *charge, static int rk817_charge_get_otg_state(struct rk817_charger *charge) { - return (rk817_charge_field_read(charge, OTG_EN) & 0x03); + return ((rk817_charge_field_read(charge, OTG_EN) & + OTG_MODE) == OTG_MODE_ON); } static void rk817_charge_otg_disable(struct rk817_charger *charge) From b0104476f8f6b20bad18ae8be23530ecac01f3fe Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Sun, 11 Feb 2018 16:13:11 +0800 Subject: [PATCH 419/427] arm64: dts: rockchip: rk3326/px30: add pmic pwrkey node pwrkey node is necessary for U-Boot RK817/RK809 pwrkey driver, because the device-driver model requires it to make a match. Change-Id: Ica766232646ba93508592ab1a20b65157859d688 Signed-off-by: Joseph Chen --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 4 ++++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index c12b5bca62ef..e50293c7dbfa 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -332,6 +332,10 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; + pwrkey { + status = "okay"; + }; + regulators { vdd_logic: DCDC_REG1 { regulator-always-on; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index b9f2c9e30108..dd855d95b450 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -332,6 +332,10 @@ vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; + pwrkey { + status = "okay"; + }; + regulators { vdd_logic: DCDC_REG1 { regulator-always-on; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index ebbf0e3ebd6d..fd94f077ac56 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -268,6 +268,10 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; + pwrkey { + status = "okay"; + }; + regulators { vdd_logic: DCDC_REG1 { regulator-always-on; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 38840d7c4d75..b7baa49c7ae8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -362,6 +362,10 @@ vcc8-supply = <&vccsys>; vcc9-supply = <&dcdc_boost>; + pwrkey { + status = "okay"; + }; + regulators { vdd_logic: DCDC_REG1 { regulator-always-on; From 84dd6061e3b8ed63fefd1d48c28b349413946523 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 23 Feb 2018 09:29:37 +0800 Subject: [PATCH 420/427] arm64: dts: rockchip: add px30-evb lvds board support Change-Id: I50b587f592d88d704c4843db428c5e847eb484cb Signed-off-by: Wyon Bi --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../dts/rockchip/px30-evb-ddr3-lvds-v10.dts | 626 ++++++++++++++++++ 2 files changed, 627 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/px30-evb-ddr3-lvds-v10.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 2ad38b3c0917..b464ee609d26 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-lvds-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-863-lp3-v10.dtb diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-lvds-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-lvds-v10.dts new file mode 100644 index 000000000000..a7fdd6ef6914 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-lvds-v10.dts @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +/dts-v1/; +#include +#include +#include +#include +#include "px30.dtsi" +#include "px30-android.dtsi" + +/ { + model = "Rockchip PX30 evb ddr3 lvds board"; + compatible = "rockchip,px30-evb-ddr3-lvds-v10", "rockchip,px30"; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + poll-interval = <100>; + keyup-threshold-microvolt = <1800000>; + + esc-key { + linux,code = ; + label = "esc"; + press-threshold-microvolt = <1270000>; + }; + + home-key { + linux,code = ; + label = "home"; + press-threshold-microvolt = <602000>; + }; + + menu-key { + linux,code = ; + label = "menu"; + press-threshold-microvolt = <952000>; + }; + + vol-down-key { + linux,code = ; + label = "volume down"; + press-threshold-microvolt = <290000>; + }; + + vol-up-key { + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <17000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + }; + + panel { + compatible = "samsung,lsl070nl01", "simple-panel"; + backlight = <&backlight>; + power-supply = <&vcc3v3_lcd>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + + width-mm = <217>; + height-mm = <136>; + + rockchip,data-mapping = "vesa"; + rockchip,data-width = <24>; + rockchip,output = "lvds"; + + display-timings { + native-mode = <&timing0>; + + timing0: timing0 { + clock-frequency = <49500000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <90>; + hfront-porch = <90>; + vback-porch = <10>; + vfront-porch = <10>; + hsync-len = <90>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + port { + panel_in_lvds: endpoint { + remote-endpoint = <&lvds_out_panel>; + }; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + /*clocks = <&rk809 1>;*/ + /*clock-names = "ext_clock";*/ + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc5v0_sys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + wifi_chip_type = "AP6210"; + WIFI,host_wake_irq = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + /*clocks = <&rk809 1>;*/ + /*clock-names = "ext_clock";*/ + uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; + pinctrl-names = "default","rts_gpio"; + pinctrl-0 = <&uart1_rts>; + pinctrl-1 = <&uart1_rts_gpio>; + BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&display_subsystem { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + supports-emmc; + disable-wp; + non-removable; + num-slots = <1>; + status = "okay"; +}; + +&gmac { + phy-supply = <&vcc_phy>; + clock_in_out = "output"; + snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 50000 50000>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_logic>; + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; + regulator-name = "vcc_3v0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc2v5_ddr: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc2v5_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vcc1v8_soc: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v0_soc: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-name = "vcc1v0_soc"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-name = "vcc3v0_pmu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-name = "vcc_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-name = "vcc2v8_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-name = "vcc1v8_dvp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd1v5_dvp: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-name = "vdd1v5_dvp"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcc3v3_sys: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v3_lcd: SWITCH_REG1 { + regulator-boot-on; + regulator-name = "vcc3v3_lcd"; + }; + + vcc5v0_host: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_host"; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + + sensor@0f { + status = "okay"; + compatible = "ak8963"; + reg = <0x0f>; + type = ; + irq_enable = <0>; + poll_delay_ms = <30>; + layout = <1>; + reprobe_en = <1>; + }; + + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; + }; + + sensor@4c { + status = "okay"; + compatible = "gs_mma7660"; + reg = <0x4c>; + type = ; + irq-gpio = <&gpio0 RK_PB7 IRQ_TYPE_LEVEL_LOW>; + irq_enable = <0>; + poll_delay_ms = <30>; + layout = <2>; + reprobe_en = <1>; + }; +}; + +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc1v8_soc>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc3v0_pmu>; + vccio5-supply = <&vcc_3v0>; +}; + +&lvds { + status = "okay"; + + ports { + port@1 { + reg = <1>; + + lvds_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds>; + }; + }; + }; +}; + +&lvds_in_vopl { + status = "disabled"; +}; + +&route_lvds { + status = "okay"; +}; + +&nandc0 { + status = "okay"; +}; + +&pinctrl { + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + status = "okay"; + + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; +}; + +&pwm1 { + status = "okay"; +}; + +&rk_rga { + status = "okay"; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc1v8_soc>; +}; + +&sdmmc { + cap-mmc-highspeed; + supports-sd; + broken-cd; + card-detect-delay = <800>; + ignore-pm-notify; + keep-power-in-suspend; + /*cd-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; [> CD GPIO <]*/ + status = "disabled"; +}; + +&sdio { + max-frequency = <50000000>; + cap-sd-highspeed; + supports-sdio; + ignore-pm-notify; + keep-power-in-suspend; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts>; + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + +&vpu_combo { + status = "okay"; +}; From 72a3380985aa172ef4b1080a040237f5f9db7ebf Mon Sep 17 00:00:00 2001 From: Longjian Lin Date: Sun, 11 Feb 2018 03:23:23 -0500 Subject: [PATCH 421/427] arm64: dts: rockchip: add bluetooth clk control on rk3326-evb-lp3-v10 Change-Id: I745d4f9b80e0d6cb70844b0508931f394b7f5b8d Signed-off-by: Longjian Lin --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index b7baa49c7ae8..2461c44a8253 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -200,8 +200,8 @@ wireless-bluetooth { compatible = "bluetooth-platdata"; - /*clocks = <&rk817 1>;*/ - /*clock-names = "ext_clock";*/ + clocks = <&rk817 1>; + clock-names = "ext_clock"; uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; pinctrl-names = "default","rts_gpio"; pinctrl-0 = <&uart1_rts>; From 807a02af274894d7baebc8bbe2bef57d2d126935 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 24 Feb 2018 09:27:22 +0800 Subject: [PATCH 422/427] ethernet: stmmac: dwmac-rk: Add speed setting for gmac controller of px30 Need to setup the speed setting for 10/100, otherwise the gmac can't work. Change-Id: I92a410b7b453e145fecc817841eecc54afca4051 Signed-off-by: David Wu --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index a5cb21f5baf4..ad1a1d462401 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -89,6 +89,8 @@ struct rk_priv_data { /* PX30_GRF_GMAC_CON1 */ #define PX30_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | \ GRF_BIT(6)) +#define PX30_GMAC_SPEED_10M GRF_CLR_BIT(2) +#define PX30_GMAC_SPEED_100M GRF_BIT(2) static void px30_set_to_rmii(struct rk_priv_data *bsp_priv) { @@ -114,11 +116,17 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) } if (speed == 10) { + regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, + PX30_GMAC_SPEED_10M); + ret = clk_set_rate(bsp_priv->clk_mac_speed, 2500000); if (ret) dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n", __func__, ret); } else if (speed == 100) { + regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, + PX30_GMAC_SPEED_100M); + ret = clk_set_rate(bsp_priv->clk_mac_speed, 25000000); if (ret) dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n", From d23333f9d6cdc6d9942e38470dbd12aa510134f1 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 24 Feb 2018 09:20:36 +0800 Subject: [PATCH 423/427] arm64: dts: rockchip: Make adc key detected value more accurately for rk3326/px30 board Change-Id: Ibcc08001789478d714628fdec10024e6254daa74 Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 8 ++++---- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 8 ++++---- arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts | 2 +- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index e50293c7dbfa..50f2abaf32c9 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -27,25 +27,25 @@ esc-key { linux,code = ; label = "esc"; - press-threshold-microvolt = <1270000>; + press-threshold-microvolt = <1310000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <602000>; + press-threshold-microvolt = <624000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <952000>; + press-threshold-microvolt = <987000>; }; vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <290000>; + press-threshold-microvolt = <300000>; }; vol-up-key { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index dd855d95b450..4a074618a113 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -27,25 +27,25 @@ esc-key { linux,code = ; label = "esc"; - press-threshold-microvolt = <1270000>; + press-threshold-microvolt = <1310000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <602000>; + press-threshold-microvolt = <624000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <952000>; + press-threshold-microvolt = <987000>; }; vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <290000>; + press-threshold-microvolt = <300000>; }; vol-up-key { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts index fd94f077ac56..aea2bf7a0c3f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dts @@ -28,7 +28,7 @@ vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <290000>; + press-threshold-microvolt = <300000>; }; vol-up-key { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 2461c44a8253..87f743b2a790 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -28,25 +28,25 @@ esc-key { linux,code = ; label = "esc"; - press-threshold-microvolt = <1270000>; + press-threshold-microvolt = <1310000>; }; home-key { linux,code = ; label = "home"; - press-threshold-microvolt = <602000>; + press-threshold-microvolt = <624000>; }; menu-key { linux,code = ; label = "menu"; - press-threshold-microvolt = <952000>; + press-threshold-microvolt = <987000>; }; vol-down-key { linux,code = ; label = "volume down"; - press-threshold-microvolt = <290000>; + press-threshold-microvolt = <300000>; }; vol-up-key { From 52acfab66d8a5ed75f9e6af3cd4dc5db59ee8b91 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 24 Feb 2018 09:35:01 +0800 Subject: [PATCH 424/427] arm64: dts: rockchip: Add gmac_clkin fixed clock for gmac usage for px30 Change-Id: Ibb155666235c609603e0a89316398c3aeb303805 Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/px30.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 0188fd40bf58..4ce888c7a564 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -133,6 +133,13 @@ }; }; + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <50000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; From 5060d58965aa9df8ffdce0759805cf3125c69abb Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 23 Feb 2018 14:58:01 +0800 Subject: [PATCH 425/427] arm64: dts: rockchip: Fix the RMII REF_CLK with input mode for px30-evb Base on the evb board, the mode of RMII REF_CLK need to be setup for input. Change-Id: I06220d3422835a456b5567d7797a008d313e185a Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 4 +++- arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 50f2abaf32c9..16c93271a681 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -295,7 +295,9 @@ &gmac { phy-supply = <&vcc_phy>; - clock_in_out = "output"; + assigned-clocks = <&cru SCLK_GMAC>; + assigned-clock-parents = <&gmac_clkin>; + clock_in_out = "input"; snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 50000 50000>; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index 4a074618a113..117da295f0fb 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -295,7 +295,9 @@ &gmac { phy-supply = <&vcc_phy>; - clock_in_out = "output"; + assigned-clocks = <&cru SCLK_GMAC>; + assigned-clock-parents = <&gmac_clkin>; + clock_in_out = "input"; snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 50000 50000>; From ddc05360bd41c65efd8f86e5ef3a129f6c64c7ef Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Sat, 24 Feb 2018 11:49:41 +0800 Subject: [PATCH 426/427] media: soc_camera/rockchip: Fix the build error As enable the releated config, hit the below error: drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c:937:34: error: assignment to expression with array type timings->exposure_valid_frame = ... and drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c:963:34: error: assignment to expression with array type timings->exposure_valid_frame = .... Change-Id: I4381cc8aa00bb6a968c01d7537a8942b5715fa5c Signed-off-by: Caesar Wang --- drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c | 2 +- drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c index f6f08c9d7978..cbc9a7d4d3bd 100644 --- a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c @@ -934,7 +934,7 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd, adv_timings.fine_integration_time_min; if (cam_mod->custom.g_exposure_valid_frame) - timings->exposure_valid_frame = + timings->exposure_valid_frame[0] = cam_mod->custom.g_exposure_valid_frame(cam_mod); if (cam_mod->exp_config.exp_time) timings->exp_time = cam_mod->exp_config.exp_time; diff --git a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c index 50b02c10a4c1..f862b6799591 100644 --- a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c @@ -960,7 +960,7 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd, tc_timings.fine_integration_time_min; if (cam_mod->custom.g_exposure_valid_frame) - timings->exposure_valid_frame = + timings->exposure_valid_frame[0] = cam_mod->custom.g_exposure_valid_frame(cam_mod); if (cam_mod->exp_config.exp_time) timings->exp_time = cam_mod->exp_config.exp_time; From eae92ae2b930999857df47c3057327c1c490454b Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Mon, 5 Feb 2018 17:33:28 +0800 Subject: [PATCH 427/427] media: rockchip: rga: add userptr to use normal cache-enabled memory It seems people still need it Change-Id: I4aa312b46f795beeb3eff415a971d13e81f030f8 Signed-off-by: Jacob Chen --- drivers/media/platform/rockchip/rga/rga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index af6b09529028..dc1d099551b7 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -122,7 +122,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->ops = &rga_qops; src_vq->mem_ops = &vb2_dma_sg_memops; @@ -135,7 +135,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->ops = &rga_qops; dst_vq->mem_ops = &vb2_dma_sg_memops;