You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'xtensa-next-20140123' of git://github.com/czankel/xtensa-linux
Pull Xtensa patches from Chris Zankel: "The major changes are adding support for SMP for Xtensa, fixing and cleaning up the ISS (simulator) network driver, and better support for device trees" * tag 'xtensa-next-20140123' of git://github.com/czankel/xtensa-linux: (40 commits) xtensa: implement ndelay xtensa: clean up udelay xtensa: enable HAVE_PERF_EVENTS xtensa: remap io area defined in device tree xtensa: support default device tree buses xtensa: initialize device tree clock sources xtensa: xtfpga: fix definitions of platform devices xtensa: standardize devicetree cpu compatible strings xtensa: avoid duplicate of IO range definitions xtensa: fix ATOMCTL register documentation xtensa: Enable irqs after cpu is set online xtensa: ISS: raise network polling rate to 10 times/sec xtensa: remove unused XTENSA_ISS_NETWORK Kconfig parameter xtensa: ISS: avoid simple_strtoul usage xtensa: Switch to sched_clock_register() xtensa: implement CPU hotplug xtensa: add SMP support xtensa: add MX irqchip xtensa: clear timer IRQ unconditionally in its handler xtensa: clean up do_interrupt/do_IRQ ...
This commit is contained in:
@@ -40,5 +40,5 @@ See Section 4.3.12.4 of ISA; Bits:
|
||||
--------- --------------- ----------------- ----------------
|
||||
0 Exception Exception Exception
|
||||
1 RCW Transaction RCW Transaction RCW Transaction
|
||||
2 Internal Operation Exception Reserved
|
||||
2 Internal Operation Internal Operation Reserved
|
||||
3 Reserved Reserved Reserved
|
||||
|
||||
@@ -44,3 +44,21 @@ After step 4, we jump to intended (linked) address of this code.
|
||||
40..5F -> 40 40..5F -> pc -> pc 40..5F -> pc
|
||||
20..3F -> 20 -> 20 20..3F -> 20
|
||||
00..1F -> 00 -> 00 00..1F -> 00
|
||||
|
||||
The default location of IO peripherals is above 0xf0000000. This may change
|
||||
using a "ranges" property in a device tree simple-bus node. See ePAPR 1.1, §6.5
|
||||
for details on the syntax and semantic of simple-bus nodes. The following
|
||||
limitations apply:
|
||||
|
||||
1. Only top level simple-bus nodes are considered
|
||||
|
||||
2. Only one (first) simple-bus node is considered
|
||||
|
||||
3. Empty "ranges" properties are not supported
|
||||
|
||||
4. Only the first triplet in the "ranges" property is considered
|
||||
|
||||
5. The parent-bus-address value is rounded down to the nearest 256MB boundary
|
||||
|
||||
6. The IO area covers the entire 256MB segment of parent-bus-address; the
|
||||
"ranges" triplet length field is ignored
|
||||
|
||||
+47
-5
@@ -9,7 +9,6 @@ config XTENSA
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select VIRT_TO_BUS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_PCI_IOMAP
|
||||
@@ -19,6 +18,8 @@ config XTENSA
|
||||
select IRQ_DOMAIN
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_IRQ_TIME_ACCOUNTING
|
||||
select HAVE_PERF_EVENTS
|
||||
help
|
||||
Xtensa processors are 32-bit RISC machines designed by Tensilica
|
||||
primarily for embedded systems. These processors are both
|
||||
@@ -67,6 +68,9 @@ config VARIANT_IRQ_SWITCH
|
||||
config HAVE_XTENSA_GPIO32
|
||||
def_bool n
|
||||
|
||||
config MAY_HAVE_SMP
|
||||
def_bool n
|
||||
|
||||
menu "Processor type and features"
|
||||
|
||||
choice
|
||||
@@ -110,6 +114,48 @@ config XTENSA_UNALIGNED_USER
|
||||
|
||||
source "kernel/Kconfig.preempt"
|
||||
|
||||
config HAVE_SMP
|
||||
bool "System Supports SMP (MX)"
|
||||
depends on MAY_HAVE_SMP
|
||||
select XTENSA_MX
|
||||
help
|
||||
This option is use to indicate that the system-on-a-chip (SOC)
|
||||
supports Multiprocessing. Multiprocessor support implemented above
|
||||
the CPU core definition and currently needs to be selected manually.
|
||||
|
||||
Multiprocessor support in implemented with external cache and
|
||||
interrupt controlers.
|
||||
|
||||
The MX interrupt distributer adds Interprocessor Interrupts
|
||||
and causes the IRQ numbers to be increased by 4 for devices
|
||||
like the open cores ethernet driver and the serial interface.
|
||||
|
||||
You still have to select "Enable SMP" to enable SMP on this SOC.
|
||||
|
||||
config SMP
|
||||
bool "Enable Symmetric multi-processing support"
|
||||
depends on HAVE_SMP
|
||||
select USE_GENERIC_SMP_HELPERS
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
help
|
||||
Enabled SMP Software; allows more than one CPU/CORE
|
||||
to be activated during startup.
|
||||
|
||||
config NR_CPUS
|
||||
depends on SMP
|
||||
int "Maximum number of CPUs (2-32)"
|
||||
range 2 32
|
||||
default "4"
|
||||
|
||||
config HOTPLUG_CPU
|
||||
bool "Enable CPU hotplug support"
|
||||
depends on SMP
|
||||
help
|
||||
Say Y here to allow turning CPUs off and on. CPUs can be
|
||||
controlled through /sys/devices/system/cpu.
|
||||
|
||||
Say N if you want to disable CPU hotplug.
|
||||
|
||||
config MATH_EMULATION
|
||||
bool "Math emulation"
|
||||
help
|
||||
@@ -156,9 +202,6 @@ config XTENSA_CALIBRATE_CCOUNT
|
||||
config SERIAL_CONSOLE
|
||||
def_bool n
|
||||
|
||||
config XTENSA_ISS_NETWORK
|
||||
def_bool n
|
||||
|
||||
menu "Bus options"
|
||||
|
||||
config PCI
|
||||
@@ -185,7 +228,6 @@ config XTENSA_PLATFORM_ISS
|
||||
depends on TTY
|
||||
select XTENSA_CALIBRATE_CCOUNT
|
||||
select SERIAL_CONSOLE
|
||||
select XTENSA_ISS_NETWORK
|
||||
help
|
||||
ISS is an acronym for Tensilica's Instruction Set Simulator.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/include/ "xtfpga-flash-4m.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "xtensa,lx60";
|
||||
compatible = "cdns,xtensa-lx60";
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x04000000>;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/include/ "xtfpga-flash-16m.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "xtensa,ml605";
|
||||
compatible = "cdns,xtensa-ml605";
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x08000000>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/ {
|
||||
compatible = "xtensa,xtfpga";
|
||||
compatible = "cdns,xtensa-xtfpga";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&pic>;
|
||||
@@ -17,7 +17,7 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
compatible = "xtensa,cpu";
|
||||
compatible = "cdns,xtensa-cpu";
|
||||
reg = <0>;
|
||||
/* Filled in by platform_setup from FPGA register
|
||||
* clock-frequency = <100000000>;
|
||||
@@ -26,7 +26,7 @@
|
||||
};
|
||||
|
||||
pic: pic {
|
||||
compatible = "xtensa,pic";
|
||||
compatible = "cdns,xtensa-pic";
|
||||
/* one cell: internal irq number,
|
||||
* two cells: second cell == 0: internal irq number
|
||||
* second cell == 1: external irq number
|
||||
|
||||
@@ -8,7 +8,6 @@ generic-y += emergency-restart.h
|
||||
generic-y += errno.h
|
||||
generic-y += exec.h
|
||||
generic-y += fcntl.h
|
||||
generic-y += futex.h
|
||||
generic-y += hardirq.h
|
||||
generic-y += ioctl.h
|
||||
generic-y += irq_regs.h
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
#define rmb() barrier()
|
||||
#define wmb() mb()
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#error smp_* not defined
|
||||
#endif
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
||||
#endif /* _XTENSA_SYSTEM_H */
|
||||
|
||||
@@ -22,12 +22,8 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
# error SMP not supported on this architecture
|
||||
#endif
|
||||
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
#define smp_mb__before_clear_bit() smp_mb()
|
||||
#define smp_mb__after_clear_bit() smp_mb()
|
||||
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
/*
|
||||
* include/asm-xtensa/cacheflush.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* (C) 2001 - 2007 Tensilica Inc.
|
||||
* (C) 2001 - 2013 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_CACHEFLUSH_H
|
||||
#define _XTENSA_CACHEFLUSH_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
@@ -51,7 +47,6 @@ extern void __invalidate_icache_page(unsigned long);
|
||||
extern void __invalidate_icache_range(unsigned long, unsigned long);
|
||||
extern void __invalidate_dcache_range(unsigned long, unsigned long);
|
||||
|
||||
|
||||
#if XCHAL_DCACHE_IS_WRITEBACK
|
||||
extern void __flush_invalidate_dcache_all(void);
|
||||
extern void __flush_dcache_page(unsigned long);
|
||||
@@ -87,9 +82,22 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
|
||||
* (see also Documentation/cachetlb.txt)
|
||||
*/
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) || defined(CONFIG_SMP)
|
||||
|
||||
#define flush_cache_all() \
|
||||
#ifdef CONFIG_SMP
|
||||
void flush_cache_all(void);
|
||||
void flush_cache_range(struct vm_area_struct*, ulong, ulong);
|
||||
void flush_icache_range(unsigned long start, unsigned long end);
|
||||
void flush_cache_page(struct vm_area_struct*,
|
||||
unsigned long, unsigned long);
|
||||
#else
|
||||
#define flush_cache_all local_flush_cache_all
|
||||
#define flush_cache_range local_flush_cache_range
|
||||
#define flush_icache_range local_flush_icache_range
|
||||
#define flush_cache_page local_flush_cache_page
|
||||
#endif
|
||||
|
||||
#define local_flush_cache_all() \
|
||||
do { \
|
||||
__flush_invalidate_dcache_all(); \
|
||||
__invalidate_icache_all(); \
|
||||
@@ -103,9 +111,11 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
|
||||
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
||||
extern void flush_dcache_page(struct page*);
|
||||
extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
|
||||
extern void flush_cache_page(struct vm_area_struct*,
|
||||
unsigned long, unsigned long);
|
||||
|
||||
void local_flush_cache_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end);
|
||||
void local_flush_cache_page(struct vm_area_struct *vma,
|
||||
unsigned long address, unsigned long pfn);
|
||||
|
||||
#else
|
||||
|
||||
@@ -119,13 +129,14 @@ extern void flush_cache_page(struct vm_area_struct*,
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
|
||||
#define flush_dcache_page(page) do { } while (0)
|
||||
|
||||
#define flush_cache_page(vma,addr,pfn) do { } while (0)
|
||||
#define flush_cache_range(vma,start,end) do { } while (0)
|
||||
#define flush_icache_range local_flush_icache_range
|
||||
#define flush_cache_page(vma, addr, pfn) do { } while (0)
|
||||
#define flush_cache_range(vma, start, end) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/* Ensure consistency between data and instruction cache. */
|
||||
#define flush_icache_range(start,end) \
|
||||
#define local_flush_icache_range(start, end) \
|
||||
do { \
|
||||
__flush_dcache_range(start, (end) - (start)); \
|
||||
__invalidate_icache_range(start,(end) - (start)); \
|
||||
@@ -253,5 +264,4 @@ static inline void flush_invalidate_dcache_unaligned(u32 addr, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _XTENSA_CACHEFLUSH_H */
|
||||
|
||||
@@ -19,23 +19,57 @@ extern unsigned long loops_per_jiffy;
|
||||
|
||||
static inline void __delay(unsigned long loops)
|
||||
{
|
||||
/* 2 cycles per loop. */
|
||||
__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
|
||||
: "=r" (loops) : "0" (loops));
|
||||
if (__builtin_constant_p(loops) && loops < 2)
|
||||
__asm__ __volatile__ ("nop");
|
||||
else if (loops >= 2)
|
||||
/* 2 cycles per loop. */
|
||||
__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
|
||||
: "+r" (loops));
|
||||
}
|
||||
|
||||
/* For SMP/NUMA systems, change boot_cpu_data to something like
|
||||
* local_cpu_data->... where local_cpu_data points to the current
|
||||
* cpu. */
|
||||
/* Undefined function to get compile-time error */
|
||||
void __bad_udelay(void);
|
||||
void __bad_ndelay(void);
|
||||
|
||||
static __inline__ void udelay (unsigned long usecs)
|
||||
#define __MAX_UDELAY 30000
|
||||
#define __MAX_NDELAY 30000
|
||||
|
||||
static inline void __udelay(unsigned long usecs)
|
||||
{
|
||||
unsigned long start = get_ccount();
|
||||
unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ));
|
||||
unsigned long cycles = (usecs * (ccount_freq >> 15)) >> 5;
|
||||
|
||||
/* Note: all variables are unsigned (can wrap around)! */
|
||||
while (((unsigned long)get_ccount()) - start < cycles)
|
||||
;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
static inline void udelay(unsigned long usec)
|
||||
{
|
||||
if (__builtin_constant_p(usec) && usec >= __MAX_UDELAY)
|
||||
__bad_udelay();
|
||||
else
|
||||
__udelay(usec);
|
||||
}
|
||||
|
||||
static inline void __ndelay(unsigned long nsec)
|
||||
{
|
||||
/*
|
||||
* Inner shift makes sure multiplication doesn't overflow
|
||||
* for legitimate nsec values
|
||||
*/
|
||||
unsigned long cycles = (nsec * (ccount_freq >> 15)) >> 15;
|
||||
__delay(cycles);
|
||||
}
|
||||
|
||||
#define ndelay(n) ndelay(n)
|
||||
|
||||
static inline void ndelay(unsigned long nsec)
|
||||
{
|
||||
if (__builtin_constant_p(nsec) && nsec >= __MAX_NDELAY)
|
||||
__bad_ndelay();
|
||||
else
|
||||
__ndelay(nsec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
__asm__ __volatile__ ( \
|
||||
"mov %0, a0\n" \
|
||||
"mov %1, a1\n" \
|
||||
: "=r"(a0), "=r"(a1) : : ); \
|
||||
: "=r"(a0), "=r"(a1)); \
|
||||
MAKE_PC_FROM_RA(a0, a1); })
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
extern unsigned long return_address(unsigned level);
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Atomic futex routines
|
||||
*
|
||||
* Based on the PowerPC implementataion
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2013 TangoTec Ltd.
|
||||
*
|
||||
* Baruch Siach <baruch@tkos.co.il>
|
||||
*/
|
||||
|
||||
#ifndef _ASM_XTENSA_FUTEX_H
|
||||
#define _ASM_XTENSA_FUTEX_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
||||
__asm__ __volatile( \
|
||||
"1: l32i %0, %2, 0\n" \
|
||||
insn "\n" \
|
||||
" wsr %0, scompare1\n" \
|
||||
"2: s32c1i %1, %2, 0\n" \
|
||||
" bne %1, %0, 1b\n" \
|
||||
" movi %1, 0\n" \
|
||||
"3:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 4\n" \
|
||||
"4: .long 3b\n" \
|
||||
"5: l32r %0, 4b\n" \
|
||||
" movi %1, %3\n" \
|
||||
" jx %0\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .long 1b,5b,2b,5b\n" \
|
||||
" .previous\n" \
|
||||
: "=&r" (oldval), "=&r" (ret) \
|
||||
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
|
||||
: "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
#if !XCHAL_HAVE_S32C1I
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
__futex_atomic_op("mov %1, %4", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
__futex_atomic_op("add %1, %0, %4", ret, oldval, uaddr,
|
||||
oparg);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
__futex_atomic_op("or %1, %0, %4", ret, oldval, uaddr,
|
||||
oparg);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
__futex_atomic_op("and %1, %0, %4", ret, oldval, uaddr,
|
||||
~oparg);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
__futex_atomic_op("xor %1, %0, %4", ret, oldval, uaddr,
|
||||
oparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
pagefault_enable();
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
|
||||
case FUTEX_OP_CMP_NE: return (oldval != cmparg);
|
||||
case FUTEX_OP_CMP_LT: return (oldval < cmparg);
|
||||
case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
|
||||
case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
|
||||
case FUTEX_OP_CMP_GT: return (oldval > cmparg);
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
u32 oldval, u32 newval)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 prev;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
#if !XCHAL_HAVE_S32C1I
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
|
||||
__asm__ __volatile__ (
|
||||
" # futex_atomic_cmpxchg_inatomic\n"
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" mov %0, %5\n"
|
||||
" wsr %1, scompare1\n"
|
||||
"2: s32c1i %0, %3, 0\n"
|
||||
"3:\n"
|
||||
" .section .fixup,\"ax\"\n"
|
||||
" .align 4\n"
|
||||
"4: .long 3b\n"
|
||||
"5: l32r %1, 4b\n"
|
||||
" movi %0, %6\n"
|
||||
" jx %1\n"
|
||||
" .previous\n"
|
||||
" .section __ex_table,\"a\"\n"
|
||||
" .long 1b,5b,2b,5b\n"
|
||||
" .previous\n"
|
||||
: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
|
||||
: "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT)
|
||||
: "memory");
|
||||
|
||||
*uval = prev;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_XTENSA_FUTEX_H */
|
||||
@@ -26,6 +26,9 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/vectors.h>
|
||||
|
||||
#define CA_BYPASS (_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
|
||||
#define CA_WRITEBACK (_PAGE_CA_WB | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#define XTENSA_HWVERSION_RC_2009_0 230000
|
||||
@@ -80,8 +83,6 @@
|
||||
/* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code
|
||||
* and jump to the new mapping.
|
||||
*/
|
||||
#define CA_BYPASS (_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
|
||||
#define CA_WRITEBACK (_PAGE_CA_WB | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
|
||||
|
||||
srli a3, a0, 27
|
||||
slli a3, a3, 27
|
||||
@@ -123,13 +124,13 @@
|
||||
wdtlb a4, a5
|
||||
witlb a4, a5
|
||||
|
||||
movi a5, 0xe0000006
|
||||
movi a4, 0xf0000000 + CA_WRITEBACK
|
||||
movi a5, XCHAL_KIO_CACHED_VADDR + 6
|
||||
movi a4, XCHAL_KIO_DEFAULT_PADDR + CA_WRITEBACK
|
||||
wdtlb a4, a5
|
||||
witlb a4, a5
|
||||
|
||||
movi a5, 0xf0000006
|
||||
movi a4, 0xf0000000 + CA_BYPASS
|
||||
movi a5, XCHAL_KIO_BYPASS_VADDR + 6
|
||||
movi a4, XCHAL_KIO_DEFAULT_PADDR + CA_BYPASS
|
||||
wdtlb a4, a5
|
||||
witlb a4, a5
|
||||
|
||||
|
||||
@@ -14,20 +14,26 @@
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/vectors.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define XCHAL_KIO_CACHED_VADDR 0xe0000000
|
||||
#define XCHAL_KIO_BYPASS_VADDR 0xf0000000
|
||||
#define XCHAL_KIO_PADDR 0xf0000000
|
||||
#define XCHAL_KIO_SIZE 0x10000000
|
||||
|
||||
#define IOADDR(x) (XCHAL_KIO_BYPASS_VADDR + (x))
|
||||
#define IO_SPACE_LIMIT ~0
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
|
||||
extern unsigned long xtensa_kio_paddr;
|
||||
|
||||
static inline unsigned long xtensa_get_kio_paddr(void)
|
||||
{
|
||||
return xtensa_kio_paddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the virtual address for the specified bus memory.
|
||||
* Note that we currently don't support any address outside the KIO segment.
|
||||
|
||||
@@ -43,5 +43,14 @@ static __inline__ int irq_canonicalize(int irq)
|
||||
}
|
||||
|
||||
struct irqaction;
|
||||
struct irq_domain;
|
||||
|
||||
void migrate_irqs(void);
|
||||
int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize,
|
||||
unsigned long int_irq, unsigned long ext_irq,
|
||||
unsigned long *out_hwirq, unsigned int *out_type);
|
||||
int xtensa_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw);
|
||||
unsigned xtensa_map_ext_irq(unsigned ext_irq);
|
||||
unsigned xtensa_get_ext_irq_no(unsigned irq);
|
||||
|
||||
#endif /* _XTENSA_IRQ_H */
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/*
|
||||
* include/asm-xtensa/mmu.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2005 Tensilica Inc.
|
||||
* Copyright (C) 2001 - 2013 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_MMU_H
|
||||
@@ -15,8 +13,10 @@
|
||||
#include <asm-generic/mmu.h>
|
||||
#else
|
||||
|
||||
/* Default "unsigned long" context */
|
||||
typedef unsigned long mm_context_t;
|
||||
typedef struct {
|
||||
unsigned long asid[NR_CPUS];
|
||||
unsigned int cpu;
|
||||
} mm_context_t;
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
#endif /* _XTENSA_MMU_H */
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
/*
|
||||
* include/asm-xtensa/mmu_context.h
|
||||
*
|
||||
* Switch an MMU context.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2005 Tensilica Inc.
|
||||
* Copyright (C) 2001 - 2013 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_MMU_CONTEXT_H
|
||||
@@ -20,22 +18,25 @@
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <variant/core.h>
|
||||
#include <asm/vectors.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm-generic/mm_hooks.h>
|
||||
#include <asm-generic/percpu.h>
|
||||
|
||||
#if (XCHAL_HAVE_TLBS != 1)
|
||||
# error "Linux must have an MMU!"
|
||||
#endif
|
||||
|
||||
extern unsigned long asid_cache;
|
||||
DECLARE_PER_CPU(unsigned long, asid_cache);
|
||||
#define cpu_asid_cache(cpu) per_cpu(asid_cache, cpu)
|
||||
|
||||
/*
|
||||
* NO_CONTEXT is the invalid ASID value that we don't ever assign to
|
||||
* any user or kernel context.
|
||||
* any user or kernel context. We use the reserved values in the
|
||||
* ASID_INSERT macro below.
|
||||
*
|
||||
* 0 invalid
|
||||
* 1 kernel
|
||||
@@ -49,6 +50,12 @@ extern unsigned long asid_cache;
|
||||
#define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
|
||||
#define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8))
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
void init_mmu(void);
|
||||
#else
|
||||
static inline void init_mmu(void) { }
|
||||
#endif
|
||||
|
||||
static inline void set_rasid_register (unsigned long val)
|
||||
{
|
||||
__asm__ __volatile__ (" wsr %0, rasid\n\t"
|
||||
@@ -62,64 +69,77 @@ static inline unsigned long get_rasid_register (void)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__get_new_mmu_context(struct mm_struct *mm)
|
||||
static inline void get_new_mmu_context(struct mm_struct *mm, unsigned int cpu)
|
||||
{
|
||||
extern void flush_tlb_all(void);
|
||||
if (! (++asid_cache & ASID_MASK) ) {
|
||||
flush_tlb_all(); /* start new asid cycle */
|
||||
asid_cache += ASID_USER_FIRST;
|
||||
unsigned long asid = cpu_asid_cache(cpu);
|
||||
if ((++asid & ASID_MASK) == 0) {
|
||||
/*
|
||||
* Start new asid cycle; continue counting with next
|
||||
* incarnation bits; skipping over 0, 1, 2, 3.
|
||||
*/
|
||||
local_flush_tlb_all();
|
||||
asid += ASID_USER_FIRST;
|
||||
}
|
||||
mm->context = asid_cache;
|
||||
cpu_asid_cache(cpu) = asid;
|
||||
mm->context.asid[cpu] = asid;
|
||||
mm->context.cpu = cpu;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__load_mmu_context(struct mm_struct *mm)
|
||||
static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
|
||||
{
|
||||
set_rasid_register(ASID_INSERT(mm->context));
|
||||
/*
|
||||
* Check if our ASID is of an older version and thus invalid.
|
||||
*/
|
||||
|
||||
if (mm) {
|
||||
unsigned long asid = mm->context.asid[cpu];
|
||||
|
||||
if (asid == NO_CONTEXT ||
|
||||
((asid ^ cpu_asid_cache(cpu)) & ~ASID_MASK))
|
||||
get_new_mmu_context(mm, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
|
||||
{
|
||||
get_mmu_context(mm, cpu);
|
||||
set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));
|
||||
invalidate_page_directory();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the context related info for a new mm_struct
|
||||
* instance.
|
||||
* instance. Valid cpu values are 0..(NR_CPUS-1), so initializing
|
||||
* to -1 says the process has never run on any core.
|
||||
*/
|
||||
|
||||
static inline int
|
||||
init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
static inline int init_new_context(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
mm->context = NO_CONTEXT;
|
||||
int cpu;
|
||||
for_each_possible_cpu(cpu) {
|
||||
mm->context.asid[cpu] = NO_CONTEXT;
|
||||
}
|
||||
mm->context.cpu = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* After we have set current->mm to a new value, this activates
|
||||
* the context for the new mm so we see the new mappings.
|
||||
*/
|
||||
static inline void
|
||||
activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||
{
|
||||
/* Unconditionally get a new ASID. */
|
||||
|
||||
__get_new_mmu_context(next);
|
||||
__load_mmu_context(next);
|
||||
}
|
||||
|
||||
|
||||
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
unsigned long asid = asid_cache;
|
||||
|
||||
/* Check if our ASID is of an older version and thus invalid */
|
||||
|
||||
if (next->context == NO_CONTEXT || ((next->context^asid) & ~ASID_MASK))
|
||||
__get_new_mmu_context(next);
|
||||
|
||||
__load_mmu_context(next);
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int migrated = next->context.cpu != cpu;
|
||||
/* Flush the icache if we migrated to a new core. */
|
||||
if (migrated) {
|
||||
__invalidate_icache_all();
|
||||
next->context.cpu = cpu;
|
||||
}
|
||||
if (migrated || prev != next)
|
||||
activate_context(next, cpu);
|
||||
}
|
||||
|
||||
#define deactivate_mm(tsk, mm) do { } while(0)
|
||||
#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
|
||||
#define deactivate_mm(tsk, mm) do { } while (0)
|
||||
|
||||
/*
|
||||
* Destroy context related info for an mm_struct that is about
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Xtensa MX interrupt distributor
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 - 2013 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_MXREGS_H
|
||||
#define _XTENSA_MXREGS_H
|
||||
|
||||
/*
|
||||
* RER/WER at, as Read/write external register
|
||||
* at: value
|
||||
* as: address
|
||||
*
|
||||
* Address Value
|
||||
* 00nn 0...0p..p Interrupt Routing, route IRQ n to processor p
|
||||
* 01pp 0...0d..d 16 bits (d) 'ored' as single IPI to processor p
|
||||
* 0180 0...0m..m Clear enable specified by mask (m)
|
||||
* 0184 0...0m..m Set enable specified by mask (m)
|
||||
* 0190 0...0x..x 8-bit IPI partition register
|
||||
* VVVVVVVVPPPPUUUUUUUUUUUUUUUUU
|
||||
* V (10-bit) Release/Version
|
||||
* P ( 4-bit) Number of cores - 1
|
||||
* U (18-bit) ID
|
||||
* 01a0 i.......i 32-bit ConfigID
|
||||
* 0200 0...0m..m RunStall core 'n'
|
||||
* 0220 c Cache coherency enabled
|
||||
*/
|
||||
|
||||
#define MIROUT(irq) (0x000 + (irq))
|
||||
#define MIPICAUSE(cpu) (0x100 + (cpu))
|
||||
#define MIPISET(cause) (0x140 + (cause))
|
||||
#define MIENG 0x180
|
||||
#define MIENGSET 0x184
|
||||
#define MIASG 0x188 /* Read Global Assert Register */
|
||||
#define MIASGSET 0x18c /* Set Global Addert Regiter */
|
||||
#define MIPIPART 0x190
|
||||
#define SYSCFGID 0x1a0
|
||||
#define MPSCORE 0x200
|
||||
#define CCON 0x220
|
||||
|
||||
#endif /* _XTENSA_MXREGS_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef __ASM_XTENSA_PERF_EVENT_H
|
||||
#define __ASM_XTENSA_PERF_EVENT_H
|
||||
|
||||
#endif /* __ASM_XTENSA_PERF_EVENT_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user