linux_5.10: weekly rls 2024.07.20
-142736, Sync spacc driver code. -2303c6, add suspend to ram featrue. -d3bff8, support pdm mic using AEC. -203610, support new spinand flash:HYF1GQ4UDACAE. Change-Id: Iec21bccaee43c4a71213b42b88f41a45527fd8a5
This commit is contained in:
committed by
carbon
parent
2330e10fa0
commit
50fd0630f7
@ -41,6 +41,7 @@ config RISCV
|
|||||||
select CLINT_TIMER if !MMU
|
select CLINT_TIMER if !MMU
|
||||||
select COMMON_CLK
|
select COMMON_CLK
|
||||||
select COMPAT_BINFMT_ELF if BINFMT_ELF && COMPAT
|
select COMPAT_BINFMT_ELF if BINFMT_ELF && COMPAT
|
||||||
|
select CPU_PM if SUSPEND
|
||||||
select EDAC_SUPPORT
|
select EDAC_SUPPORT
|
||||||
select DMA_DIRECT_REMAP
|
select DMA_DIRECT_REMAP
|
||||||
select GENERIC_ALLOCATOR
|
select GENERIC_ALLOCATOR
|
||||||
@ -517,6 +518,11 @@ config BUILTIN_DTB
|
|||||||
depends on RISCV_M_MODE
|
depends on RISCV_M_MODE
|
||||||
depends on OF
|
depends on OF
|
||||||
|
|
||||||
|
config ARCH_SUSPEND_POSSIBLE
|
||||||
|
def_bool y
|
||||||
|
help
|
||||||
|
Enable riscv deep sleep to RAM
|
||||||
|
|
||||||
menu "Power management options"
|
menu "Power management options"
|
||||||
|
|
||||||
source "kernel/power/Kconfig"
|
source "kernel/power/Kconfig"
|
||||||
|
|||||||
@ -66,4 +66,23 @@
|
|||||||
#error "Unexpected __SIZEOF_SHORT__"
|
#error "Unexpected __SIZEOF_SHORT__"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
|
||||||
|
/* Common assembly source macros */
|
||||||
|
|
||||||
|
#ifdef CONFIG_XIP_KERNEL
|
||||||
|
//TODO
|
||||||
|
.macro XIP_FIXUP_OFFSET reg
|
||||||
|
.endm
|
||||||
|
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||||
|
.endm
|
||||||
|
#else
|
||||||
|
.macro XIP_FIXUP_OFFSET reg
|
||||||
|
.endm
|
||||||
|
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||||
|
.endm
|
||||||
|
#endif /* CONFIG_XIP_KERNEL */
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_ASM_H */
|
#endif /* _ASM_RISCV_ASM_H */
|
||||||
|
|||||||
@ -27,6 +27,7 @@ enum sbi_ext_id {
|
|||||||
SBI_EXT_IPI = 0x735049,
|
SBI_EXT_IPI = 0x735049,
|
||||||
SBI_EXT_RFENCE = 0x52464E43,
|
SBI_EXT_RFENCE = 0x52464E43,
|
||||||
SBI_EXT_HSM = 0x48534D,
|
SBI_EXT_HSM = 0x48534D,
|
||||||
|
SBI_EXT_SUSP = 0x53555350,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sbi_ext_base_fid {
|
enum sbi_ext_base_fid {
|
||||||
@ -73,6 +74,14 @@ enum sbi_hsm_hart_status {
|
|||||||
SBI_HSM_HART_STATUS_STOP_PENDING,
|
SBI_HSM_HART_STATUS_STOP_PENDING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sbi_ext_susp_fid {
|
||||||
|
SBI_EXT_SUSP_SYSTEM_SUSPEND = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_ext_susp_sleep_type {
|
||||||
|
SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM = 0,
|
||||||
|
};
|
||||||
|
|
||||||
#define SBI_SPEC_VERSION_DEFAULT 0x1
|
#define SBI_SPEC_VERSION_DEFAULT 0x1
|
||||||
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
|
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
|
||||||
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
|
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
|
||||||
|
|||||||
40
linux_5.10/arch/riscv/include/asm/suspend.h
Normal file
40
linux_5.10/arch/riscv/include/asm/suspend.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||||
|
* Copyright (c) 2022 Ventana Micro Systems Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_RISCV_SUSPEND_H
|
||||||
|
#define _ASM_RISCV_SUSPEND_H
|
||||||
|
|
||||||
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
|
struct suspend_context {
|
||||||
|
/* Saved and restored by low-level functions */
|
||||||
|
struct pt_regs regs;
|
||||||
|
/* Saved and restored by high-level functions */
|
||||||
|
unsigned long scratch;
|
||||||
|
unsigned long tvec;
|
||||||
|
unsigned long ie;
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
unsigned long satp;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Low-level CPU suspend entry function */
|
||||||
|
int __cpu_suspend_enter(struct suspend_context *context);
|
||||||
|
|
||||||
|
/* High-level CPU suspend which will save context and call finish() */
|
||||||
|
int cpu_suspend(unsigned long arg,
|
||||||
|
int (*finish)(unsigned long arg,
|
||||||
|
unsigned long entry,
|
||||||
|
unsigned long context));
|
||||||
|
|
||||||
|
/* Low-level CPU resume entry function */
|
||||||
|
int __cpu_resume_enter(unsigned long hartid, unsigned long context);
|
||||||
|
|
||||||
|
/* Used to save and restore the CSRs */
|
||||||
|
void suspend_save_csrs(struct suspend_context *context);
|
||||||
|
void suspend_restore_csrs(struct suspend_context *context);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -44,6 +44,8 @@ obj-$(CONFIG_SMP) += cpu_ops_spinwait.o
|
|||||||
obj-$(CONFIG_MODULES) += module.o
|
obj-$(CONFIG_MODULES) += module.o
|
||||||
obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
|
obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_CPU_PM) += suspend_entry.o suspend.o
|
||||||
|
|
||||||
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
|
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
#include <asm/suspend.h>
|
||||||
|
|
||||||
void asm_offsets(void)
|
void asm_offsets(void)
|
||||||
{
|
{
|
||||||
@ -145,6 +146,8 @@ void asm_offsets(void)
|
|||||||
OFFSET(PT_BADADDR, pt_regs, badaddr);
|
OFFSET(PT_BADADDR, pt_regs, badaddr);
|
||||||
OFFSET(PT_CAUSE, pt_regs, cause);
|
OFFSET(PT_CAUSE, pt_regs, cause);
|
||||||
|
|
||||||
|
OFFSET(SUSPEND_CONTEXT_REGS, suspend_context, regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* THREAD_{F,X}* might be larger than a S-type offset can handle, but
|
* THREAD_{F,X}* might be larger than a S-type offset can handle, but
|
||||||
* these are used in performance-sensitive assembly so we can't resort
|
* these are used in performance-sensitive assembly so we can't resort
|
||||||
|
|||||||
@ -61,7 +61,8 @@ pe_head_start:
|
|||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
relocate:
|
.global relocate_enable_mmu
|
||||||
|
relocate_enable_mmu:
|
||||||
/* Relocate return address */
|
/* Relocate return address */
|
||||||
li a1, PAGE_OFFSET + LOAD_OFFSET
|
li a1, PAGE_OFFSET + LOAD_OFFSET
|
||||||
la a2, _start
|
la a2, _start
|
||||||
@ -150,7 +151,7 @@ secondary_start_common:
|
|||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
/* Enable virtual memory and relocate to virtual address */
|
/* Enable virtual memory and relocate to virtual address */
|
||||||
la a0, swapper_pg_dir
|
la a0, swapper_pg_dir
|
||||||
call relocate
|
call relocate_enable_mmu
|
||||||
#endif
|
#endif
|
||||||
call setup_trap_vector
|
call setup_trap_vector
|
||||||
tail smp_callin
|
tail smp_callin
|
||||||
@ -258,7 +259,7 @@ clear_bss_done:
|
|||||||
call setup_vm
|
call setup_vm
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
la a0, early_pg_dir
|
la a0, early_pg_dir
|
||||||
call relocate
|
call relocate_enable_mmu
|
||||||
#endif /* CONFIG_MMU */
|
#endif /* CONFIG_MMU */
|
||||||
|
|
||||||
call setup_trap_vector
|
call setup_trap_vector
|
||||||
|
|||||||
131
linux_5.10/arch/riscv/kernel/suspend.c
Normal file
131
linux_5.10/arch/riscv/kernel/suspend.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||||
|
* Copyright (c) 2022 Ventana Micro Systems Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "suspend: " fmt
|
||||||
|
|
||||||
|
#include <linux/ftrace.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
|
#include <asm/csr.h>
|
||||||
|
#include <asm/sbi.h>
|
||||||
|
#include <asm/suspend.h>
|
||||||
|
|
||||||
|
void suspend_save_csrs(struct suspend_context *context)
|
||||||
|
{
|
||||||
|
context->scratch = csr_read(CSR_SCRATCH);
|
||||||
|
context->tvec = csr_read(CSR_TVEC);
|
||||||
|
context->ie = csr_read(CSR_IE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No need to save/restore IP CSR (i.e. MIP or SIP) because:
|
||||||
|
*
|
||||||
|
* 1. For no-MMU (M-mode) kernel, the bits in MIP are set by
|
||||||
|
* external devices (such as interrupt controller, timer, etc).
|
||||||
|
* 2. For MMU (S-mode) kernel, the bits in SIP are set by
|
||||||
|
* M-mode firmware and external devices (such as interrupt
|
||||||
|
* controller, etc).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
context->satp = csr_read(CSR_SATP);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void suspend_restore_csrs(struct suspend_context *context)
|
||||||
|
{
|
||||||
|
csr_write(CSR_SCRATCH, context->scratch);
|
||||||
|
csr_write(CSR_TVEC, context->tvec);
|
||||||
|
csr_write(CSR_IE, context->ie);
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
csr_write(CSR_SATP, context->satp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpu_suspend(unsigned long arg,
|
||||||
|
int (*finish)(unsigned long arg,
|
||||||
|
unsigned long entry,
|
||||||
|
unsigned long context))
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct suspend_context context = { 0 };
|
||||||
|
|
||||||
|
/* Finisher should be non-NULL */
|
||||||
|
if (!finish)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Save additional CSRs*/
|
||||||
|
suspend_save_csrs(&context);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function graph tracer state gets incosistent when the kernel
|
||||||
|
* calls functions that never return (aka finishers) hence disable
|
||||||
|
* graph tracing during their execution.
|
||||||
|
*/
|
||||||
|
pause_graph_tracing();
|
||||||
|
|
||||||
|
/* Save context on stack */
|
||||||
|
if (__cpu_suspend_enter(&context)) {
|
||||||
|
/* Call the finisher */
|
||||||
|
rc = finish(arg, __pa_symbol(__cpu_resume_enter),
|
||||||
|
(ulong)&context);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should never reach here, unless the suspend finisher
|
||||||
|
* fails. Successful cpu_suspend() should return from
|
||||||
|
* __cpu_resume_entry()
|
||||||
|
*/
|
||||||
|
if (!rc)
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable function graph tracer */
|
||||||
|
unpause_graph_tracing();
|
||||||
|
|
||||||
|
/* Restore additional CSRs */
|
||||||
|
suspend_restore_csrs(&context);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_RISCV_SBI
|
||||||
|
static int sbi_system_suspend(unsigned long sleep_type,
|
||||||
|
unsigned long resume_addr,
|
||||||
|
unsigned long opaque)
|
||||||
|
{
|
||||||
|
struct sbiret ret;
|
||||||
|
|
||||||
|
ret = sbi_ecall(SBI_EXT_SUSP, SBI_EXT_SUSP_SYSTEM_SUSPEND,
|
||||||
|
sleep_type, resume_addr, opaque, 0, 0, 0);
|
||||||
|
if (ret.error)
|
||||||
|
return sbi_err_map_linux_errno(ret.error);
|
||||||
|
|
||||||
|
return ret.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_system_suspend_enter(suspend_state_t state)
|
||||||
|
{
|
||||||
|
return cpu_suspend(SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM, sbi_system_suspend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct platform_suspend_ops sbi_system_suspend_ops = {
|
||||||
|
.valid = suspend_valid_only_mem,
|
||||||
|
.enter = sbi_system_suspend_enter,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init sbi_system_suspend_init(void)
|
||||||
|
{
|
||||||
|
pr_info("SBI SUSP extension detecting\n");
|
||||||
|
if (sbi_probe_extension(SBI_EXT_SUSP) > 0) {
|
||||||
|
pr_info("SBI SUSP extension detected\n");
|
||||||
|
if (IS_ENABLED(CONFIG_SUSPEND))
|
||||||
|
suspend_set_ops(&sbi_system_suspend_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_initcall(sbi_system_suspend_init);
|
||||||
|
#endif
|
||||||
124
linux_5.10/arch/riscv/kernel/suspend_entry.S
Normal file
124
linux_5.10/arch/riscv/kernel/suspend_entry.S
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||||
|
* Copyright (c) 2022 Ventana Micro Systems Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/asm.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
#include <asm/csr.h>
|
||||||
|
|
||||||
|
.text
|
||||||
|
.altmacro
|
||||||
|
.option norelax
|
||||||
|
|
||||||
|
ENTRY(__cpu_suspend_enter)
|
||||||
|
/* Save registers (except A0 and T0-T6) */
|
||||||
|
REG_S ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0)
|
||||||
|
REG_S sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0)
|
||||||
|
REG_S gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0)
|
||||||
|
REG_S tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0)
|
||||||
|
REG_S s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0)
|
||||||
|
REG_S s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0)
|
||||||
|
REG_S a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0)
|
||||||
|
REG_S a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0)
|
||||||
|
REG_S a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0)
|
||||||
|
REG_S a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0)
|
||||||
|
REG_S a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0)
|
||||||
|
REG_S a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0)
|
||||||
|
REG_S a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0)
|
||||||
|
REG_S s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0)
|
||||||
|
REG_S s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0)
|
||||||
|
REG_S s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0)
|
||||||
|
REG_S s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0)
|
||||||
|
REG_S s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0)
|
||||||
|
REG_S s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0)
|
||||||
|
REG_S s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0)
|
||||||
|
REG_S s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0)
|
||||||
|
REG_S s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0)
|
||||||
|
REG_S s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0)
|
||||||
|
|
||||||
|
/* Save CSRs */
|
||||||
|
csrr t0, CSR_EPC
|
||||||
|
REG_S t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0)
|
||||||
|
csrr t0, CSR_STATUS
|
||||||
|
REG_S t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0)
|
||||||
|
csrr t0, CSR_TVAL
|
||||||
|
REG_S t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0)
|
||||||
|
csrr t0, CSR_CAUSE
|
||||||
|
REG_S t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0)
|
||||||
|
|
||||||
|
/* Return non-zero value */
|
||||||
|
li a0, 1
|
||||||
|
|
||||||
|
/* Return to C code */
|
||||||
|
ret
|
||||||
|
END(__cpu_suspend_enter)
|
||||||
|
|
||||||
|
ENTRY(__cpu_resume_enter)
|
||||||
|
/* Load the global pointer */
|
||||||
|
.option push
|
||||||
|
.option norelax
|
||||||
|
la gp, __global_pointer$
|
||||||
|
.option pop
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
/* Save A0 and A1 */
|
||||||
|
add t0, a0, zero
|
||||||
|
add t1, a1, zero
|
||||||
|
|
||||||
|
/* Enable MMU */
|
||||||
|
la a0, swapper_pg_dir
|
||||||
|
XIP_FIXUP_OFFSET a0
|
||||||
|
call relocate_enable_mmu
|
||||||
|
|
||||||
|
/* Restore A0 and A1 */
|
||||||
|
add a0, t0, zero
|
||||||
|
add a1, t1, zero
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make A0 point to suspend context */
|
||||||
|
add a0, a1, zero
|
||||||
|
|
||||||
|
/* Restore CSRs */
|
||||||
|
REG_L t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0)
|
||||||
|
csrw CSR_EPC, t0
|
||||||
|
REG_L t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0)
|
||||||
|
csrw CSR_STATUS, t0
|
||||||
|
REG_L t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0)
|
||||||
|
csrw CSR_TVAL, t0
|
||||||
|
REG_L t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0)
|
||||||
|
csrw CSR_CAUSE, t0
|
||||||
|
|
||||||
|
/* Restore registers (except A0 and T0-T6) */
|
||||||
|
REG_L ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0)
|
||||||
|
REG_L sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0)
|
||||||
|
REG_L gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0)
|
||||||
|
REG_L tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0)
|
||||||
|
REG_L s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0)
|
||||||
|
REG_L s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0)
|
||||||
|
REG_L a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0)
|
||||||
|
REG_L a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0)
|
||||||
|
REG_L a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0)
|
||||||
|
REG_L a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0)
|
||||||
|
REG_L a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0)
|
||||||
|
REG_L a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0)
|
||||||
|
REG_L a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0)
|
||||||
|
REG_L s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0)
|
||||||
|
REG_L s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0)
|
||||||
|
REG_L s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0)
|
||||||
|
REG_L s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0)
|
||||||
|
REG_L s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0)
|
||||||
|
REG_L s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0)
|
||||||
|
REG_L s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0)
|
||||||
|
REG_L s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0)
|
||||||
|
REG_L s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0)
|
||||||
|
REG_L s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0)
|
||||||
|
|
||||||
|
/* Return zero value */
|
||||||
|
add a0, zero, zero
|
||||||
|
|
||||||
|
/* Return to C code */
|
||||||
|
ret
|
||||||
|
END(__cpu_resume_enter)
|
||||||
@ -2673,7 +2673,7 @@ static void cv180x_clk_resume(void)
|
|||||||
|
|
||||||
/* switch clock to xtal */
|
/* switch clock to xtal */
|
||||||
writel(0xffffffff, clk_data->base + REG_CLK_BYP_0);
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_0);
|
||||||
writel(0x0000000f, clk_data->base + REG_CLK_BYP_1);
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_1);
|
||||||
|
|
||||||
memcpy_toio(clk_data->base + REG_CLK_EN_START,
|
memcpy_toio(clk_data->base + REG_CLK_EN_START,
|
||||||
clk_data->clken_saved_regs,
|
clk_data->clken_saved_regs,
|
||||||
@ -2691,9 +2691,9 @@ static void cv180x_clk_resume(void)
|
|||||||
clk_data->g2_clkdiv_saved_regs,
|
clk_data->g2_clkdiv_saved_regs,
|
||||||
REG_CLK_G2_DIV_NUM * 4);
|
REG_CLK_G2_DIV_NUM * 4);
|
||||||
|
|
||||||
memcpy_toio(clk_data->base + REG_PLL_G6_CSR_START,
|
//memcpy_toio(clk_data->base + REG_PLL_G6_CSR_START,
|
||||||
clk_data->pll_g6_csr_saved_regs,
|
// clk_data->pll_g6_csr_saved_regs,
|
||||||
REG_PLL_G6_CSR_NUM * 4);
|
// REG_PLL_G6_CSR_NUM * 4);
|
||||||
|
|
||||||
/* wait for pll setting updated */
|
/* wait for pll setting updated */
|
||||||
while (readl(clk_data->base + REG_PLL_G6_STATUS) & 0x7) {
|
while (readl(clk_data->base + REG_PLL_G6_STATUS) & 0x7) {
|
||||||
|
|||||||
@ -2679,7 +2679,7 @@ static void cv181x_clk_resume(void)
|
|||||||
|
|
||||||
/* switch clock to xtal */
|
/* switch clock to xtal */
|
||||||
writel(0xffffffff, clk_data->base + REG_CLK_BYP_0);
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_0);
|
||||||
writel(0x0000000f, clk_data->base + REG_CLK_BYP_1);
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_1);
|
||||||
|
|
||||||
memcpy_toio(clk_data->base + REG_CLK_EN_START,
|
memcpy_toio(clk_data->base + REG_CLK_EN_START,
|
||||||
clk_data->clken_saved_regs,
|
clk_data->clken_saved_regs,
|
||||||
@ -2697,9 +2697,9 @@ static void cv181x_clk_resume(void)
|
|||||||
clk_data->g2_clkdiv_saved_regs,
|
clk_data->g2_clkdiv_saved_regs,
|
||||||
REG_CLK_G2_DIV_NUM * 4);
|
REG_CLK_G2_DIV_NUM * 4);
|
||||||
|
|
||||||
memcpy_toio(clk_data->base + REG_PLL_G6_CSR_START,
|
// memcpy_toio(clk_data->base + REG_PLL_G6_CSR_START,
|
||||||
clk_data->pll_g6_csr_saved_regs,
|
// clk_data->pll_g6_csr_saved_regs,
|
||||||
REG_PLL_G6_CSR_NUM * 4);
|
// REG_PLL_G6_CSR_NUM * 4);
|
||||||
|
|
||||||
/* wait for pll setting updated */
|
/* wait for pll setting updated */
|
||||||
while (readl(clk_data->base + REG_PLL_G6_STATUS) & 0x7) {
|
while (readl(clk_data->base + REG_PLL_G6_STATUS) & 0x7) {
|
||||||
|
|||||||
@ -901,4 +901,12 @@ config CRYPTO_DEV_SA2UL
|
|||||||
used for crypto offload. Select this if you want to use hardware
|
used for crypto offload. Select this if you want to use hardware
|
||||||
acceleration for cryptographic algorithms on these devices.
|
acceleration for cryptographic algorithms on these devices.
|
||||||
|
|
||||||
|
config CRYPTO_DEV_CVITEK_SPACC
|
||||||
|
tristate "Support for cvitek spacc"
|
||||||
|
depends on ARCH_CVITEK
|
||||||
|
help
|
||||||
|
This driver provides support for SPACC devices that are part of the CVITEK SoCs.
|
||||||
|
It handles cryptographic operations and provides a generic interface for SPACC devices.
|
||||||
|
To compile this driver as a module, choose M here: the module will be called spacc-cvitek.
|
||||||
|
|
||||||
endif # CRYPTO_HW
|
endif # CRYPTO_HW
|
||||||
|
|||||||
@ -51,3 +51,5 @@ obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/
|
|||||||
obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_AES) += xilinx/
|
obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_AES) += xilinx/
|
||||||
obj-y += hisilicon/
|
obj-y += hisilicon/
|
||||||
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
|
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
|
||||||
|
obj-$(CONFIG_CRYPTO_DEV_CVITEK_SPACC) += cvitek-spacc.o
|
||||||
|
|
||||||
|
|||||||
57
linux_5.10/drivers/crypto/cvitek-spacc-regs.h
Normal file
57
linux_5.10/drivers/crypto/cvitek-spacc-regs.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef _CVITEK_SPACC_REGS_H_
|
||||||
|
#define _CVITEK_SPACC_REGS_H_
|
||||||
|
|
||||||
|
// Register offset
|
||||||
|
#define CRYPTODMA_DMA_CTRL 0x0
|
||||||
|
#define CRYPTODMA_INT_MASK 0x4
|
||||||
|
#define CRYPTODMA_DES_BASE_L 0x8
|
||||||
|
#define CRYPTODMA_DES_BASE_H 0xC
|
||||||
|
#define CRYPTODMA_WR_INT 0x10
|
||||||
|
#define CRYPTODMA_DES_KEY 0x100
|
||||||
|
#define CRYPTODMA_DES_IV 0x180
|
||||||
|
#define CRYPTODMA_SHA_PARA 0x1C0
|
||||||
|
|
||||||
|
// DMA Descriptor
|
||||||
|
#define CRYPTODMA_CTRL 0x00
|
||||||
|
#define CRYPTODMA_CIPHER 0x01
|
||||||
|
#define CRYPTODMA_NEXT_PTR_ADDR_L 0x02
|
||||||
|
#define CRYPTODMA_NEXT_PTR_ADDR_H 0x03
|
||||||
|
#define CRYPTODMA_SRC_ADDR_L 0x04
|
||||||
|
#define CRYPTODMA_SRC_ADDR_H 0x05
|
||||||
|
#define CRYPTODMA_DST_ADDR_L 0x06
|
||||||
|
#define CRYPTODMA_DST_ADDR_H 0x07
|
||||||
|
#define CRYPTODMA_DATA_AMOUNT_L 0x08
|
||||||
|
#define CRYPTODMA_SRC_LEN 0x08
|
||||||
|
#define CRYPTODMA_DATA_AMOUNT_H 0x09
|
||||||
|
#define CRYPTODMA_DST_LEN 0x0A
|
||||||
|
#define CRYPTODMA_KEY 0x0A
|
||||||
|
#define CRYPTODMA_IV 0x12
|
||||||
|
|
||||||
|
#define DES_USE_BYPASS BIT(8)
|
||||||
|
#define DES_USE_AES BIT(9)
|
||||||
|
#define DES_USE_DES BIT(10)
|
||||||
|
#define DES_USE_SM4 BIT(11)
|
||||||
|
#define DES_USE_SHA BIT(12)
|
||||||
|
#define DES_USE_BASE64 BIT(13)
|
||||||
|
#define DES_USE_KEY0 BIT(16)
|
||||||
|
#define DES_USE_KEY1 BIT(17)
|
||||||
|
#define DES_USE_KEY2 BIT(18)
|
||||||
|
#define DES_USE_DESCRIPTOR_KEY BIT(19)
|
||||||
|
#define DES_USE_IV0 BIT(20)
|
||||||
|
#define DES_USE_IV1 BIT(21)
|
||||||
|
#define DES_USE_IV2 BIT(22)
|
||||||
|
#define DES_USE_DESCRIPTOR_IV BIT(23)
|
||||||
|
|
||||||
|
// Cipher control for AES
|
||||||
|
#define DECRYPT_ENABLE 0x0
|
||||||
|
#define CBC_ENABLE 0x1
|
||||||
|
#define AES_KEY_MODE 0x4
|
||||||
|
|
||||||
|
// DMA control
|
||||||
|
#define DMA_ENABLE 1
|
||||||
|
#define DMA_DESCRIPTOR_MODE 1
|
||||||
|
#define DMA_READ_MAX_BURST 16
|
||||||
|
#define DMA_WRITE_MAX_BURST 6
|
||||||
|
|
||||||
|
#endif
|
||||||
748
linux_5.10/drivers/crypto/cvitek-spacc.c
Normal file
748
linux_5.10/drivers/crypto/cvitek-spacc.c
Normal file
@ -0,0 +1,748 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright 2022-2023 CVITEK
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/moduleparam.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
|
#include <linux/dma-map-ops.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/cdev.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/cvitek_spacc.h>
|
||||||
|
#include <cvitek-spacc-regs.h>
|
||||||
|
|
||||||
|
#define DEVICE_NAME "spacc"
|
||||||
|
|
||||||
|
static char flag = 'n';
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(wq);
|
||||||
|
|
||||||
|
struct cvi_spacc {
|
||||||
|
struct device *dev;
|
||||||
|
struct cdev cdev;
|
||||||
|
dev_t tdev;
|
||||||
|
void __iomem *spacc_base;
|
||||||
|
struct class *spacc_class;
|
||||||
|
void *buffer;
|
||||||
|
u32 buffer_size;
|
||||||
|
u32 used_size;
|
||||||
|
|
||||||
|
// for sha256/sha1
|
||||||
|
u32 state[8];
|
||||||
|
u32 result_size;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
struct clk *efuse_clk;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int cvitek_spacc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = dev_get_drvdata(dev);
|
||||||
|
void __iomem *sec_top;
|
||||||
|
|
||||||
|
clk_prepare_enable(spacc->efuse_clk);
|
||||||
|
|
||||||
|
sec_top = ioremap(0x020b0000, 4);
|
||||||
|
iowrite32(0x3, sec_top);
|
||||||
|
iounmap(sec_top);
|
||||||
|
|
||||||
|
clk_disable_unprepare(spacc->efuse_clk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvitek_spacc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = dev_get_drvdata(dev);
|
||||||
|
void __iomem *sec_top;
|
||||||
|
|
||||||
|
clk_prepare_enable(spacc->efuse_clk);
|
||||||
|
|
||||||
|
sec_top = ioremap(0x020b0000, 4);
|
||||||
|
iowrite32(0x0, sec_top);
|
||||||
|
iounmap(sec_top);
|
||||||
|
|
||||||
|
clk_disable_unprepare(spacc->efuse_clk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(cvitek_spacc_pm_ops, cvitek_spacc_suspend, cvitek_spacc_resume);
|
||||||
|
|
||||||
|
static inline void cvi_sha256_init(struct cvi_spacc *spacc)
|
||||||
|
{
|
||||||
|
spacc->state[0] = cpu_to_be32(0x6A09E667);
|
||||||
|
spacc->state[1] = cpu_to_be32(0xBB67AE85);
|
||||||
|
spacc->state[2] = cpu_to_be32(0x3C6EF372);
|
||||||
|
spacc->state[3] = cpu_to_be32(0xA54FF53A);
|
||||||
|
spacc->state[4] = cpu_to_be32(0x510E527F);
|
||||||
|
spacc->state[5] = cpu_to_be32(0x9B05688C);
|
||||||
|
spacc->state[6] = cpu_to_be32(0x1F83D9AB);
|
||||||
|
spacc->state[7] = cpu_to_be32(0x5BE0CD19);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cvi_sha1_init(struct cvi_spacc *spacc)
|
||||||
|
{
|
||||||
|
spacc->state[0] = cpu_to_be32(0x67452301);
|
||||||
|
spacc->state[1] = cpu_to_be32(0xEFCDAB89);
|
||||||
|
spacc->state[2] = cpu_to_be32(0x98BADCFE);
|
||||||
|
spacc->state[3] = cpu_to_be32(0x10325476);
|
||||||
|
spacc->state[4] = cpu_to_be32(0xC3D2E1F0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void trigger_cryptodma_engine_and_wait_finish(struct cvi_spacc *spacc)
|
||||||
|
{
|
||||||
|
// Set cryptodma control
|
||||||
|
iowrite32(0x3, spacc->spacc_base + CRYPTODMA_INT_MASK);
|
||||||
|
|
||||||
|
// Clear interrupt
|
||||||
|
// Important!!! must do this
|
||||||
|
iowrite32(0x3, spacc->spacc_base + CRYPTODMA_WR_INT);
|
||||||
|
|
||||||
|
// Trigger cryptodma engine
|
||||||
|
iowrite32(DMA_WRITE_MAX_BURST << 24 |
|
||||||
|
DMA_READ_MAX_BURST << 16 |
|
||||||
|
DMA_DESCRIPTOR_MODE << 1 | DMA_ENABLE, spacc->spacc_base + CRYPTODMA_DMA_CTRL);
|
||||||
|
|
||||||
|
wait_event_interruptible(wq, flag == 'y');
|
||||||
|
flag = 'n';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void get_hash_result(struct cvi_spacc *spacc, int count)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u32 *result = (u32 *)spacc->buffer;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
result[i] = ioread32(spacc->spacc_base + CRYPTODMA_SHA_PARA + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setup_dma_descriptor(struct cvi_spacc *spacc, uint32_t *dma_descriptor)
|
||||||
|
{
|
||||||
|
phys_addr_t descriptor_phys;
|
||||||
|
|
||||||
|
descriptor_phys = virt_to_phys(dma_descriptor);
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(descriptor_phys, /*sizeof(dma_descriptor)*/ 4 * 22, DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
// set dma descriptor addr
|
||||||
|
iowrite32((uint32_t)((uint64_t)descriptor_phys & 0xFFFFFFFF), spacc->spacc_base + CRYPTODMA_DES_BASE_L);
|
||||||
|
iowrite32((uint32_t)((uint64_t)descriptor_phys >> 32), spacc->spacc_base + CRYPTODMA_DES_BASE_H);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setup_src(u32 *dma_descriptor, uintptr_t src, u32 len)
|
||||||
|
{
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
|
||||||
|
src_phys = virt_to_phys((void *)src);
|
||||||
|
arch_sync_dma_for_device(src_phys, len, DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_LEN] = len;
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_ADDR_L] = (uint32_t)((uint64_t)src_phys & 0xFFFFFFFF);
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_ADDR_H] = (uint32_t)((uint64_t)src_phys >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_src_dst(u32 *dma_descriptor, phys_addr_t buffer, u32 len)
|
||||||
|
{
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_LEN] = len;
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_ADDR_L] = (uint32_t)((uint64_t)buffer & 0xFFFFFFFF);
|
||||||
|
dma_descriptor[CRYPTODMA_SRC_ADDR_H] = (uint32_t)((uint64_t)buffer >> 32);
|
||||||
|
|
||||||
|
dma_descriptor[CRYPTODMA_DST_ADDR_L] = (uint32_t)((uint64_t)buffer & 0xFFFFFFFF);
|
||||||
|
dma_descriptor[CRYPTODMA_DST_ADDR_H] = (uint32_t)((uint64_t)buffer >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setup_dst(dst)\
|
||||||
|
do {\
|
||||||
|
phys_addr_t dst_phys = virt_to_phys((void *)dst);\
|
||||||
|
dma_descriptor[CRYPTODMA_DST_ADDR_L] = (uint32_t)((uint64_t)dst_phys & 0xFFFFFFFF);\
|
||||||
|
dma_descriptor[CRYPTODMA_DST_ADDR_H] = (uint32_t)((uint64_t)dst_phys >> 32);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline void setup_mode(u32 *dma_descriptor, SPACC_ALGO_MODE_E mode, unsigned char *iv)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case SPACC_ALGO_MODE_CBC:
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] |= DES_USE_DESCRIPTOR_IV;
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] = CBC_ENABLE << 1;
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_IV], iv, 16);
|
||||||
|
break;
|
||||||
|
case SPACC_ALGO_MODE_CTR:
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] |= DES_USE_DESCRIPTOR_IV;
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] = 0x1 << 2;
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_IV], iv, 16);
|
||||||
|
break;
|
||||||
|
case SPACC_ALGO_MODE_ECB:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setup_key_size(u32 *dma_descriptor, SPACC_KEY_SIZE_E size, unsigned char *key)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case SPACC_KEY_SIZE_64BITS:
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], key, 8);
|
||||||
|
break;
|
||||||
|
case SPACC_KEY_SIZE_128BITS:
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] |= (0x1 << 5);
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], key, 16);
|
||||||
|
break;
|
||||||
|
case SPACC_KEY_SIZE_192BITS:
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] |= (0x1 << 4);
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], key, 24);
|
||||||
|
break;
|
||||||
|
case SPACC_KEY_SIZE_256BITS:
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] |= (0x1 << 3);
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], key, 32);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setup_action(u32 *dma_descriptor, SPACC_ACTION_E action)
|
||||||
|
{
|
||||||
|
if (action == SPACC_ACTION_ENCRYPTION)
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] |= 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t cvitek_spacc_irq(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = (struct cvi_spacc *)data;
|
||||||
|
|
||||||
|
iowrite32(0x3, spacc->spacc_base + CRYPTODMA_WR_INT);
|
||||||
|
|
||||||
|
flag = 'y';
|
||||||
|
wake_up_interruptible(&wq);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_sha256(struct cvi_spacc *spacc, uintptr_t src, uint32_t len)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
// must mark DES_USE_DESCRIPTOR_KEY flag
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_DESCRIPTOR_KEY | DES_USE_SHA | 0xF;
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] = (0x1 << 1) | 0x1;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
dma_descriptor[CRYPTODMA_KEY + i] = spacc->state[i];
|
||||||
|
|
||||||
|
setup_src(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_sha1(struct cvi_spacc *spacc, uintptr_t src, uint32_t len)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
// must mark DES_USE_DESCRIPTOR_KEY flag
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_DESCRIPTOR_KEY | DES_USE_SHA | 0xF;
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] = 0x1;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
dma_descriptor[CRYPTODMA_KEY + i] = spacc->state[i];
|
||||||
|
|
||||||
|
setup_src(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_base64(struct cvi_spacc *spacc, phys_addr_t src, uint32_t len, SPACC_ACTION_E ation)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_BASE64 | 0xF;
|
||||||
|
|
||||||
|
if (ation == SPACC_ACTION_ENCRYPTION) {
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] = 0x1;
|
||||||
|
spacc->result_size = (len + (3 - 1)) / 3 * 4;
|
||||||
|
dma_descriptor[CRYPTODMA_DST_LEN] = spacc->result_size;
|
||||||
|
} else {
|
||||||
|
spacc->result_size = (len / 4) * 3;
|
||||||
|
dma_descriptor[CRYPTODMA_DST_LEN] = spacc->result_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_src_dst(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_aes(struct cvi_spacc *spacc, phys_addr_t src, uint32_t len, spacc_aes_config_s config)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
|
||||||
|
spacc->result_size = len;
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_DESCRIPTOR_KEY | DES_USE_AES | 0xF;
|
||||||
|
|
||||||
|
setup_mode(dma_descriptor, config.mode, config.iv);
|
||||||
|
setup_key_size(dma_descriptor, config.size, config.key);
|
||||||
|
setup_action(dma_descriptor, config.action);
|
||||||
|
|
||||||
|
setup_src_dst(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_sm4(struct cvi_spacc *spacc, phys_addr_t src, uint32_t len, spacc_sm4_config_s config)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
|
||||||
|
spacc->result_size = len;
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_DESCRIPTOR_KEY | DES_USE_SM4 | 0xF;
|
||||||
|
|
||||||
|
setup_mode(dma_descriptor, config.mode, config.iv);
|
||||||
|
setup_key_size(dma_descriptor, config.size, config.key);
|
||||||
|
setup_action(dma_descriptor, config.action);
|
||||||
|
|
||||||
|
setup_src_dst(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spacc_des(struct cvi_spacc *spacc, phys_addr_t src, uint32_t len, spacc_des_config_s config, int is_tdes)
|
||||||
|
{
|
||||||
|
__aligned(32) u32 dma_descriptor[22] = {0};
|
||||||
|
|
||||||
|
spacc->result_size = len;
|
||||||
|
dma_descriptor[CRYPTODMA_CTRL] = DES_USE_DESCRIPTOR_KEY | DES_USE_DES | 0xF;
|
||||||
|
|
||||||
|
setup_mode(dma_descriptor, config.mode, config.iv);
|
||||||
|
if (is_tdes) {
|
||||||
|
dma_descriptor[CRYPTODMA_CIPHER] |= (0x1 << 3);
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], config.key, 24);
|
||||||
|
} else {
|
||||||
|
memcpy(&dma_descriptor[CRYPTODMA_KEY], config.key, 8);
|
||||||
|
}
|
||||||
|
setup_action(dma_descriptor, config.action);
|
||||||
|
|
||||||
|
setup_src_dst(dma_descriptor, src, len);
|
||||||
|
setup_dma_descriptor(spacc, dma_descriptor);
|
||||||
|
|
||||||
|
trigger_cryptodma_engine_and_wait_finish(spacc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvi_spacc_init_buffer(struct cvi_spacc *spacc, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int order = get_order(size);
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if (size == spacc->buffer_size) {
|
||||||
|
return 0;
|
||||||
|
} else if (spacc->buffer_size) {
|
||||||
|
free_pages((unsigned long)spacc->buffer, get_order(spacc->buffer_size));
|
||||||
|
spacc->buffer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
|
||||||
|
if (!page)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spacc->buffer = page_address(page);
|
||||||
|
spacc->buffer_size = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spacc_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc;
|
||||||
|
|
||||||
|
spacc = container_of(inode->i_cdev, struct cvi_spacc, cdev);
|
||||||
|
|
||||||
|
spacc->used_size = 0;
|
||||||
|
spacc->result_size = 0;
|
||||||
|
file->private_data = spacc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t spacc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = filp->private_data;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (spacc->result_size == 0) {
|
||||||
|
pr_err("spacc result is 0\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < spacc->result_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = copy_to_user(buf, spacc->buffer, spacc->result_size);
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return spacc->result_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t spacc_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = filp->private_data;
|
||||||
|
int ret = spacc->buffer_size - spacc->used_size;
|
||||||
|
|
||||||
|
if (ret <= 0)
|
||||||
|
return spacc->used_size;
|
||||||
|
|
||||||
|
if (count > ret)
|
||||||
|
count = ret;
|
||||||
|
|
||||||
|
ret = copy_from_user(((unsigned char *)spacc->buffer + spacc->used_size), buf, count);
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
spacc->used_size += count;
|
||||||
|
return spacc->used_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spacc_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long spacc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = filp->private_data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case IOCTL_SPACC_CREATE_MEMPOOL: {
|
||||||
|
unsigned int size = 0;
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&size, (unsigned char *)arg, sizeof(size));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = cvi_spacc_init_buffer(spacc, size);
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_GET_MEMPOOL_SIZE: {
|
||||||
|
ret = copy_to_user((unsigned char *)arg, (unsigned char *)&spacc->buffer_size,
|
||||||
|
sizeof(spacc->buffer_size));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_SHA256_ACTION: {
|
||||||
|
if (spacc->used_size & 0x3F) {
|
||||||
|
pr_err("used_size : %d\n", spacc->used_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cvi_sha256_init(spacc);
|
||||||
|
|
||||||
|
ret = spacc_sha256(spacc, (uintptr_t)spacc->buffer, spacc->used_size);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_hash_result(spacc, 8);
|
||||||
|
spacc->result_size = 32;
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_SHA1_ACTION: {
|
||||||
|
if (spacc->used_size & 0x3F) {
|
||||||
|
pr_err("spacc_dev->used_size : %d\n", spacc->used_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cvi_sha1_init(spacc);
|
||||||
|
|
||||||
|
ret = spacc_sha1(spacc, (uintptr_t)spacc->buffer, spacc->used_size);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_hash_result(spacc, 5);
|
||||||
|
spacc->result_size = 20;
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_BASE64_ACTION: {
|
||||||
|
spacc_base64_action_s action = {0};
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&action, (unsigned char *)arg, sizeof(action));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src_phys = virt_to_phys(spacc->buffer);
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->used_size, DMA_TO_DEVICE);
|
||||||
|
ret = spacc_base64(spacc, src_phys, spacc->used_size, action.action);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->result_size, DMA_FROM_DEVICE);
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_AES_ACTION: {
|
||||||
|
spacc_aes_config_s config = {0};
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&config, (unsigned char *)arg, sizeof(config));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (config.src) {
|
||||||
|
if ((config.len == 0) ||
|
||||||
|
(config.len & 0xF)) {
|
||||||
|
pr_err("src len [%d] invailed\n", config.len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_phys = (phys_addr_t)config.src;
|
||||||
|
len = config.len;
|
||||||
|
} else {
|
||||||
|
if ((spacc->used_size == 0) ||
|
||||||
|
(spacc->used_size & 0xF)) {
|
||||||
|
pr_err("used_size : %d\n", spacc->used_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_phys = virt_to_phys(spacc->buffer);
|
||||||
|
len = spacc->used_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, len, DMA_TO_DEVICE);
|
||||||
|
ret = spacc_aes(spacc, src_phys, len, config);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->result_size, DMA_FROM_DEVICE);
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_SM4_ACTION: {
|
||||||
|
spacc_sm4_config_s action = {0};
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
|
||||||
|
if (spacc->used_size & 0xF) {
|
||||||
|
pr_err("used_size : %d\n", spacc->used_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&action, (unsigned char *)arg, sizeof(action));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src_phys = virt_to_phys(spacc->buffer);
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->used_size, DMA_TO_DEVICE);
|
||||||
|
ret = spacc_sm4(spacc, src_phys, spacc->used_size, action);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->result_size, DMA_FROM_DEVICE);
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_DES_ACTION: {
|
||||||
|
spacc_des_config_s action = {0};
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
|
||||||
|
if (spacc->used_size & 0x7) {
|
||||||
|
pr_err("spacc_dev->used_size : %d\n", spacc->used_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&action, (unsigned char *)arg, sizeof(action));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src_phys = virt_to_phys(spacc->buffer);
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->used_size, DMA_TO_DEVICE);
|
||||||
|
ret = spacc_des(spacc, src_phys, spacc->used_size, action, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->result_size, DMA_FROM_DEVICE);
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SPACC_TDES_ACTION: {
|
||||||
|
spacc_tdes_config_s action = {0};
|
||||||
|
phys_addr_t src_phys;
|
||||||
|
|
||||||
|
if (spacc->used_size & 0x7) {
|
||||||
|
pr_err("spacc_dev->used_size : %d\n", spacc->used_size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = copy_from_user((unsigned char *)&action, (unsigned char *)arg, sizeof(action));
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src_phys = virt_to_phys(spacc->buffer);
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->used_size, DMA_TO_DEVICE);
|
||||||
|
ret = spacc_des(spacc, src_phys, spacc->used_size, action, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("plat_cryptodma_do failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_sync_dma_for_device(src_phys, spacc->result_size, DMA_FROM_DEVICE);
|
||||||
|
spacc->used_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct file_operations spacc_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = spacc_open,
|
||||||
|
.read = spacc_read,
|
||||||
|
.write = spacc_write,
|
||||||
|
.release = spacc_release,
|
||||||
|
.unlocked_ioctl = spacc_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cvitek_spacc_drv_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
spacc = devm_kzalloc(dev, sizeof(*spacc), GFP_KERNEL);
|
||||||
|
if (!spacc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spacc->dev = dev;
|
||||||
|
spacc->spacc_base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (!spacc->spacc_base)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = platform_get_irq(pdev, 0);
|
||||||
|
if (ret <= 0) {
|
||||||
|
pr_err("get irq num failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
spacc->efuse_clk = clk_get_sys(NULL, "clk_efuse");
|
||||||
|
if (IS_ERR(spacc->efuse_clk)) {
|
||||||
|
pr_err("%s: efuse clock not found %ld\n", __func__
|
||||||
|
, PTR_ERR(spacc->efuse_clk));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = devm_request_irq(dev, ret, cvitek_spacc_irq
|
||||||
|
, IRQF_SHARED | IRQF_TRIGGER_RISING, pdev->name, spacc);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("request irq failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = alloc_chrdev_region(&spacc->tdev, 0, 1, DEVICE_NAME);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cdev_init(&spacc->cdev, &spacc_fops);
|
||||||
|
spacc->cdev.owner = THIS_MODULE;
|
||||||
|
|
||||||
|
ret = cdev_add(&spacc->cdev, spacc->tdev, 1);
|
||||||
|
if (ret)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
spacc->spacc_class = class_create(THIS_MODULE, DEVICE_NAME);
|
||||||
|
if (IS_ERR(spacc->spacc_class)) {
|
||||||
|
pr_err("Err: failed when create class.\n");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_create(spacc->spacc_class, NULL, spacc->tdev, spacc, DEVICE_NAME);
|
||||||
|
return ret;
|
||||||
|
failed:
|
||||||
|
unregister_chrdev_region(spacc->tdev, 1);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvitek_spacc_drv_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct cvi_spacc *spacc = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
device_destroy(spacc->spacc_class, spacc->tdev);
|
||||||
|
cdev_del(&spacc->cdev);
|
||||||
|
unregister_chrdev_region(spacc->tdev, 1);
|
||||||
|
class_destroy(spacc->spacc_class);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id cvitek_spacc_of_match[] = {
|
||||||
|
{ .compatible = "cvitek,spacc", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, cvitek_spacc_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct platform_driver cvitek_spacc_driver = {
|
||||||
|
.probe = cvitek_spacc_drv_probe,
|
||||||
|
.remove = cvitek_spacc_drv_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "cvitek_spacc",
|
||||||
|
.of_match_table = of_match_ptr(cvitek_spacc_of_match),
|
||||||
|
.pm = &cvitek_spacc_pm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(cvitek_spacc_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Cvitek Spacc Driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@ -17,6 +17,7 @@
|
|||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/syscore_ops.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,6 +65,8 @@ struct plic_priv {
|
|||||||
struct cpumask lmask;
|
struct cpumask lmask;
|
||||||
struct irq_domain *irqdomain;
|
struct irq_domain *irqdomain;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
|
unsigned int nr_irqs;
|
||||||
|
unsigned long *prio_save;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct plic_handler {
|
struct plic_handler {
|
||||||
@ -75,6 +78,7 @@ struct plic_handler {
|
|||||||
*/
|
*/
|
||||||
raw_spinlock_t enable_lock;
|
raw_spinlock_t enable_lock;
|
||||||
void __iomem *enable_base;
|
void __iomem *enable_base;
|
||||||
|
u32 *enable_save;
|
||||||
struct plic_priv *priv;
|
struct plic_priv *priv;
|
||||||
};
|
};
|
||||||
static int plic_parent_irq;
|
static int plic_parent_irq;
|
||||||
@ -182,6 +186,70 @@ static struct irq_chip plic_chip = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int plic_irq_suspend(void)
|
||||||
|
{
|
||||||
|
unsigned int i, cpu;
|
||||||
|
u32 __iomem *reg;
|
||||||
|
struct plic_priv *priv;
|
||||||
|
|
||||||
|
priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nr_irqs; i++)
|
||||||
|
if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID))
|
||||||
|
__set_bit(i, priv->prio_save);
|
||||||
|
else
|
||||||
|
__clear_bit(i, priv->prio_save);
|
||||||
|
|
||||||
|
for_each_cpu(cpu, cpu_present_mask) {
|
||||||
|
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
|
||||||
|
|
||||||
|
if (!handler->present)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
raw_spin_lock(&handler->enable_lock);
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
|
||||||
|
reg = handler->enable_base + i * sizeof(u32);
|
||||||
|
handler->enable_save[i] = readl(reg);
|
||||||
|
}
|
||||||
|
raw_spin_unlock(&handler->enable_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plic_irq_resume(void)
|
||||||
|
{
|
||||||
|
unsigned int i, index, cpu;
|
||||||
|
u32 __iomem *reg;
|
||||||
|
struct plic_priv *priv;
|
||||||
|
|
||||||
|
priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nr_irqs; i++) {
|
||||||
|
index = BIT_WORD(i);
|
||||||
|
writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0,
|
||||||
|
priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_cpu(cpu, cpu_present_mask) {
|
||||||
|
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
|
||||||
|
|
||||||
|
if (!handler->present)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
raw_spin_lock(&handler->enable_lock);
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
|
||||||
|
reg = handler->enable_base + i * sizeof(u32);
|
||||||
|
writel(handler->enable_save[i], reg);
|
||||||
|
}
|
||||||
|
raw_spin_unlock(&handler->enable_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct syscore_ops plic_irq_syscore_ops = {
|
||||||
|
.suspend = plic_irq_suspend,
|
||||||
|
.resume = plic_irq_resume,
|
||||||
|
};
|
||||||
static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
|
static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
|
||||||
irq_hw_number_t hwirq)
|
irq_hw_number_t hwirq)
|
||||||
{
|
{
|
||||||
@ -302,15 +370,21 @@ static int __init plic_init(struct device_node *node,
|
|||||||
if (WARN_ON(!nr_irqs))
|
if (WARN_ON(!nr_irqs))
|
||||||
goto out_iounmap;
|
goto out_iounmap;
|
||||||
|
|
||||||
|
priv->nr_irqs = nr_irqs;
|
||||||
|
|
||||||
|
priv->prio_save = bitmap_alloc(nr_irqs, GFP_KERNEL);
|
||||||
|
if (!priv->prio_save)
|
||||||
|
goto out_free_priority_reg;
|
||||||
|
|
||||||
nr_contexts = of_irq_count(node);
|
nr_contexts = of_irq_count(node);
|
||||||
if (WARN_ON(!nr_contexts))
|
if (WARN_ON(!nr_contexts))
|
||||||
goto out_iounmap;
|
goto out_free_priority_reg;
|
||||||
|
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1,
|
priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1,
|
||||||
&plic_irqdomain_ops, priv);
|
&plic_irqdomain_ops, priv);
|
||||||
if (WARN_ON(!priv->irqdomain))
|
if (WARN_ON(!priv->irqdomain))
|
||||||
goto out_iounmap;
|
goto out_free_priority_reg;
|
||||||
|
|
||||||
for (i = 0; i < nr_contexts; i++) {
|
for (i = 0; i < nr_contexts; i++) {
|
||||||
struct of_phandle_args parent;
|
struct of_phandle_args parent;
|
||||||
@ -369,6 +443,11 @@ static int __init plic_init(struct device_node *node,
|
|||||||
handler->enable_base =
|
handler->enable_base =
|
||||||
priv->regs + ENABLE_BASE + i * ENABLE_PER_HART;
|
priv->regs + ENABLE_BASE + i * ENABLE_PER_HART;
|
||||||
handler->priv = priv;
|
handler->priv = priv;
|
||||||
|
|
||||||
|
handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32),
|
||||||
|
sizeof(*handler->enable_save), GFP_KERNEL);
|
||||||
|
if (!handler->enable_save)
|
||||||
|
goto out_free_enable_reg;
|
||||||
done:
|
done:
|
||||||
for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
|
for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
|
||||||
plic_toggle(handler, hwirq, 0);
|
plic_toggle(handler, hwirq, 0);
|
||||||
@ -384,6 +463,7 @@ done:
|
|||||||
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
|
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
|
||||||
"irqchip/sifive/plic:starting",
|
"irqchip/sifive/plic:starting",
|
||||||
plic_starting_cpu, plic_dying_cpu);
|
plic_starting_cpu, plic_dying_cpu);
|
||||||
|
register_syscore_ops(&plic_irq_syscore_ops);
|
||||||
plic_cpuhp_setup_done = true;
|
plic_cpuhp_setup_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +471,10 @@ done:
|
|||||||
" %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts);
|
" %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_free_enable_reg:
|
||||||
|
kfree(handler->enable_save);
|
||||||
|
out_free_priority_reg:
|
||||||
|
kfree(priv->prio_save);
|
||||||
out_iounmap:
|
out_iounmap:
|
||||||
iounmap(priv->regs);
|
iounmap(priv->regs);
|
||||||
out_free_priv:
|
out_free_priv:
|
||||||
|
|||||||
@ -97,6 +97,7 @@ short ECC_1bits_remap[4] = {0, 1, -1, -1};
|
|||||||
short ECC_GD_4bit_remap[16] = {0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff};
|
short ECC_GD_4bit_remap[16] = {0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff};
|
||||||
short ECC_GD_8bit_remap[16] = {0, 0, 0, 0, 4, 5, 6, 7, 0, 0, 0, 0, 8, 8, 8, 8};
|
short ECC_GD_8bit_remap[16] = {0, 0, 0, 0, 4, 5, 6, 7, 0, 0, 0, 0, 8, 8, 8, 8};
|
||||||
short ECC_HYF2G_remap[4] = {0, 1, -1, 14};
|
short ECC_HYF2G_remap[4] = {0, 1, -1, 14};
|
||||||
|
short ECC_HYF1G_remap[4] = {0, 1, -1, 4};
|
||||||
|
|
||||||
struct cvsnfc_chip_info nand_flash_cvitek_supported_ids[] = {
|
struct cvsnfc_chip_info nand_flash_cvitek_supported_ids[] = {
|
||||||
{
|
{
|
||||||
@ -1272,6 +1273,32 @@ struct cvsnfc_chip_info nand_flash_cvitek_supported_ids[] = {
|
|||||||
.flags = 0
|
.flags = 0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{ .name = "HYF1GQ4UDACAE",
|
||||||
|
.id = {0xC9, 0x21},
|
||||||
|
.pagesize = SZ_2K,
|
||||||
|
.chipsize = SZ_128,
|
||||||
|
.erasesize = SZ_128K,
|
||||||
|
.options = 0,
|
||||||
|
.id_len = 2,
|
||||||
|
.oobsize = SZ_64,
|
||||||
|
{ .strength_ds = 4,
|
||||||
|
.step_ds = SZ_512
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .ecc_sr_addr = 0xc0,
|
||||||
|
.ecc_mbf_addr = 0x0,
|
||||||
|
.read_ecc_opcode = 0,
|
||||||
|
.ecc_bits = 2,
|
||||||
|
.ecc_bit_shift = 4,
|
||||||
|
.uncorr_val = 0x2,
|
||||||
|
.remap = ECC_HYF1G_remap
|
||||||
|
},
|
||||||
|
.driver = &spi_nand_driver_gd,
|
||||||
|
.flags = 0
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
{ .name = "FM25S01A",
|
{ .name = "FM25S01A",
|
||||||
.id = {0xA1, 0xE4},
|
.id = {0xA1, 0xE4},
|
||||||
|
|||||||
@ -24,6 +24,14 @@
|
|||||||
|
|
||||||
#include "stmmac_platform.h"
|
#include "stmmac_platform.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
#if defined(CONFIG_ARCH_CV180X) || defined(CONFIG_ARCH_CV181X)
|
||||||
|
#include "dwmac1000.h"
|
||||||
|
#include "dwmac_dma.h"
|
||||||
|
#include "hwif.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
struct cvitek_mac {
|
struct cvitek_mac {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct reset_control *rst;
|
struct reset_control *rst;
|
||||||
@ -39,19 +47,54 @@ static int bm_eth_reset_phy(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
int phy_reset_gpio;
|
int phy_reset_gpio;
|
||||||
u32 ephy_addr = 0x0;
|
u32 ephy_base_addr = 0x0;
|
||||||
void __iomem *ephy_reg;
|
void __iomem *ephy_base_reg;
|
||||||
|
u32 ephy_top_addr = 0x0;
|
||||||
|
void __iomem *ephy_top_reg;
|
||||||
|
|
||||||
if (!np)
|
if (!np)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
of_property_read_u32(np, "ephy_ctl_reg", &ephy_addr);
|
of_property_read_u32(np, "ephy_base_reg", &ephy_base_addr);
|
||||||
|
of_property_read_u32(np, "ephy_top_reg", &ephy_top_addr);
|
||||||
|
|
||||||
if (ephy_addr) {
|
if (ephy_base_addr && ephy_top_addr) {
|
||||||
ephy_reg = ioremap(ephy_addr, 0x10);
|
ephy_base_reg = ioremap(ephy_base_addr, 0x80);
|
||||||
writel(readl(ephy_reg) & 0xFFFFFFFC, ephy_reg);
|
ephy_top_reg = ioremap(ephy_top_addr, 0x10);
|
||||||
mdelay(2);
|
#ifdef CONFIG_PM_SLEEP
|
||||||
iounmap(ephy_reg);
|
#if defined(CONFIG_ARCH_CV180X) || defined(CONFIG_ARCH_CV181X)
|
||||||
|
// set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
|
||||||
|
writel(0x0001, ephy_top_reg + 0x4);
|
||||||
|
|
||||||
|
// Release 0x0800[0]=0/shutdown
|
||||||
|
writel(0x0900, ephy_top_reg);
|
||||||
|
|
||||||
|
// Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
|
||||||
|
writel(0x0904, ephy_top_reg);
|
||||||
|
// ANA INIT (PD/EN), switch to MII-page5
|
||||||
|
writel(0x0500, ephy_base_reg + 0x7c);
|
||||||
|
// Release ANA_PD p5.0x10@[13:8] = 6'b001100
|
||||||
|
writel(0x0c00, ephy_base_reg + 0x40);
|
||||||
|
// Release ANA_EN p5.0x10@[7:0] = 8'b01111110
|
||||||
|
writel(0x0c7e, ephy_base_reg + 0x40);
|
||||||
|
// Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
|
||||||
|
//mdelay(1);
|
||||||
|
|
||||||
|
// Release 0x0800[1] = 1/ana_rst_n
|
||||||
|
writel(0x0906, ephy_top_reg);
|
||||||
|
|
||||||
|
// ANA INIT
|
||||||
|
// @Switch to MII-page5
|
||||||
|
writel(0x0500, ephy_base_reg + 0x7c);
|
||||||
|
// PHY_ID
|
||||||
|
writel(0x0043, ephy_base_reg + 0x8);
|
||||||
|
writel(0x5649, ephy_base_reg + 0xc);
|
||||||
|
// switch to MDIO control by ETH_MAC
|
||||||
|
writel(0x0, ephy_top_reg + 0x4);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
iounmap(ephy_base_reg);
|
||||||
|
iounmap(ephy_top_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
phy_reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0);
|
phy_reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0);
|
||||||
@ -143,12 +186,108 @@ static const struct of_device_id bm_dwmac_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, bm_dwmac_match);
|
MODULE_DEVICE_TABLE(of, bm_dwmac_match);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
#if defined(CONFIG_ARCH_CV180X) || defined(CONFIG_ARCH_CV181X)
|
||||||
|
|
||||||
|
static int cvi_eth_pm_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct net_device *ndev = dev_get_drvdata(dev);
|
||||||
|
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||||
|
|
||||||
|
if (!priv->reg_ctx) {
|
||||||
|
priv->reg_ctx = devm_kzalloc(priv->device, sizeof(struct stmmac_reg_context), GFP_KERNEL);
|
||||||
|
if (!priv->reg_ctx)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
priv->reg_ctx->ctrl = readl(priv->ioaddr + GMAC_CONTROL);
|
||||||
|
priv->reg_ctx->frame_filter = readl(priv->ioaddr + GMAC_FRAME_FILTER);
|
||||||
|
priv->reg_ctx->hash_high = readl(priv->ioaddr + GMAC_HASH_HIGH);
|
||||||
|
priv->reg_ctx->hash_low = readl(priv->ioaddr + GMAC_HASH_LOW);
|
||||||
|
priv->reg_ctx->mii_addr = readl(priv->ioaddr + GMAC_MII_ADDR);
|
||||||
|
priv->reg_ctx->mii_data = readl(priv->ioaddr + GMAC_MII_DATA);
|
||||||
|
priv->reg_ctx->flow_ctrl = readl(priv->ioaddr + GMAC_FLOW_CTRL);
|
||||||
|
priv->reg_ctx->vlan_tag = readl(priv->ioaddr + GMAC_VLAN_TAG);
|
||||||
|
priv->reg_ctx->debug = readl(priv->ioaddr + GMAC_DEBUG);
|
||||||
|
priv->reg_ctx->wakeup_fileter = readl(priv->ioaddr + GMAC_WAKEUP_FILTER);
|
||||||
|
priv->reg_ctx->lpi_ctrl_status = readl(priv->ioaddr + LPI_CTRL_STATUS);
|
||||||
|
priv->reg_ctx->lpi_timer_ctrl = readl(priv->ioaddr + LPI_TIMER_CTRL);
|
||||||
|
priv->reg_ctx->int_mask = readl(priv->ioaddr + GMAC_INT_MASK);
|
||||||
|
priv->reg_ctx->mac_addr0_high = readl(priv->ioaddr + GMAC_MAC_ADDR0_HIGH);
|
||||||
|
priv->reg_ctx->mac_addr0_low = readl(priv->ioaddr + GMAC_MAC_ADDR0_LOW);
|
||||||
|
priv->reg_ctx->pcs_base = readl(priv->ioaddr + GMAC_PCS_BASE);
|
||||||
|
priv->reg_ctx->mmc_ctrl = readl(priv->ioaddr + GMAC_MMC_CTRL);
|
||||||
|
priv->reg_ctx->mmc_rx_intr_mask = readl(priv->ioaddr + GMAC_MMC_RX_INTR_MASK);
|
||||||
|
priv->reg_ctx->mmc_tx_intr_mask = readl(priv->ioaddr + GMAC_MMC_TX_INTR_MASK);
|
||||||
|
priv->reg_ctx->mmc_ipc_rx_intr_mask = readl(priv->ioaddr + GMAC_MMC_IPC_RX_INTR_MASK);
|
||||||
|
priv->reg_ctx->mmc_rx_csum_offload = readl(priv->ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD);
|
||||||
|
priv->reg_ctx->dma_bus_mode = readl(priv->ioaddr + DMA_BUS_MODE);
|
||||||
|
priv->reg_ctx->dma_rx_base_addr = readl(priv->ioaddr + DMA_RCV_BASE_ADDR);
|
||||||
|
priv->reg_ctx->dma_tx_base_addr = readl(priv->ioaddr + DMA_TX_BASE_ADDR);
|
||||||
|
priv->reg_ctx->dma_ctrl = readl(priv->ioaddr + DMA_CONTROL);
|
||||||
|
priv->reg_ctx->dma_intr_ena = readl(priv->ioaddr + DMA_INTR_ENA);
|
||||||
|
priv->reg_ctx->dma_rx_watchdog = readl(priv->ioaddr + DMA_RX_WATCHDOG);
|
||||||
|
priv->reg_ctx->dma_axi_bus_mode = readl(priv->ioaddr + DMA_AXI_BUS_MODE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void stmmac_reset_subtask2(struct stmmac_priv *priv);
|
||||||
|
|
||||||
|
static int cvi_eth_pm_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct net_device *ndev = dev_get_drvdata(dev);
|
||||||
|
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
|
||||||
|
bm_eth_reset_phy(pdev);
|
||||||
|
writel(priv->reg_ctx->ctrl, priv->ioaddr + GMAC_CONTROL);
|
||||||
|
writel(priv->reg_ctx->frame_filter, priv->ioaddr + GMAC_FRAME_FILTER);
|
||||||
|
writel(priv->reg_ctx->hash_high, priv->ioaddr + GMAC_HASH_HIGH);
|
||||||
|
writel(priv->reg_ctx->hash_low, priv->ioaddr + GMAC_HASH_LOW);
|
||||||
|
writel(priv->reg_ctx->mii_addr, priv->ioaddr + GMAC_MII_ADDR);
|
||||||
|
writel(priv->reg_ctx->mii_data, priv->ioaddr + GMAC_MII_DATA);
|
||||||
|
writel(priv->reg_ctx->flow_ctrl, priv->ioaddr + GMAC_FLOW_CTRL);
|
||||||
|
writel(priv->reg_ctx->vlan_tag, priv->ioaddr + GMAC_VLAN_TAG);
|
||||||
|
writel(priv->reg_ctx->debug, priv->ioaddr + GMAC_DEBUG);
|
||||||
|
writel(priv->reg_ctx->wakeup_fileter, priv->ioaddr + GMAC_WAKEUP_FILTER);
|
||||||
|
writel(priv->reg_ctx->lpi_ctrl_status, priv->ioaddr + LPI_CTRL_STATUS);
|
||||||
|
writel(priv->reg_ctx->lpi_timer_ctrl, priv->ioaddr + LPI_TIMER_CTRL);
|
||||||
|
writel(priv->reg_ctx->int_mask, priv->ioaddr + GMAC_INT_MASK);
|
||||||
|
writel(priv->reg_ctx->mac_addr0_high, priv->ioaddr + GMAC_MAC_ADDR0_HIGH);
|
||||||
|
writel(priv->reg_ctx->mac_addr0_low, priv->ioaddr + GMAC_MAC_ADDR0_LOW);
|
||||||
|
writel(priv->reg_ctx->pcs_base, priv->ioaddr + GMAC_PCS_BASE);
|
||||||
|
writel(priv->reg_ctx->mmc_ctrl, priv->ioaddr + GMAC_MMC_CTRL);
|
||||||
|
writel(priv->reg_ctx->mmc_rx_intr_mask, priv->ioaddr + GMAC_MMC_RX_INTR_MASK);
|
||||||
|
writel(priv->reg_ctx->mmc_tx_intr_mask, priv->ioaddr + GMAC_MMC_TX_INTR_MASK);
|
||||||
|
writel(priv->reg_ctx->mmc_ipc_rx_intr_mask, priv->ioaddr + GMAC_MMC_IPC_RX_INTR_MASK);
|
||||||
|
writel(priv->reg_ctx->mmc_rx_csum_offload, priv->ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD);
|
||||||
|
writel(priv->reg_ctx->dma_bus_mode | 0x1, priv->ioaddr + DMA_BUS_MODE);
|
||||||
|
|
||||||
|
stmmac_reset_subtask2(priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define cvi_eth_pm_suspend NULL
|
||||||
|
#define cvi_eth_pm_resume NULL
|
||||||
|
#endif
|
||||||
|
static const struct dev_pm_ops cvi_eth_pm_ops = {
|
||||||
|
SET_SYSTEM_SLEEP_PM_OPS(cvi_eth_pm_suspend, cvi_eth_pm_resume)
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct platform_driver bm_dwmac_driver = {
|
static struct platform_driver bm_dwmac_driver = {
|
||||||
.probe = bm_dwmac_probe,
|
.probe = bm_dwmac_probe,
|
||||||
.remove = stmmac_pltfr_remove,
|
.remove = stmmac_pltfr_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "bm-dwmac",
|
.name = "bm-dwmac",
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
#if defined(CONFIG_ARCH_CV180X) || defined(CONFIG_ARCH_CV181X)
|
||||||
|
.pm = &cvi_eth_pm_ops,
|
||||||
|
#else
|
||||||
.pm = &stmmac_pltfr_pm_ops,
|
.pm = &stmmac_pltfr_pm_ops,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
.of_match_table = bm_dwmac_match,
|
.of_match_table = bm_dwmac_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -76,6 +76,9 @@ enum power_event {
|
|||||||
#define LPI_CTRL_STATUS_TLPIEN 0x00000001 /* Transmit LPI Entry */
|
#define LPI_CTRL_STATUS_TLPIEN 0x00000001 /* Transmit LPI Entry */
|
||||||
|
|
||||||
/* GMAC HW ADDR regs */
|
/* GMAC HW ADDR regs */
|
||||||
|
#define GMAC_MAC_ADDR0_HIGH 0x00000040
|
||||||
|
#define GMAC_MAC_ADDR0_LOW 0x00000044
|
||||||
|
|
||||||
#define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
|
#define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
|
||||||
(reg * 8))
|
(reg * 8))
|
||||||
#define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \
|
#define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \
|
||||||
@ -326,6 +329,9 @@ enum rtc_control {
|
|||||||
#define GMAC_MMC_CTRL 0x100
|
#define GMAC_MMC_CTRL 0x100
|
||||||
#define GMAC_MMC_RX_INTR 0x104
|
#define GMAC_MMC_RX_INTR 0x104
|
||||||
#define GMAC_MMC_TX_INTR 0x108
|
#define GMAC_MMC_TX_INTR 0x108
|
||||||
|
#define GMAC_MMC_RX_INTR_MASK 0x10c
|
||||||
|
#define GMAC_MMC_TX_INTR_MASK 0x110
|
||||||
|
#define GMAC_MMC_IPC_RX_INTR_MASK 0x200
|
||||||
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
|
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
|
||||||
#define GMAC_EXTHASH_BASE 0x500
|
#define GMAC_EXTHASH_BASE 0x500
|
||||||
|
|
||||||
|
|||||||
@ -128,6 +128,41 @@ struct stmmac_pps_cfg {
|
|||||||
struct timespec64 period;
|
struct timespec64 period;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
#if defined(CONFIG_ARCH_CV180X) || defined(CONFIG_ARCH_CV181X)
|
||||||
|
struct stmmac_reg_context {
|
||||||
|
u32 ctrl;
|
||||||
|
u32 frame_filter;
|
||||||
|
u32 hash_high;
|
||||||
|
u32 hash_low;
|
||||||
|
u32 mii_addr;
|
||||||
|
u32 mii_data;
|
||||||
|
u32 flow_ctrl;
|
||||||
|
u32 vlan_tag;
|
||||||
|
u32 debug;
|
||||||
|
u32 wakeup_fileter;
|
||||||
|
u32 lpi_ctrl_status;
|
||||||
|
u32 lpi_timer_ctrl;
|
||||||
|
u32 int_mask;
|
||||||
|
u32 mac_addr0_high;
|
||||||
|
u32 mac_addr0_low;
|
||||||
|
u32 pcs_base;
|
||||||
|
u32 mmc_ctrl;
|
||||||
|
u32 mmc_rx_intr_mask;
|
||||||
|
u32 mmc_tx_intr_mask;
|
||||||
|
u32 mmc_ipc_rx_intr_mask;
|
||||||
|
u32 mmc_rx_csum_offload;
|
||||||
|
u32 exthash_base;
|
||||||
|
u32 dma_bus_mode;
|
||||||
|
u32 dma_rx_base_addr;
|
||||||
|
u32 dma_tx_base_addr;
|
||||||
|
u32 dma_ctrl;
|
||||||
|
u32 dma_intr_ena;
|
||||||
|
u32 dma_rx_watchdog;
|
||||||
|
u32 dma_axi_bus_mode;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
struct stmmac_rss {
|
struct stmmac_rss {
|
||||||
int enable;
|
int enable;
|
||||||
u8 key[STMMAC_RSS_HASH_KEY_SIZE];
|
u8 key[STMMAC_RSS_HASH_KEY_SIZE];
|
||||||
@ -244,12 +279,15 @@ struct stmmac_priv {
|
|||||||
|
|
||||||
/* Receive Side Scaling */
|
/* Receive Side Scaling */
|
||||||
struct stmmac_rss rss;
|
struct stmmac_rss rss;
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
struct stmmac_reg_context *reg_ctx;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum stmmac_state {
|
enum stmmac_state {
|
||||||
STMMAC_DOWN,
|
STMMAC_DOWN,
|
||||||
STMMAC_RESET_REQUESTED,
|
STMMAC_RESET_REQUESTED,
|
||||||
STMMAC_RESETING,
|
STMMAC_RESETTING,
|
||||||
STMMAC_SERVICE_SCHED,
|
STMMAC_SERVICE_SCHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4627,6 +4627,22 @@ static const struct net_device_ops stmmac_netdev_ops = {
|
|||||||
.ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid,
|
.ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void stmmac_reset_subtask2(struct stmmac_priv *priv)
|
||||||
|
{
|
||||||
|
rtnl_lock();
|
||||||
|
netif_trans_update(priv->dev);
|
||||||
|
while (test_and_set_bit(STMMAC_RESETTING, &priv->state))
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
|
set_bit(STMMAC_DOWN, &priv->state);
|
||||||
|
dev_close(priv->dev);
|
||||||
|
dev_open(priv->dev, NULL);
|
||||||
|
clear_bit(STMMAC_DOWN, &priv->state);
|
||||||
|
clear_bit(STMMAC_RESETTING, &priv->state);
|
||||||
|
rtnl_unlock();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(stmmac_reset_subtask2);
|
||||||
|
|
||||||
static void stmmac_reset_subtask(struct stmmac_priv *priv)
|
static void stmmac_reset_subtask(struct stmmac_priv *priv)
|
||||||
{
|
{
|
||||||
if (!test_and_clear_bit(STMMAC_RESET_REQUESTED, &priv->state))
|
if (!test_and_clear_bit(STMMAC_RESET_REQUESTED, &priv->state))
|
||||||
@ -4638,14 +4654,14 @@ static void stmmac_reset_subtask(struct stmmac_priv *priv)
|
|||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
netif_trans_update(priv->dev);
|
netif_trans_update(priv->dev);
|
||||||
while (test_and_set_bit(STMMAC_RESETING, &priv->state))
|
while (test_and_set_bit(STMMAC_RESETTING, &priv->state))
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
set_bit(STMMAC_DOWN, &priv->state);
|
set_bit(STMMAC_DOWN, &priv->state);
|
||||||
dev_close(priv->dev);
|
dev_close(priv->dev);
|
||||||
dev_open(priv->dev, NULL);
|
dev_open(priv->dev, NULL);
|
||||||
clear_bit(STMMAC_DOWN, &priv->state);
|
clear_bit(STMMAC_DOWN, &priv->state);
|
||||||
clear_bit(STMMAC_RESETING, &priv->state);
|
clear_bit(STMMAC_RESETTING, &priv->state);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5305,6 +5321,8 @@ int stmmac_resume(struct device *dev)
|
|||||||
phylink_mac_change(priv->phylink, true);
|
phylink_mac_change(priv->phylink, true);
|
||||||
|
|
||||||
netif_device_attach(ndev);
|
netif_device_attach(ndev);
|
||||||
|
if (ndev->phydev)
|
||||||
|
phy_start(ndev->phydev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -343,6 +343,22 @@ err_ephy_mem_1:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cvi_genphy_suspend(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvi_genphy_resume(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = cv182xa_phy_config_init(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ret = genphy_config_aneg(phydev);
|
||||||
|
//return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static struct phy_driver cv182xa_phy_driver[] = {
|
static struct phy_driver cv182xa_phy_driver[] = {
|
||||||
{
|
{
|
||||||
.phy_id = 0x00435649,
|
.phy_id = 0x00435649,
|
||||||
@ -355,8 +371,8 @@ static struct phy_driver cv182xa_phy_driver[] = {
|
|||||||
.ack_interrupt = cv182xa_phy_ack_interrupt,
|
.ack_interrupt = cv182xa_phy_ack_interrupt,
|
||||||
.config_intr = cv182xa_phy_config_intr,
|
.config_intr = cv182xa_phy_config_intr,
|
||||||
.aneg_done = genphy_aneg_done,
|
.aneg_done = genphy_aneg_done,
|
||||||
.suspend = genphy_suspend,
|
.suspend = cvi_genphy_suspend,
|
||||||
.resume = genphy_resume,
|
.resume = cvi_genphy_resume,
|
||||||
.set_loopback = genphy_loopback,
|
.set_loopback = genphy_loopback,
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
|||||||
@ -88,6 +88,7 @@ static int dma_remap_suspend_late(struct device *dev)
|
|||||||
|
|
||||||
static int dma_remap_resume_early(struct device *dev)
|
static int dma_remap_resume_early(struct device *dev)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
val = UPDATE_REMAP
|
val = UPDATE_REMAP
|
||||||
@ -106,6 +107,22 @@ static int dma_remap_resume_early(struct device *dev)
|
|||||||
|
|
||||||
writel(val, remap_subsys_base + 0x4);
|
writel(val, remap_subsys_base + 0x4);
|
||||||
|
|
||||||
|
if (device_property_present(&pdev->dev, "int_mux_base") &&
|
||||||
|
device_property_present(&pdev->dev, "int_mux")) {
|
||||||
|
u32 int_mux_base = 0;
|
||||||
|
u32 int_mux = 0;
|
||||||
|
void __iomem *int_mux_reg;
|
||||||
|
|
||||||
|
/* Set sysDMA interrupt receiver of IC after CV181X */
|
||||||
|
device_property_read_u32(&pdev->dev, "int_mux_base", &int_mux_base);
|
||||||
|
if (int_mux_base != 0x0) {
|
||||||
|
int_mux_reg = ioremap(int_mux_base, 0x4);
|
||||||
|
device_property_read_u32(&pdev->dev, "int_mux", &int_mux);
|
||||||
|
writel(int_mux, int_mux_reg);
|
||||||
|
iounmap(int_mux_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -347,6 +347,27 @@ static const struct acpi_device_id dw_spi_mmio_acpi_match[] = {
|
|||||||
MODULE_DEVICE_TABLE(acpi, dw_spi_mmio_acpi_match);
|
MODULE_DEVICE_TABLE(acpi, dw_spi_mmio_acpi_match);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int dw_spi_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct dw_spi *dws = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
dws->dw_spi_div = dw_readl(dws, DW_SPI_BAUDR);
|
||||||
|
dw_spi_remove_host(dws);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_spi_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct dw_spi *dws = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
spi_set_clk(dws, dws->dw_spi_div);
|
||||||
|
return dw_spi_add_host(dev, dws);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(dw_spi_pm_ops, dw_spi_suspend, dw_spi_resume);
|
||||||
|
|
||||||
static struct platform_driver dw_spi_mmio_driver = {
|
static struct platform_driver dw_spi_mmio_driver = {
|
||||||
.probe = dw_spi_mmio_probe,
|
.probe = dw_spi_mmio_probe,
|
||||||
.remove = dw_spi_mmio_remove,
|
.remove = dw_spi_mmio_remove,
|
||||||
@ -354,6 +375,7 @@ static struct platform_driver dw_spi_mmio_driver = {
|
|||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.of_match_table = dw_spi_mmio_of_match,
|
.of_match_table = dw_spi_mmio_of_match,
|
||||||
.acpi_match_table = ACPI_PTR(dw_spi_mmio_acpi_match),
|
.acpi_match_table = ACPI_PTR(dw_spi_mmio_acpi_match),
|
||||||
|
.pm = &dw_spi_pm_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(dw_spi_mmio_driver);
|
module_platform_driver(dw_spi_mmio_driver);
|
||||||
|
|||||||
@ -185,6 +185,10 @@ struct dw_spi {
|
|||||||
const struct dw_spi_dma_ops *dma_ops;
|
const struct dw_spi_dma_ops *dma_ops;
|
||||||
struct completion dma_completion;
|
struct completion dma_completion;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
u32 dw_spi_div;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *debugfs;
|
struct dentry *debugfs;
|
||||||
struct debugfs_regset32 regset;
|
struct debugfs_regset32 regset;
|
||||||
|
|||||||
@ -5,6 +5,7 @@ config USB_DWC2
|
|||||||
depends on HAS_DMA
|
depends on HAS_DMA
|
||||||
depends on USB || USB_GADGET
|
depends on USB || USB_GADGET
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM
|
||||||
|
select USB_ROLE_SWITCH
|
||||||
help
|
help
|
||||||
Say Y here if your system has a Dual Role Hi-Speed USB
|
Say Y here if your system has a Dual Role Hi-Speed USB
|
||||||
controller based on the DesignWare HSOTG IP Core.
|
controller based on the DesignWare HSOTG IP Core.
|
||||||
|
|||||||
73
linux_5.10/include/uapi/linux/cvitek_spacc.h
Normal file
73
linux_5.10/include/uapi/linux/cvitek_spacc.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
#ifndef _CVITEK_SPACC_H_
|
||||||
|
#define _CVITEK_SPACC_H_
|
||||||
|
|
||||||
|
typedef enum SPACC_ALGO {
|
||||||
|
SPACC_ALGO_AES,
|
||||||
|
SPACC_ALGO_DES,
|
||||||
|
SPACC_ALGO_TDES,
|
||||||
|
SPACC_ALGO_SM4,
|
||||||
|
SPACC_ALGO_SHA1,
|
||||||
|
SPACC_ALGO_SHA256,
|
||||||
|
SPACC_ALGO_BASE64,
|
||||||
|
} SPACC_ALGO_E;
|
||||||
|
|
||||||
|
typedef enum SPACC_ALGO_MODE {
|
||||||
|
SPACC_ALGO_MODE_ECB,
|
||||||
|
SPACC_ALGO_MODE_CBC, //cv180x Not Supported
|
||||||
|
SPACC_ALGO_MODE_CTR, //cv180x Not Supported
|
||||||
|
SPACC_ALGO_MODE_OFB, //cv180x Not Supported
|
||||||
|
} SPACC_ALGO_MODE_E;
|
||||||
|
|
||||||
|
typedef enum SPACC_KEY_SIZE {
|
||||||
|
SPACC_KEY_SIZE_64BITS,
|
||||||
|
SPACC_KEY_SIZE_128BITS,
|
||||||
|
SPACC_KEY_SIZE_192BITS,
|
||||||
|
SPACC_KEY_SIZE_256BITS,
|
||||||
|
} SPACC_KEY_SIZE_E;
|
||||||
|
|
||||||
|
typedef enum SPACC_ACTION {
|
||||||
|
SPACC_ACTION_ENCRYPTION,
|
||||||
|
SPACC_ACTION_DECRYPT,
|
||||||
|
} SPACC_ACTION_E;
|
||||||
|
|
||||||
|
typedef struct spacc_base64_action {
|
||||||
|
SPACC_ACTION_E action;
|
||||||
|
} spacc_base64_action_s;
|
||||||
|
|
||||||
|
typedef struct spacc_aes_config {
|
||||||
|
// data config
|
||||||
|
void *src; //src phy address
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
// spacc config
|
||||||
|
unsigned char key[32];
|
||||||
|
unsigned char iv[16];
|
||||||
|
SPACC_ALGO_MODE_E mode;
|
||||||
|
SPACC_KEY_SIZE_E size;
|
||||||
|
SPACC_ACTION_E action;
|
||||||
|
} spacc_aes_config_s;
|
||||||
|
|
||||||
|
typedef struct spacc_des_config {
|
||||||
|
unsigned char key[24];
|
||||||
|
unsigned char iv[16];
|
||||||
|
SPACC_ALGO_MODE_E mode;
|
||||||
|
SPACC_ACTION_E action;
|
||||||
|
} spacc_des_config_s;
|
||||||
|
|
||||||
|
typedef spacc_aes_config_s spacc_sm4_config_s;
|
||||||
|
typedef spacc_des_config_s spacc_tdes_config_s;
|
||||||
|
|
||||||
|
#define IOCTL_SPACC_BASE 'S'
|
||||||
|
#define IOCTL_SPACC_CREATE_MEMPOOL _IOW(IOCTL_SPACC_BASE, 1, unsigned int)
|
||||||
|
#define IOCTL_SPACC_GET_MEMPOOL_SIZE _IOR(IOCTL_SPACC_BASE, 2, unsigned int)
|
||||||
|
|
||||||
|
#define IOCTL_SPACC_SHA256_ACTION _IO(IOCTL_SPACC_BASE, 5)
|
||||||
|
#define IOCTL_SPACC_SHA1_ACTION _IO(IOCTL_SPACC_BASE, 6)
|
||||||
|
#define IOCTL_SPACC_BASE64_ACTION _IOW(IOCTL_SPACC_BASE, 7, spacc_base64_action_s)
|
||||||
|
#define IOCTL_SPACC_AES_ACTION _IOW(IOCTL_SPACC_BASE, 8, spacc_aes_config_s)
|
||||||
|
#define IOCTL_SPACC_SM4_ACTION _IOW(IOCTL_SPACC_BASE, 9, spacc_sm4_config_s)
|
||||||
|
#define IOCTL_SPACC_DES_ACTION _IOW(IOCTL_SPACC_BASE, 10, spacc_des_config_s)
|
||||||
|
#define IOCTL_SPACC_TDES_ACTION _IOW(IOCTL_SPACC_BASE, 11, spacc_tdes_config_s)
|
||||||
|
|
||||||
|
#endif // _CVITEK_SPACC_H_
|
||||||
@ -12,17 +12,32 @@
|
|||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
|
|
||||||
|
// #define PDM_AEC
|
||||||
|
|
||||||
/* register offset */
|
/* register offset */
|
||||||
#define PDM_EN_REG 0x30
|
#define PDM_EN_REG 0x30
|
||||||
#define PDM_EN 0x1
|
#define PDM_EN 0x1
|
||||||
#define PDM_OFF 0x0
|
#define PDM_OFF 0x0
|
||||||
|
|
||||||
|
#ifdef PDM_AEC
|
||||||
|
//for 16384M audio clk
|
||||||
|
#define PDM_48K 2
|
||||||
|
#define PDM_44_1K 2
|
||||||
|
#define PDM_32K 3
|
||||||
|
#define PDM_22_05K 4
|
||||||
|
#define PDM_16K 7
|
||||||
|
#define PDM_11_025K 10
|
||||||
|
#define PDM_8K 15
|
||||||
|
#else
|
||||||
|
//for 24576M audio clk
|
||||||
#define PDM_48K 3
|
#define PDM_48K 3
|
||||||
#define PDM_44_1K 3
|
#define PDM_44_1K 3
|
||||||
#define PDM_22_05K 7
|
#define PDM_22_05K 7
|
||||||
#define PDM_16K 11
|
#define PDM_16K 11
|
||||||
#define PDM_11_025K 15
|
#define PDM_11_025K 15
|
||||||
#define PDM_8K 23
|
#define PDM_8K 23
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PDM_SETTING_REG 0x34
|
#define PDM_SETTING_REG 0x34
|
||||||
#define PDM_CLK_DIV_MASK 0xFFFFFFE0
|
#define PDM_CLK_DIV_MASK 0xFFFFFFE0
|
||||||
@ -34,13 +49,26 @@
|
|||||||
#define PDM_BOND_SEL_0 (0 << 24)
|
#define PDM_BOND_SEL_0 (0 << 24)
|
||||||
#define PDM_BOND_SEL_1 (1 << 24)
|
#define PDM_BOND_SEL_1 (1 << 24)
|
||||||
|
|
||||||
|
#ifdef PDM_AEC
|
||||||
|
//for 16384M audio clk
|
||||||
|
#define I2S_48K 4
|
||||||
|
#define I2S_44_1K 4
|
||||||
|
#define I2S_32K 7
|
||||||
|
#define I2S_22_05K 10
|
||||||
|
#define I2S_16K 15
|
||||||
|
#define I2S_11_025K 20
|
||||||
|
#define I2S_8K 31
|
||||||
|
#else
|
||||||
|
//for 24576M audio clk
|
||||||
#define I2S_48K 7
|
#define I2S_48K 7
|
||||||
#define I2S_44_1K 7
|
#define I2S_44_1K 7
|
||||||
#define I2S_22_05K 15
|
#define I2S_22_05K 15
|
||||||
#define I2S_16K 23
|
#define I2S_16K 23
|
||||||
#define I2S_11_025K 31
|
#define I2S_11_025K 31
|
||||||
#define I2S_8K 47
|
#define I2S_8K 47
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define I2S_SETTING_REG 0x38
|
#define I2S_SETTING_REG 0x38
|
||||||
#define I2S_CLK_DIV_MASK 0xFFFFFF00
|
#define I2S_CLK_DIV_MASK 0xFFFFFF00
|
||||||
#define I2S_CLK_DIV(v) (v << 0)
|
#define I2S_CLK_DIV(v) (v << 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user