Skip to content
Snippets Groups Projects
Commit c6188dff authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'csky-for-linus-5.6-rc3' of git://github.com/c-sky/csky-linux

Pull csky updates from Guo Ren:
 "Sorry, I missed 5.6-rc1 merge window, but in this pull request the
  most are the fixes and the rests are between fixes and features. The
  only outside modification is the MAINTAINERS file update with our
  mailing list.

   - cache flush implementation fixes

   - ftrace modify panic fix

   - CONFIG_SMP boot problem fix

   - fix pt_regs saving for atomic.S

   - fix fixaddr_init without highmem.

   - fix stack protector support

   - fix fake Tightly-Coupled Memory code compile and use

   - fix some typos and coding convention"

* tag 'csky-for-linus-5.6-rc3' of git://github.com/c-sky/csky-linux: (23 commits)
  csky: Replace <linux/clk-provider.h> by <linux/of_clk.h>
  csky: Implement copy_thread_tls
  csky: Add PCI support
  csky: Minimize defconfig to support buildroot config.fragment
  csky: Add setup_initrd check code
  csky: Cleanup old Kconfig options
  arch/csky: fix some Kconfig typos
  csky: Fixup compile warning for three unimplemented syscalls
  csky: Remove unused cache implementation
  csky: Fixup ftrace modify panic
  csky: Add flush_icache_mm to defer flush icache all
  csky: Optimize abiv2 copy_to_user_page with VM_EXEC
  csky: Enable defer flush_dcache_page for abiv2 cpus (807/810/860)
  csky: Remove unnecessary flush_icache_* implementation
  csky: Support icache flush without specific instructions
  csky/Kconfig: Add Kconfig.platforms to support some drivers
  csky/smp: Fixup boot failed when CONFIG_SMP
  csky: Set regs->usp to kernel sp, when the exception is from kernel
  csky/mm: Fixup export invalid_pte_table symbol
  csky: Separate fixaddr_init from highmem
  ...
parents dca132a6 99db590b
No related branches found
No related tags found
No related merge requests found
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#define __ARCH_WANT_STAT64
#define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_CLONE
#define __ARCH_WANT_SYS_CLONE3
#define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_SET_GET_RLIMIT
#define __ARCH_WANT_TIME32_SYSCALLS #define __ARCH_WANT_TIME32_SYSCALLS
#include <asm-generic/unistd.h> #include <asm-generic/unistd.h>
......
...@@ -17,10 +17,12 @@ ENTRY(csky_cmpxchg) ...@@ -17,10 +17,12 @@ ENTRY(csky_cmpxchg)
mfcr a3, epc mfcr a3, epc
addi a3, TRAP0_SIZE addi a3, TRAP0_SIZE
subi sp, 8 subi sp, 16
stw a3, (sp, 0) stw a3, (sp, 0)
mfcr a3, epsr mfcr a3, epsr
stw a3, (sp, 4) stw a3, (sp, 4)
mfcr a3, usp
stw a3, (sp, 8)
psrset ee psrset ee
#ifdef CONFIG_CPU_HAS_LDSTEX #ifdef CONFIG_CPU_HAS_LDSTEX
...@@ -47,7 +49,9 @@ ENTRY(csky_cmpxchg) ...@@ -47,7 +49,9 @@ ENTRY(csky_cmpxchg)
mtcr a3, epc mtcr a3, epc
ldw a3, (sp, 4) ldw a3, (sp, 4)
mtcr a3, epsr mtcr a3, epsr
addi sp, 8 ldw a3, (sp, 8)
mtcr a3, usp
addi sp, 16
KSPTOUSP KSPTOUSP
rte rte
END(csky_cmpxchg) END(csky_cmpxchg)
......
...@@ -16,6 +16,12 @@ ...@@ -16,6 +16,12 @@
struct cpuinfo_csky cpu_data[NR_CPUS]; struct cpuinfo_csky cpu_data[NR_CPUS];
#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif
asmlinkage void ret_from_fork(void); asmlinkage void ret_from_fork(void);
asmlinkage void ret_from_kernel_thread(void); asmlinkage void ret_from_kernel_thread(void);
...@@ -34,10 +40,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk) ...@@ -34,10 +40,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return sw->r15; return sw->r15;
} }
int copy_thread(unsigned long clone_flags, int copy_thread_tls(unsigned long clone_flags,
unsigned long usp, unsigned long usp,
unsigned long kthread_arg, unsigned long kthread_arg,
struct task_struct *p) struct task_struct *p,
unsigned long tls)
{ {
struct switch_stack *childstack; struct switch_stack *childstack;
struct pt_regs *childregs = task_pt_regs(p); struct pt_regs *childregs = task_pt_regs(p);
...@@ -64,7 +71,7 @@ int copy_thread(unsigned long clone_flags, ...@@ -64,7 +71,7 @@ int copy_thread(unsigned long clone_flags,
childregs->usp = usp; childregs->usp = usp;
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
task_thread_info(p)->tp_value = childregs->tls task_thread_info(p)->tp_value = childregs->tls
= childregs->regs[0]; = tls;
childregs->a0 = 0; childregs->a0 = 0;
childstack->r15 = (unsigned long) ret_from_fork; childstack->r15 = (unsigned long) ret_from_fork;
......
...@@ -47,9 +47,6 @@ static void __init csky_memblock_init(void) ...@@ -47,9 +47,6 @@ static void __init csky_memblock_init(void)
signed long size; signed long size;
memblock_reserve(__pa(_stext), _end - _stext); memblock_reserve(__pa(_stext), _end - _stext);
#ifdef CONFIG_BLK_DEV_INITRD
memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
#endif
early_init_fdt_reserve_self(); early_init_fdt_reserve_self();
early_init_fdt_scan_reserved_mem(); early_init_fdt_scan_reserved_mem();
...@@ -133,6 +130,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -133,6 +130,8 @@ void __init setup_arch(char **cmdline_p)
sparse_init(); sparse_init();
fixaddr_init();
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
kmap_init(); kmap_init();
#endif #endif
......
...@@ -120,7 +120,7 @@ void __init setup_smp_ipi(void) ...@@ -120,7 +120,7 @@ void __init setup_smp_ipi(void)
int rc; int rc;
if (ipi_irq == 0) if (ipi_irq == 0)
panic("%s IRQ mapping failed\n", __func__); return;
rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt",
&ipi_dummy_dev); &ipi_dummy_dev);
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#include <linux/clk-provider.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/of_clk.h>
void __init time_init(void) void __init time_init(void)
{ {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <asm/vmlinux.lds.h> #include <asm/vmlinux.lds.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/memory.h>
OUTPUT_ARCH(csky) OUTPUT_ARCH(csky)
ENTRY(_start) ENTRY(_start)
...@@ -53,6 +54,54 @@ SECTIONS ...@@ -53,6 +54,54 @@ SECTIONS
RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .; _edata = .;
#ifdef CONFIG_HAVE_TCM
.tcm_start : {
. = ALIGN(PAGE_SIZE);
__tcm_start = .;
}
.text_data_tcm FIXADDR_TCM : AT(__tcm_start)
{
. = ALIGN(4);
__stcm_text_data = .;
*(.tcm.text)
*(.tcm.rodata)
#ifndef CONFIG_HAVE_DTCM
*(.tcm.data)
#endif
. = ALIGN(4);
__etcm_text_data = .;
}
. = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_data_tcm);
#ifdef CONFIG_HAVE_DTCM
#define ITCM_SIZE CONFIG_ITCM_NR_PAGES * PAGE_SIZE
.dtcm_start : {
__dtcm_start = .;
}
.data_tcm FIXADDR_TCM + ITCM_SIZE : AT(__dtcm_start)
{
. = ALIGN(4);
__stcm_data = .;
*(.tcm.data)
. = ALIGN(4);
__etcm_data = .;
}
. = ADDR(.dtcm_start) + SIZEOF(.data_tcm);
.tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_tcm)) {
#else
.tcm_end : AT(ADDR(.tcm_start) + SIZEOF(.text_data_tcm)) {
#endif
. = ALIGN(PAGE_SIZE);
__tcm_end = .;
}
#endif
EXCEPTION_TABLE(L1_CACHE_BYTES) EXCEPTION_TABLE(L1_CACHE_BYTES)
BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES) BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES)
VBR_BASE VBR_BASE
......
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
ifeq ($(CONFIG_CPU_HAS_CACHEV2),y) ifeq ($(CONFIG_CPU_HAS_CACHEV2),y)
obj-y += cachev2.o obj-y += cachev2.o
CFLAGS_REMOVE_cachev2.o = $(CC_FLAGS_FTRACE)
else else
obj-y += cachev1.o obj-y += cachev1.o
CFLAGS_REMOVE_cachev1.o = $(CC_FLAGS_FTRACE)
endif endif
obj-y += dma-mapping.o obj-y += dma-mapping.o
...@@ -14,3 +16,4 @@ obj-y += syscache.o ...@@ -14,3 +16,4 @@ obj-y += syscache.o
obj-y += tlb.o obj-y += tlb.o
obj-y += asid.o obj-y += asid.o
obj-y += context.o obj-y += context.o
obj-$(CONFIG_HAVE_TCM) += tcm.o
...@@ -94,6 +94,11 @@ void icache_inv_all(void) ...@@ -94,6 +94,11 @@ void icache_inv_all(void)
cache_op_all(INS_CACHE|CACHE_INV, 0); cache_op_all(INS_CACHE|CACHE_INV, 0);
} }
void local_icache_inv_all(void *priv)
{
cache_op_all(INS_CACHE|CACHE_INV, 0);
}
void dcache_wb_range(unsigned long start, unsigned long end) void dcache_wb_range(unsigned long start, unsigned long end)
{ {
cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0); cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
......
...@@ -3,15 +3,25 @@ ...@@ -3,15 +3,25 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/mm.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/barrier.h> #include <asm/barrier.h>
inline void dcache_wb_line(unsigned long start) #define INS_CACHE (1 << 0)
#define CACHE_INV (1 << 4)
void local_icache_inv_all(void *priv)
{ {
asm volatile("dcache.cval1 %0\n"::"r"(start):"memory"); mtcr("cr17", INS_CACHE|CACHE_INV);
sync_is(); sync_is();
} }
void icache_inv_all(void)
{
on_each_cpu(local_icache_inv_all, NULL, 1);
}
#ifdef CONFIG_CPU_HAS_ICACHE_INS
void icache_inv_range(unsigned long start, unsigned long end) void icache_inv_range(unsigned long start, unsigned long end)
{ {
unsigned long i = start & ~(L1_CACHE_BYTES - 1); unsigned long i = start & ~(L1_CACHE_BYTES - 1);
...@@ -20,43 +30,32 @@ void icache_inv_range(unsigned long start, unsigned long end) ...@@ -20,43 +30,32 @@ void icache_inv_range(unsigned long start, unsigned long end)
asm volatile("icache.iva %0\n"::"r"(i):"memory"); asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is(); sync_is();
} }
#else
void icache_inv_all(void) void icache_inv_range(unsigned long start, unsigned long end)
{ {
asm volatile("icache.ialls\n":::"memory"); icache_inv_all();
sync_is();
} }
#endif
void dcache_wb_range(unsigned long start, unsigned long end) inline void dcache_wb_line(unsigned long start)
{ {
unsigned long i = start & ~(L1_CACHE_BYTES - 1); asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
for (; i < end; i += L1_CACHE_BYTES)
asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is(); sync_is();
} }
void dcache_inv_range(unsigned long start, unsigned long end) void dcache_wb_range(unsigned long start, unsigned long end)
{ {
unsigned long i = start & ~(L1_CACHE_BYTES - 1); unsigned long i = start & ~(L1_CACHE_BYTES - 1);
for (; i < end; i += L1_CACHE_BYTES) for (; i < end; i += L1_CACHE_BYTES)
asm volatile("dcache.civa %0\n"::"r"(i):"memory"); asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is(); sync_is();
} }
void cache_wbinv_range(unsigned long start, unsigned long end) void cache_wbinv_range(unsigned long start, unsigned long end)
{ {
unsigned long i = start & ~(L1_CACHE_BYTES - 1); dcache_wb_range(start, end);
icache_inv_range(start, end);
for (; i < end; i += L1_CACHE_BYTES)
asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is();
i = start & ~(L1_CACHE_BYTES - 1);
for (; i < end; i += L1_CACHE_BYTES)
asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is();
} }
EXPORT_SYMBOL(cache_wbinv_range); EXPORT_SYMBOL(cache_wbinv_range);
......
...@@ -117,85 +117,29 @@ struct page *kmap_atomic_to_page(void *ptr) ...@@ -117,85 +117,29 @@ struct page *kmap_atomic_to_page(void *ptr)
return pte_page(*pte); return pte_page(*pte);
} }
static void __init fixrange_init(unsigned long start, unsigned long end, static void __init kmap_pages_init(void)
pgd_t *pgd_base)
{ {
#ifdef CONFIG_HIGHMEM
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
int i, j, k;
unsigned long vaddr; unsigned long vaddr;
vaddr = start;
i = __pgd_offset(vaddr);
j = __pud_offset(vaddr);
k = __pmd_offset(vaddr);
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
pud = (pud_t *)pgd;
for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
pmd = (pmd_t *)pud;
for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
if (pmd_none(*pmd)) {
pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pte)
panic("%s: Failed to allocate %lu bytes align=%lx\n",
__func__, PAGE_SIZE,
PAGE_SIZE);
set_pmd(pmd, __pmd(__pa(pte)));
BUG_ON(pte != pte_offset_kernel(pmd, 0));
}
vaddr += PMD_SIZE;
}
k = 0;
}
j = 0;
}
#endif
}
void __init fixaddr_kmap_pages_init(void)
{
unsigned long vaddr;
pgd_t *pgd_base;
#ifdef CONFIG_HIGHMEM
pgd_t *pgd; pgd_t *pgd;
pmd_t *pmd; pmd_t *pmd;
pud_t *pud; pud_t *pud;
pte_t *pte; pte_t *pte;
#endif
pgd_base = swapper_pg_dir;
/*
* Fixed mappings:
*/
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
fixrange_init(vaddr, 0, pgd_base);
#ifdef CONFIG_HIGHMEM
/*
* Permanent kmaps:
*/
vaddr = PKMAP_BASE; vaddr = PKMAP_BASE;
fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
pgd = swapper_pg_dir + __pgd_offset(vaddr); pgd = swapper_pg_dir + __pgd_offset(vaddr);
pud = (pud_t *)pgd; pud = (pud_t *)pgd;
pmd = pmd_offset(pud, vaddr); pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr); pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte; pkmap_page_table = pte;
#endif
} }
void __init kmap_init(void) void __init kmap_init(void)
{ {
unsigned long vaddr; unsigned long vaddr;
fixaddr_kmap_pages_init(); kmap_pages_init();
vaddr = __fix_to_virt(FIX_KMAP_BEGIN); vaddr = __fix_to_virt(FIX_KMAP_BEGIN);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/initrd.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/cachectl.h> #include <asm/cachectl.h>
...@@ -31,10 +32,50 @@ ...@@ -31,10 +32,50 @@
pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
EXPORT_SYMBOL(invalid_pte_table);
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
__page_aligned_bss; __page_aligned_bss;
EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(empty_zero_page);
#ifdef CONFIG_BLK_DEV_INITRD
static void __init setup_initrd(void)
{
unsigned long size;
if (initrd_start >= initrd_end) {
pr_err("initrd not found or empty");
goto disable;
}
if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
pr_err("initrd extends beyond end of memory");
goto disable;
}
size = initrd_end - initrd_start;
if (memblock_is_region_reserved(__pa(initrd_start), size)) {
pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region",
__pa(initrd_start), size);
goto disable;
}
memblock_reserve(__pa(initrd_start), size);
pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
(void *)(initrd_start), size);
initrd_below_start_ok = 1;
return;
disable:
initrd_start = initrd_end = 0;
pr_err(" - disabling initrd\n");
}
#endif
void __init mem_init(void) void __init mem_init(void)
{ {
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
...@@ -46,6 +87,10 @@ void __init mem_init(void) ...@@ -46,6 +87,10 @@ void __init mem_init(void)
#endif #endif
high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
#ifdef CONFIG_BLK_DEV_INITRD
setup_initrd();
#endif
memblock_free_all(); memblock_free_all();
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
...@@ -101,3 +146,50 @@ void __init pre_mmu_init(void) ...@@ -101,3 +146,50 @@ void __init pre_mmu_init(void)
/* Setup page mask to 4k */ /* Setup page mask to 4k */
write_mmu_pagemask(0); write_mmu_pagemask(0);
} }
void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
int i, j, k;
unsigned long vaddr;
vaddr = start;
i = __pgd_offset(vaddr);
j = __pud_offset(vaddr);
k = __pmd_offset(vaddr);
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
pud = (pud_t *)pgd;
for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
pmd = (pmd_t *)pud;
for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
if (pmd_none(*pmd)) {
pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pte)
panic("%s: Failed to allocate %lu bytes align=%lx\n",
__func__, PAGE_SIZE,
PAGE_SIZE);
set_pmd(pmd, __pmd(__pa(pte)));
BUG_ON(pte != pte_offset_kernel(pmd, 0));
}
vaddr += PMD_SIZE;
}
k = 0;
}
j = 0;
}
}
void __init fixaddr_init(void)
{
unsigned long vaddr;
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
fixrange_init(vaddr, vaddr + PMD_SIZE, swapper_pg_dir);
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/cache.h> #include <asm/cacheflush.h>
#include <asm/cachectl.h> #include <asm/cachectl.h>
SYSCALL_DEFINE3(cacheflush, SYSCALL_DEFINE3(cacheflush,
...@@ -13,17 +13,14 @@ SYSCALL_DEFINE3(cacheflush, ...@@ -13,17 +13,14 @@ SYSCALL_DEFINE3(cacheflush,
{ {
switch (cache) { switch (cache) {
case ICACHE: case ICACHE:
icache_inv_range((unsigned long)addr, case BCACHE:
flush_icache_mm_range(current->mm,
(unsigned long)addr,
(unsigned long)addr + bytes); (unsigned long)addr + bytes);
break;
case DCACHE: case DCACHE:
dcache_wb_range((unsigned long)addr, dcache_wb_range((unsigned long)addr,
(unsigned long)addr + bytes); (unsigned long)addr + bytes);
break; break;
case BCACHE:
cache_wbinv_range((unsigned long)addr,
(unsigned long)addr + bytes);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/highmem.h>
#include <linux/genalloc.h>
#include <asm/tlbflush.h>
#include <asm/fixmap.h>
#if (CONFIG_ITCM_RAM_BASE == 0xffffffff)
#error "You should define ITCM_RAM_BASE"
#endif
#ifdef CONFIG_HAVE_DTCM
#if (CONFIG_DTCM_RAM_BASE == 0xffffffff)
#error "You should define DTCM_RAM_BASE"
#endif
#if (CONFIG_DTCM_RAM_BASE == CONFIG_ITCM_RAM_BASE)
#error "You should define correct DTCM_RAM_BASE"
#endif
#endif
extern char __tcm_start, __tcm_end, __dtcm_start;
static struct gen_pool *tcm_pool;
static void __init tcm_mapping_init(void)
{
pte_t *tcm_pte;
unsigned long vaddr, paddr;
int i;
paddr = CONFIG_ITCM_RAM_BASE;
if (pfn_valid(PFN_DOWN(CONFIG_ITCM_RAM_BASE)))
goto panic;
#ifndef CONFIG_HAVE_DTCM
for (i = 0; i < TCM_NR_PAGES; i++) {
#else
for (i = 0; i < CONFIG_ITCM_NR_PAGES; i++) {
#endif
vaddr = __fix_to_virt(FIX_TCM - i);
tcm_pte =
pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr);
set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
flush_tlb_one(vaddr);
paddr = paddr + PAGE_SIZE;
}
#ifdef CONFIG_HAVE_DTCM
if (pfn_valid(PFN_DOWN(CONFIG_DTCM_RAM_BASE)))
goto panic;
paddr = CONFIG_DTCM_RAM_BASE;
for (i = 0; i < CONFIG_DTCM_NR_PAGES; i++) {
vaddr = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES - i);
tcm_pte =
pte_offset_kernel((pmd_t *) pgd_offset_k(vaddr), vaddr);
set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
flush_tlb_one(vaddr);
paddr = paddr + PAGE_SIZE;
}
#endif
#ifndef CONFIG_HAVE_DTCM
memcpy((void *)__fix_to_virt(FIX_TCM),
&__tcm_start, &__tcm_end - &__tcm_start);
pr_info("%s: mapping tcm va:0x%08lx to pa:0x%08x\n",
__func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
pr_info("%s: __tcm_start va:0x%08lx size:%d\n",
__func__, (unsigned long)&__tcm_start, &__tcm_end - &__tcm_start);
#else
memcpy((void *)__fix_to_virt(FIX_TCM),
&__tcm_start, &__dtcm_start - &__tcm_start);
pr_info("%s: mapping itcm va:0x%08lx to pa:0x%08x\n",
__func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
pr_info("%s: __itcm_start va:0x%08lx size:%d\n",
__func__, (unsigned long)&__tcm_start, &__dtcm_start - &__tcm_start);
memcpy((void *)__fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
&__dtcm_start, &__tcm_end - &__dtcm_start);
pr_info("%s: mapping dtcm va:0x%08lx to pa:0x%08x\n",
__func__, __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
CONFIG_DTCM_RAM_BASE);
pr_info("%s: __dtcm_start va:0x%08lx size:%d\n",
__func__, (unsigned long)&__dtcm_start, &__tcm_end - &__dtcm_start);
#endif
return;
panic:
panic("TCM init error");
}
void *tcm_alloc(size_t len)
{
unsigned long vaddr;
if (!tcm_pool)
return NULL;
vaddr = gen_pool_alloc(tcm_pool, len);
if (!vaddr)
return NULL;
return (void *) vaddr;
}
EXPORT_SYMBOL(tcm_alloc);
void tcm_free(void *addr, size_t len)
{
gen_pool_free(tcm_pool, (unsigned long) addr, len);
}
EXPORT_SYMBOL(tcm_free);
static int __init tcm_setup_pool(void)
{
#ifndef CONFIG_HAVE_DTCM
u32 pool_size = (u32) (TCM_NR_PAGES * PAGE_SIZE)
- (u32) (&__tcm_end - &__tcm_start);
u32 tcm_pool_start = __fix_to_virt(FIX_TCM)
+ (u32) (&__tcm_end - &__tcm_start);
#else
u32 pool_size = (u32) (CONFIG_DTCM_NR_PAGES * PAGE_SIZE)
- (u32) (&__tcm_end - &__dtcm_start);
u32 tcm_pool_start = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES)
+ (u32) (&__tcm_end - &__dtcm_start);
#endif
int ret;
tcm_pool = gen_pool_create(2, -1);
ret = gen_pool_add(tcm_pool, tcm_pool_start, pool_size, -1);
if (ret) {
pr_err("%s: gen_pool add failed!\n", __func__);
return ret;
}
pr_info("%s: Added %d bytes @ 0x%08x to memory pool\n",
__func__, pool_size, tcm_pool_start);
return 0;
}
static int __init tcm_init(void)
{
tcm_mapping_init();
tcm_setup_pool();
return 0;
}
arch_initcall(tcm_init);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment