Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS updates from Ralf Baechle:
 - three fixes for 3.15 that didn't make it in time
 - limited Octeon 3 support.
 - paravirtualization support
 - improvment to platform support for Netlogix SOCs.
 - add support for powering down the Malta eval board in software
 - add many instructions to the in-kernel microassembler.
 - add support for the BPF JIT.
 - minor cleanups of the BCM47xx code.
 - large cleanup of math emu code resulting in significant code size
   reduction, better readability of the code and more accurate
   emulation.
 - improvments to the MIPS CPS code.
 - support C3 power status for the R4k count/compare clock device.
 - improvments to the GIO support for older SGI workstations.
 - increase number of supported CPUs to 256; this can be reached on
   certain embedded multithreaded ccNUMA configurations.
 - various small cleanups, updates and fixes

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (173 commits)
  MIPS: IP22/IP28: Improve GIO support
  MIPS: Octeon: Add twsi interrupt initialization for OCTEON 3XXX, 5XXX, 63XX
  DEC: Document the R4k MB ASIC mini interrupt controller
  DEC: Add self as the maintainer
  MIPS: Add microMIPS MSA support.
  MIPS: Replace calls to obsolete strict_strto call with kstrto* equivalents.
  MIPS: Replace obsolete strict_strto call with kstrto
  MIPS: BFP: Simplify code slightly.
  MIPS: Call find_vma with the mmap_sem held
  MIPS: Fix 'write_msa_##' inline macro.
  MIPS: Fix MSA toolchain support detection.
  mips: Update the email address of Geert Uytterhoeven
  MIPS: Add minimal defconfig for mips_paravirt
  MIPS: Enable build for new system 'paravirt'
  MIPS: paravirt: Add pci controller for virtio
  MIPS: Add code for new system 'paravirt'
  MIPS: Add functions for hypervisor call
  MIPS: OCTEON: Add OCTEON3 to __get_cpu_type
  MIPS: Add function get_ebase_cpunum
  MIPS: Add minimal support for OCTEON3 to c-r4k.c
  ...
This commit is contained in:
Linus Torvalds
2014-06-09 18:10:34 -07:00
256 changed files with 8553 additions and 7896 deletions

View File

@@ -17,26 +17,8 @@
#ifdef CONFIG_64BIT
#include <asm/asmmacro-64.h>
#endif
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#endif
#ifdef CONFIG_MIPS_MT_SMTC
.macro local_irq_enable reg=t0
mfc0 \reg, CP0_TCSTATUS
ori \reg, \reg, TCSTATUS_IXMT
xori \reg, \reg, TCSTATUS_IXMT
mtc0 \reg, CP0_TCSTATUS
_ehb
.endm
.macro local_irq_disable reg=t0
mfc0 \reg, CP0_TCSTATUS
ori \reg, \reg, TCSTATUS_IXMT
mtc0 \reg, CP0_TCSTATUS
_ehb
.endm
#elif defined(CONFIG_CPU_MIPSR2)
#ifdef CONFIG_CPU_MIPSR2
.macro local_irq_enable reg=t0
ei
irq_enable_hazard
@@ -71,7 +53,7 @@
sw \reg, TI_PRE_COUNT($28)
#endif
.endm
#endif /* CONFIG_MIPS_MT_SMTC */
#endif /* CONFIG_CPU_MIPSR2 */
.macro fpu_save_16even thread tmp=t0
cfc1 \tmp, fcr31
@@ -267,13 +249,35 @@
.set pop
.endm
#else
#ifdef CONFIG_CPU_MICROMIPS
#define CFC_MSA_INSN 0x587e0056
#define CTC_MSA_INSN 0x583e0816
#define LDD_MSA_INSN 0x58000837
#define STD_MSA_INSN 0x5800083f
#define COPY_UW_MSA_INSN 0x58f00056
#define COPY_UD_MSA_INSN 0x58f80056
#define INSERT_W_MSA_INSN 0x59300816
#define INSERT_D_MSA_INSN 0x59380816
#else
#define CFC_MSA_INSN 0x787e0059
#define CTC_MSA_INSN 0x783e0819
#define LDD_MSA_INSN 0x78000823
#define STD_MSA_INSN 0x78000827
#define COPY_UW_MSA_INSN 0x78f00059
#define COPY_UD_MSA_INSN 0x78f80059
#define INSERT_W_MSA_INSN 0x79300819
#define INSERT_D_MSA_INSN 0x79380819
#endif
/*
* Temporary until all toolchains in use include MSA support.
*/
.macro cfcmsa rd, cs
.set push
.set noat
.word 0x787e0059 | (\cs << 11)
.insn
.word CFC_MSA_INSN | (\cs << 11)
move \rd, $1
.set pop
.endm
@@ -282,7 +286,7 @@
.set push
.set noat
move $1, \rs
.word 0x783e0819 | (\cd << 6)
.word CTC_MSA_INSN | (\cd << 6)
.set pop
.endm
@@ -290,7 +294,7 @@
.set push
.set noat
add $1, \base, \off
.word 0x78000823 | (\wd << 6)
.word LDD_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -298,14 +302,15 @@
.set push
.set noat
add $1, \base, \off
.word 0x78000827 | (\wd << 6)
.word STD_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro copy_u_w rd, ws, n
.set push
.set noat
.word 0x78f00059 | (\n << 16) | (\ws << 11)
.insn
.word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
/* move triggers an assembler bug... */
or \rd, $1, zero
.set pop
@@ -314,7 +319,8 @@
.macro copy_u_d rd, ws, n
.set push
.set noat
.word 0x78f80059 | (\n << 16) | (\ws << 11)
.insn
.word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
/* move triggers an assembler bug... */
or \rd, $1, zero
.set pop
@@ -325,7 +331,7 @@
.set noat
/* move triggers an assembler bug... */
or $1, \rs, zero
.word 0x79300819 | (\n << 16) | (\wd << 6)
.word INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
.set pop
.endm
@@ -334,7 +340,7 @@
.set noat
/* move triggers an assembler bug... */
or $1, \rs, zero
.word 0x79380819 | (\n << 16) | (\wd << 6)
.word INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
.set pop
.endm
#endif

View File

@@ -8,6 +8,8 @@
#ifndef _ASM_BRANCH_H
#define _ASM_BRANCH_H
#include <asm/cpu-features.h>
#include <asm/mipsregs.h>
#include <asm/ptrace.h>
#include <asm/inst.h>
@@ -18,12 +20,40 @@ extern int __compute_return_epc_for_insn(struct pt_regs *regs,
extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
/*
* microMIPS bitfields
*/
#define MM_POOL32A_MINOR_MASK 0x3f
#define MM_POOL32A_MINOR_SHIFT 0x6
#define MM_MIPS32_COND_FC 0x30
extern int __mm_isBranchInstr(struct pt_regs *regs,
struct mm_decoded_insn dec_insn, unsigned long *contpc);
static inline int mm_isBranchInstr(struct pt_regs *regs,
struct mm_decoded_insn dec_insn, unsigned long *contpc)
{
if (!cpu_has_mmips)
return 0;
return __mm_isBranchInstr(regs, dec_insn, contpc);
}
static inline int delay_slot(struct pt_regs *regs)
{
return regs->cp0_cause & CAUSEF_BD;
}
static inline void clear_delay_slot(struct pt_regs *regs)
{
regs->cp0_cause &= ~CAUSEF_BD;
}
static inline void set_delay_slot(struct pt_regs *regs)
{
regs->cp0_cause |= CAUSEF_BD;
}
static inline unsigned long exception_epc(struct pt_regs *regs)
{
if (likely(!delay_slot(regs)))

View File

@@ -113,6 +113,12 @@ unsigned long run_uncached(void *func);
extern void *kmap_coherent(struct page *page, unsigned long addr);
extern void kunmap_coherent(void);
extern void *kmap_noncoherent(struct page *page, unsigned long addr);
static inline void kunmap_noncoherent(void)
{
kunmap_coherent();
}
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
static inline void flush_kernel_dcache_page(struct page *page)

View File

@@ -10,7 +10,6 @@ extern void cmp_smp_setup(void);
extern void cmp_smp_finish(void);
extern void cmp_boot_secondary(int cpu, struct task_struct *t);
extern void cmp_init_secondary(void);
extern void cmp_cpus_done(void);
extern void cmp_prepare_cpus(unsigned int max_cpus);
/* This is platform specific */

View File

@@ -110,9 +110,15 @@
#ifndef cpu_has_smartmips
#define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS)
#endif
#ifndef cpu_has_rixi
#define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI)
# ifdef CONFIG_64BIT
# define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI)
# else /* CONFIG_32BIT */
# define cpu_has_rixi ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits)
# endif
#endif
#ifndef cpu_has_mmips
# ifdef CONFIG_SYS_SUPPORTS_MICROMIPS
# define cpu_has_mmips (cpu_data[0].options & MIPS_CPU_MICROMIPS)
@@ -120,6 +126,7 @@
# define cpu_has_mmips 0
# endif
#endif
#ifndef cpu_has_vtag_icache
#define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
#endif
@@ -183,6 +190,17 @@
/*
* Shortcuts ...
*/
#define cpu_has_mips_2_3_4_5 (cpu_has_mips_2 | cpu_has_mips_3_4_5)
#define cpu_has_mips_3_4_5 (cpu_has_mips_3 | cpu_has_mips_4_5)
#define cpu_has_mips_4_5 (cpu_has_mips_4 | cpu_has_mips_5)
#define cpu_has_mips_2_3_4_5_r (cpu_has_mips_2 | cpu_has_mips_3_4_5_r)
#define cpu_has_mips_3_4_5_r (cpu_has_mips_3 | cpu_has_mips_4_5_r)
#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
#define cpu_has_mips_4_5_r2 (cpu_has_mips_4_5 | cpu_has_mips_r2)
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2)
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)

View File

@@ -65,17 +65,12 @@ struct cpuinfo_mips {
#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
#endif
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
#ifdef CONFIG_MIPS_MT_SMP
/*
* In the MIPS MT "SMTC" model, each TC is considered
* to be a "CPU" for the purposes of scheduling, but
* exception resources, ASID spaces, etc, are common
* to all TCs within the same VPE.
* There is not necessarily a 1:1 mapping of VPE num to CPU number
* in particular on multi-core systems.
*/
int vpe_id; /* Virtual Processor number */
#endif
#ifdef CONFIG_MIPS_MT_SMTC
int tc_id; /* Thread Context number */
#endif
void *data; /* Additional data */
unsigned int watch_reg_count; /* Number that exist */
@@ -117,7 +112,7 @@ struct proc_cpuinfo_notifier_args {
unsigned long n;
};
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
#ifdef CONFIG_MIPS_MT_SMP
# define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id)
#else
# define cpu_vpe_id(cpuinfo) 0

View File

@@ -155,9 +155,6 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_RM7000:
case CPU_SR71000:
#endif
#ifdef CONFIG_SYS_HAS_CPU_RM9000
case CPU_RM9000:
#endif
#ifdef CONFIG_SYS_HAS_CPU_SB1
case CPU_SB1:
case CPU_SB1A:
@@ -166,6 +163,7 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
case CPU_CAVIUM_OCTEON3:
#endif
#if defined(CONFIG_SYS_HAS_CPU_BMIPS32_3300) || \

View File

@@ -201,6 +201,7 @@
#define PRID_IMP_NETLOGIC_XLP3XX 0x1100
#define PRID_IMP_NETLOGIC_XLP2XX 0x1200
#define PRID_IMP_NETLOGIC_XLP9XX 0x1500
#define PRID_IMP_NETLOGIC_XLP5XX 0x1300
/*
* Particular Revision values for bits 7:0 of the PRId register.
@@ -281,7 +282,7 @@ enum cpu_type_enum {
CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000,
CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122,
CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
CPU_SR71000, CPU_RM9000, CPU_TX49XX,
CPU_SR71000, CPU_TX49XX,
/*
* R8000 class processors

View File

@@ -48,13 +48,21 @@
#define KN4K_RES_14 (14*IOASIC_SLOT_SIZE) /* unused? */
#define KN4K_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */
/*
* MB ASIC interrupt bits.
*/
#define KN4K_MB_INR_MB 4 /* ??? */
#define KN4K_MB_INR_MT 3 /* memory, I/O bus read/write errors */
#define KN4K_MB_INR_RES_2 2 /* unused */
#define KN4K_MB_INR_RTC 1 /* RTC */
#define KN4K_MB_INR_TC 0 /* I/O ASIC cascade */
/*
* Bits for the MB interrupt register.
* The register appears read-only.
*/
#define KN4K_MB_INT_TC (1<<0) /* TURBOchannel? */
#define KN4K_MB_INT_RTC (1<<1) /* RTC? */
#define KN4K_MB_INT_MT (1<<3) /* I/O ASIC cascade */
#define KN4K_MB_INT_IRQ (0x1f<<0) /* CPU Int[4:0] status. */
#define KN4K_MB_INT_IRQ_N(n) (1<<(n)) /* Individual status bits. */
/*
* Bits for the MB control & status register.
@@ -70,6 +78,7 @@
#define KN4K_MB_CSR_NC (1<<14) /* ??? */
#define KN4K_MB_CSR_EE (1<<15) /* (bus) Exception Enable? */
#define KN4K_MB_CSR_MSK (0x1f<<16) /* CPU Int[4:0] mask */
#define KN4K_MB_CSR_MSK_N(n) (1<<((n)+16)) /* Individual mask bits. */
#define KN4K_MB_CSR_FW (1<<21) /* ??? */
#define KN4K_MB_CSR_W (1<<31) /* ??? */

View File

@@ -48,11 +48,7 @@
enum fixed_addresses {
#define FIX_N_COLOURS 8
FIX_CMAP_BEGIN,
#ifdef CONFIG_MIPS_MT_SMTC
FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS * 2),
#else
FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2),
#endif
#ifdef CONFIG_HIGHMEM
/* reserved pte's for temporary kernel mappings */
FIX_KMAP_BEGIN = FIX_CMAP_END + 1,

View File

@@ -17,6 +17,7 @@
#include <asm/mipsregs.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/fpu_emulator.h>
#include <asm/hazards.h>
#include <asm/processor.h>
#include <asm/current.h>
@@ -28,7 +29,6 @@
struct sigcontext;
struct sigcontext32;
extern void fpu_emulator_init_fpu(void);
extern void _init_fpu(void);
extern void _save_fp(struct task_struct *);
extern void _restore_fp(struct task_struct *);
@@ -156,15 +156,16 @@ static inline int init_fpu(void)
int ret = 0;
preempt_disable();
if (cpu_has_fpu) {
ret = __own_fpu();
if (!ret)
_init_fpu();
} else {
} else
fpu_emulator_init_fpu();
}
preempt_enable();
return ret;
}

View File

@@ -23,9 +23,12 @@
#ifndef _ASM_FPU_EMULATOR_H
#define _ASM_FPU_EMULATOR_H
#include <linux/sched.h>
#include <asm/break.h>
#include <asm/thread_info.h>
#include <asm/inst.h>
#include <asm/local.h>
#include <asm/processor.h>
#ifdef CONFIG_DEBUG_FS
@@ -36,6 +39,11 @@ struct mips_fpu_emulator_stats {
local_t cp1ops;
local_t cp1xops;
local_t errors;
local_t ieee754_inexact;
local_t ieee754_underflow;
local_t ieee754_overflow;
local_t ieee754_zerodiv;
local_t ieee754_invalidop;
};
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
@@ -71,4 +79,17 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
*/
#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))
#define SIGNALLING_NAN 0x7ff800007ff80000LL
static inline void fpu_emulator_init_fpu(void)
{
struct task_struct *t = current;
int i;
t->thread.fpu.fcr31 = 0;
for (i = 0; i < 32; i++)
set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN);
}
#endif /* _ASM_FPU_EMULATOR_H */

View File

@@ -380,6 +380,7 @@ extern unsigned int gic_compare_int (void);
extern cycle_t gic_read_count(void);
extern cycle_t gic_read_compare(void);
extern void gic_write_compare(cycle_t cnt);
extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
extern void gic_send_ipi(unsigned int intr);
extern unsigned int plat_ipi_call_int_xlate(unsigned int);
extern unsigned int plat_ipi_resched_int_xlate(unsigned int);

View File

@@ -50,7 +50,7 @@ static inline void gio_device_free(struct gio_device *dev)
extern int gio_register_driver(struct gio_driver *);
extern void gio_unregister_driver(struct gio_driver *);
#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
#define gio_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define gio_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data))
extern void gio_set_master(struct gio_device *);

View File

@@ -1,6 +1,7 @@
#ifndef __ASM_IDLE_H
#define __ASM_IDLE_H
#include <linux/cpuidle.h>
#include <linux/linkage.h>
extern void (*cpu_wait)(void);
@@ -20,4 +21,17 @@ static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
addr < (unsigned long)__pastwait;
}
extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
#define MIPS_CPUIDLE_WAIT_STATE {\
.enter = mips_cpuidle_wait_enter,\
.exit_latency = 1,\
.target_residency = 1,\
.power_usage = UINT_MAX,\
.flags = CPUIDLE_FLAG_TIME_VALID,\
.name = "wait",\
.desc = "MIPS wait",\
}
#endif /* __ASM_IDLE_H */

View File

@@ -26,104 +26,8 @@ static inline int irq_canonicalize(int irq)
#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */
#endif
#ifdef CONFIG_MIPS_MT_SMTC
struct irqaction;
extern unsigned long irq_hwmask[];
extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
unsigned long hwmask);
static inline void smtc_im_ack_irq(unsigned int irq)
{
if (irq_hwmask[irq] & ST0_IM)
set_c0_status(irq_hwmask[irq] & ST0_IM);
}
#else
static inline void smtc_im_ack_irq(unsigned int irq)
{
}
#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
#include <linux/cpumask.h>
extern int plat_set_irq_affinity(struct irq_data *d,
const struct cpumask *affinity, bool force);
extern void smtc_forward_irq(struct irq_data *d);
/*
* IRQ affinity hook invoked at the beginning of interrupt dispatch
* if option is enabled.
*
* Up through Linux 2.6.22 (at least) cpumask operations are very
* inefficient on MIPS. Initial prototypes of SMTC IRQ affinity
* used a "fast path" per-IRQ-descriptor cache of affinity information
* to reduce latency. As there is a project afoot to optimize the
* cpumask implementations, this version is optimistically assuming
* that cpumask.h macro overhead is reasonable during interrupt dispatch.
*/
static inline int handle_on_other_cpu(unsigned int irq)
{
struct irq_data *d = irq_get_irq_data(irq);
if (cpumask_test_cpu(smp_processor_id(), d->affinity))
return 0;
smtc_forward_irq(d);
return 1;
}
#else /* Not doing SMTC affinity */
static inline int handle_on_other_cpu(unsigned int irq) { return 0; }
#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
static inline void smtc_im_backstop(unsigned int irq)
{
if (irq_hwmask[irq] & 0x0000ff00)
write_c0_tccontext(read_c0_tccontext() &
~(irq_hwmask[irq] & 0x0000ff00));
}
/*
* Clear interrupt mask handling "backstop" if irq_hwmask
* entry so indicates. This implies that the ack() or end()
* functions will take over re-enabling the low-level mask.
* Otherwise it will be done on return from exception.
*/
static inline int smtc_handle_on_other_cpu(unsigned int irq)
{
int ret = handle_on_other_cpu(irq);
if (!ret)
smtc_im_backstop(irq);
return ret;
}
#else
static inline void smtc_im_backstop(unsigned int irq) { }
static inline int smtc_handle_on_other_cpu(unsigned int irq)
{
return handle_on_other_cpu(irq);
}
#endif
extern void do_IRQ(unsigned int irq);
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
extern void do_IRQ_no_affinity(unsigned int irq);
#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
extern void arch_init_irq(void);
extern void spurious_interrupt(void);

View File

@@ -17,7 +17,7 @@
#include <linux/stringify.h>
#include <asm/hazards.h>
#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
#ifdef CONFIG_CPU_MIPSR2
static inline void arch_local_irq_disable(void)
{
@@ -118,30 +118,15 @@ void arch_local_irq_disable(void);
unsigned long arch_local_irq_save(void);
void arch_local_irq_restore(unsigned long flags);
void __arch_local_irq_restore(unsigned long flags);
#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
extern void smtc_ipi_replay(void);
#endif /* CONFIG_CPU_MIPSR2 */
static inline void arch_local_irq_enable(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC kernel needs to do a software replay of queued
* IPIs, at the cost of call overhead on each local_irq_enable()
*/
smtc_ipi_replay();
#endif
__asm__ __volatile__(
" .set push \n"
" .set reorder \n"
" .set noat \n"
#ifdef CONFIG_MIPS_MT_SMTC
" mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
" ori $1, 0x400 \n"
" xori $1, 0x400 \n"
" mtc0 $1, $2, 1 \n"
#elif defined(CONFIG_CPU_MIPSR2)
#if defined(CONFIG_CPU_MIPSR2)
" ei \n"
#else
" mfc0 $1,$12 \n"
@@ -163,11 +148,7 @@ static inline unsigned long arch_local_save_flags(void)
asm __volatile__(
" .set push \n"
" .set reorder \n"
#ifdef CONFIG_MIPS_MT_SMTC
" mfc0 %[flags], $2, 1 \n"
#else
" mfc0 %[flags], $12 \n"
#endif
" .set pop \n"
: [flags] "=r" (flags));
@@ -177,14 +158,7 @@ static inline unsigned long arch_local_save_flags(void)
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
*/
return flags & 0x400;
#else
return !(flags & 1);
#endif
}
#endif /* #ifndef __ASSEMBLY__ */

View File

@@ -0,0 +1,109 @@
#ifndef _ASM_MIPS_KVM_PARA_H
#define _ASM_MIPS_KVM_PARA_H
#include <uapi/asm/kvm_para.h>
#define KVM_HYPERCALL ".word 0x42000028"
/*
* Hypercalls for KVM.
*
* Hypercall number is passed in v0.
* Return value will be placed in v0.
* Up to 3 arguments are passed in a0, a1, and a2.
*/
static inline unsigned long kvm_hypercall0(unsigned long num)
{
register unsigned long n asm("v0");
register unsigned long r asm("v0");
n = num;
__asm__ __volatile__(
KVM_HYPERCALL
: "=r" (r) : "r" (n) : "memory"
);
return r;
}
static inline unsigned long kvm_hypercall1(unsigned long num,
unsigned long arg0)
{
register unsigned long n asm("v0");
register unsigned long r asm("v0");
register unsigned long a0 asm("a0");
n = num;
a0 = arg0;
__asm__ __volatile__(
KVM_HYPERCALL
: "=r" (r) : "r" (n), "r" (a0) : "memory"
);
return r;
}
static inline unsigned long kvm_hypercall2(unsigned long num,
unsigned long arg0, unsigned long arg1)
{
register unsigned long n asm("v0");
register unsigned long r asm("v0");
register unsigned long a0 asm("a0");
register unsigned long a1 asm("a1");
n = num;
a0 = arg0;
a1 = arg1;
__asm__ __volatile__(
KVM_HYPERCALL
: "=r" (r) : "r" (n), "r" (a0), "r" (a1) : "memory"
);
return r;
}
static inline unsigned long kvm_hypercall3(unsigned long num,
unsigned long arg0, unsigned long arg1, unsigned long arg2)
{
register unsigned long n asm("v0");
register unsigned long r asm("v0");
register unsigned long a0 asm("a0");
register unsigned long a1 asm("a1");
register unsigned long a2 asm("a2");
n = num;
a0 = arg0;
a1 = arg1;
a2 = arg2;
__asm__ __volatile__(
KVM_HYPERCALL
: "=r" (r) : "r" (n), "r" (a0), "r" (a1), "r" (a2) : "memory"
);
return r;
}
static inline bool kvm_check_and_clear_guest_paused(void)
{
return false;
}
static inline unsigned int kvm_arch_para_features(void)
{
return 0;
}
#ifdef CONFIG_MIPS_PARAVIRT
static inline bool kvm_para_available(void)
{
return true;
}
#else
static inline bool kvm_para_available(void)
{
return false;
}
#endif
#endif /* _ASM_MIPS_KVM_PARA_H */

View File

@@ -22,7 +22,6 @@
#define cpu_has_3k_cache 0
#define cpu_has_4k_cache 0
#define cpu_has_tx39_cache 0
#define cpu_has_fpu 0
#define cpu_has_counter 1
#define cpu_has_watch 1
#define cpu_has_divec 1

View File

@@ -35,6 +35,8 @@ enum octeon_irq {
OCTEON_IRQ_PCI_MSI2,
OCTEON_IRQ_PCI_MSI3,
OCTEON_IRQ_TWSI,
OCTEON_IRQ_TWSI2,
OCTEON_IRQ_RML,
OCTEON_IRQ_TIMER0,
OCTEON_IRQ_TIMER1,

View File

@@ -39,6 +39,10 @@
#define cpu_has_nofpuex 0
#define cpu_has_64bits 1
#define cpu_has_mips_2 1
#define cpu_has_mips_3 1
#define cpu_has_mips_5 0
#define cpu_has_mips32r1 0
#define cpu_has_mips32r2 0
#define cpu_has_mips64r1 0

View File

@@ -80,36 +80,6 @@
.endm
.macro kernel_entry_setup
#ifdef CONFIG_MIPS_MT_SMTC
mfc0 t0, CP0_CONFIG
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 1
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 2
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 3
and t0, 1<<2
bnez t0, 0f
9:
/* Assume we came from YAMON... */
PTR_LA v0, 0x9fc00534 /* YAMON print */
lw v0, (v0)
move a0, zero
PTR_LA a1, nonmt_processor
jal v0
PTR_LA v0, 0x9fc00520 /* YAMON exit */
lw v0, (v0)
li a0, 1
jal v0
1: b 1b
__INITDATA
nonmt_processor:
.asciz "SMTC kernel requires the MT ASE to run\n"
__FINIT
#endif
#ifdef CONFIG_EVA
sync

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2014 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_MIPS_MACH_MALTA_PM_H__
#define __ASM_MIPS_MACH_MALTA_PM_H__
#include <asm/mips-boards/piix4.h>
#ifdef CONFIG_MIPS_MALTA_PM
/**
* mips_pm_suspend - enter a suspend state
* @state: the state to enter, one of PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_*
*
* Enters a suspend state via the Malta's PIIX4. If the state to be entered
* is one which loses context (eg. SOFF) then this function will never
* return.
*/
extern int mips_pm_suspend(unsigned state);
#else /* !CONFIG_MIPS_MALTA_PM */
static inline int mips_pm_suspend(unsigned state)
{
return -EINVAL;
}
#endif /* !CONFIG_MIPS_MALTA_PM */
#endif /* __ASM_MIPS_MACH_MALTA_PM_H__ */

View File

@@ -10,10 +10,12 @@
#include <asm/mach-netlogic/multi-node.h>
#ifdef CONFIG_SMP
#define topology_physical_package_id(cpu) cpu_to_node(cpu)
#define topology_core_id(cpu) (cpu_logical_map(cpu) / NLM_THREADS_PER_CORE)
#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu])
#define topology_core_cpumask(cpu) cpumask_of_node(cpu_to_node(cpu))
#endif
#include <asm-generic/topology.h>

View File

@@ -0,0 +1,36 @@
/*
* 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) 2013 Cavium, Inc.
*/
#ifndef __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H
#define cpu_has_4kex 1
#define cpu_has_3k_cache 0
#define cpu_has_tx39_cache 0
#define cpu_has_counter 1
#define cpu_has_llsc 1
/*
* We Disable LL/SC on non SMP systems as it is faster to disable
* interrupts for atomic access than a LL/SC.
*/
#ifdef CONFIG_SMP
# define kernel_uses_llsc 1
#else
# define kernel_uses_llsc 0
#endif
#ifdef CONFIG_CPU_CAVIUM_OCTEON
#define cpu_dcache_line_size() 128
#define cpu_icache_line_size() 128
#define cpu_has_octeon_cache 1
#define cpu_has_4k_cache 0
#else
#define cpu_has_octeon_cache 0
#define cpu_has_4k_cache 1
#endif
#endif /* __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H */

View File

@@ -0,0 +1,19 @@
/*
* 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) 2013 Cavium, Inc.
*/
#ifndef __ASM_MACH_PARAVIRT_IRQ_H__
#define __ASM_MACH_PARAVIRT_IRQ_H__
#define NR_IRQS 64
#define MIPS_CPU_IRQ_BASE 1
#define MIPS_IRQ_PCIA (MIPS_CPU_IRQ_BASE + 8)
#define MIPS_IRQ_MBOX0 (MIPS_CPU_IRQ_BASE + 32)
#define MIPS_IRQ_MBOX1 (MIPS_CPU_IRQ_BASE + 33)
#endif /* __ASM_MACH_PARAVIRT_IRQ_H__ */

View File

@@ -0,0 +1,50 @@
/*
* 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) 2013 Cavium, Inc
*/
#ifndef __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H
#define __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H
#define CP0_EBASE $15, 1
.macro kernel_entry_setup
mfc0 t0, CP0_EBASE
andi t0, t0, 0x3ff # CPUNum
beqz t0, 1f
# CPUs other than zero goto smp_bootstrap
j smp_bootstrap
1:
.endm
/*
* Do SMP slave processor setup necessary before we can safely execute
* C code.
*/
.macro smp_slave_setup
mfc0 t0, CP0_EBASE
andi t0, t0, 0x3ff # CPUNum
slti t1, t0, NR_CPUS
bnez t1, 1f
2:
di
wait
b 2b # Unknown CPU, loop forever.
1:
PTR_LA t1, paravirt_smp_sp
PTR_SLL t0, PTR_SCALESHIFT
PTR_ADDU t1, t1, t0
3:
PTR_L sp, 0(t1)
beqz sp, 3b # Spin until told to proceed.
PTR_LA t1, paravirt_smp_gp
PTR_ADDU t1, t1, t0
sync
PTR_L gp, 0(t1)
.endm
#endif /* __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H */

View File

@@ -0,0 +1,25 @@
/*
* 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
* Copyright (C) 2013 Cavium Networks <support@caviumnetworks.com>
*/
#ifndef __ASM_MIPS_MACH_PARAVIRT_WAR_H
#define __ASM_MIPS_MACH_PARAVIRT_WAR_H
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#define R4600_V1_HIT_CACHEOP_WAR 0
#define R4600_V2_HIT_CACHEOP_WAR 0
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
#endif /* __ASM_MIPS_MACH_PARAVIRT_WAR_H */

View File

@@ -25,11 +25,7 @@
#ifndef MSP_USB_H_
#define MSP_USB_H_
#ifdef CONFIG_MSP_HAS_DUAL_USB
#define NUM_USB_DEVS 2
#else
#define NUM_USB_DEVS 1
#endif
/* Register spaces for USB host 0 */
#define MSP_USB0_MAB_START (MSP_USB0_BASE + 0x0)

View File

@@ -17,7 +17,6 @@
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#define RM9000_CDEX_SMP_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0

View File

@@ -10,37 +10,6 @@
#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
.macro kernel_entry_setup
#ifdef CONFIG_MIPS_MT_SMTC
mfc0 t0, CP0_CONFIG
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 1
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 2
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 3
and t0, 1<<2
bnez t0, 0f
9 :
/* Assume we came from YAMON... */
PTR_LA v0, 0x9fc00534 /* YAMON print */
lw v0, (v0)
move a0, zero
PTR_LA a1, nonmt_processor
jal v0
PTR_LA v0, 0x9fc00520 /* YAMON exit */
lw v0, (v0)
li a0, 1
jal v0
1 : b 1b
__INITDATA
nonmt_processor :
.asciz "SMTC kernel requires the MT ASE to run\n"
__FINIT
0 :
#endif
.endm
/*

View File

@@ -55,4 +55,16 @@
#define PIIX4_FUNC3_PMREGMISC 0x80
#define PIIX4_FUNC3_PMREGMISC_EN (1 << 0)
/* Power Management IO Space */
#define PIIX4_FUNC3IO_PMSTS 0x00
#define PIIX4_FUNC3IO_PMSTS_PWRBTN_STS (1 << 8)
#define PIIX4_FUNC3IO_PMCNTRL 0x04
#define PIIX4_FUNC3IO_PMCNTRL_SUS_EN (1 << 13)
#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP (0x7 << 10)
#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF (0x0 << 10)
#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_STR (0x1 << 10)
/* Data for magic special PCI cycle */
#define PIIX4_SUSPEND_MAGIC 0x00120002
#endif /* __ASM_MIPS_BOARDS_PIIX4_H */

View File

@@ -72,7 +72,12 @@ static inline bool mips_cpc_present(void)
#define MIPS_CPC_COCB_OFS 0x4000
/* Macros to ease the creation of register access functions */
#define BUILD_CPC_R_(name, off) \
#define BUILD_CPC_R_(name, off) \
static inline u32 *addr_cpc_##name(void) \
{ \
return (u32 *)(mips_cpc_base + (off)); \
} \
\
static inline u32 read_cpc_##name(void) \
{ \
return __raw_readl(mips_cpc_base + (off)); \
@@ -147,4 +152,31 @@ BUILD_CPC_Cx_RW(other, 0x10)
#define CPC_Cx_OTHER_CORENUM_SHF 16
#define CPC_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xff) << 16)
#ifdef CONFIG_MIPS_CPC
/**
* mips_cpc_lock_other - lock access to another core
* core: the other core to be accessed
*
* Call before operating upon a core via the 'other' register region in
* order to prevent the region being moved during access. Must be followed
* by a call to mips_cpc_unlock_other.
*/
extern void mips_cpc_lock_other(unsigned int core);
/**
* mips_cpc_unlock_other - unlock access to another core
*
* Call after operating upon another core via the 'other' register region.
* Must be called after mips_cpc_lock_other.
*/
extern void mips_cpc_unlock_other(void);
#else /* !CONFIG_MIPS_CPC */
static inline void mips_cpc_lock_other(unsigned int core) { }
static inline void mips_cpc_unlock_other(void) { }
#endif /* !CONFIG_MIPS_CPC */
#endif /* __MIPS_ASM_MIPS_CPC_H__ */

View File

@@ -1,7 +1,6 @@
/*
* Definitions and decalrations for MIPS MT support
* that are common between SMTC, VSMP, and/or AP/SP
* kernel models.
* Definitions and decalrations for MIPS MT support that are common between
* the VSMP, and AP/SP kernel models.
*/
#ifndef __ASM_MIPS_MT_H
#define __ASM_MIPS_MT_H

View File

@@ -36,6 +36,8 @@
#define read_c0_tcbind() __read_32bit_c0_register($2, 2)
#define write_c0_tchalt(val) __write_32bit_c0_register($2, 4, val)
#define read_c0_tccontext() __read_32bit_c0_register($2, 5)
#define write_c0_tccontext(val) __write_32bit_c0_register($2, 5, val)

View File

@@ -709,11 +709,18 @@
#ifndef __ASSEMBLY__
/*
* Macros for handling the ISA mode bit for microMIPS.
* Macros for handling the ISA mode bit for MIPS16 and microMIPS.
*/
#if defined(CONFIG_SYS_SUPPORTS_MIPS16) || \
defined(CONFIG_SYS_SUPPORTS_MICROMIPS)
#define get_isa16_mode(x) ((x) & 0x1)
#define msk_isa16_mode(x) ((x) & ~0x1)
#define set_isa16_mode(x) do { (x) |= 0x1; } while(0)
#else
#define get_isa16_mode(x) 0
#define msk_isa16_mode(x) (x)
#define set_isa16_mode(x) do { } while(0)
#endif
/*
* microMIPS instructions can be 16-bit or 32-bit in length. This
@@ -1007,19 +1014,8 @@ do { \
#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
#define read_c0_status() __read_32bit_c0_register($12, 0)
#ifdef CONFIG_MIPS_MT_SMTC
#define write_c0_status(val) \
do { \
__write_32bit_c0_register($12, 0, val); \
__ehb(); \
} while (0)
#else
/*
* Legacy non-SMTC code, which may be hazardous
* but which might not support EHB
*/
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
#endif /* CONFIG_MIPS_MT_SMTC */
#define read_c0_cause() __read_32bit_c0_register($13, 0)
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
@@ -1743,11 +1739,6 @@ static inline void tlb_write_random(void)
/*
* Manipulate bits in a c0 register.
*/
#ifndef CONFIG_MIPS_MT_SMTC
/*
* SMTC Linux requires shutting-down microthread scheduling
* during CP0 register read-modify-write sequences.
*/
#define __BUILD_SET_C0(name) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
@@ -1786,121 +1777,6 @@ change_c0_##name(unsigned int change, unsigned int val) \
return res; \
}
#else /* SMTC versions that manage MT scheduling */
#include <linux/irqflags.h>
/*
* This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
* header file recursion.
*/
static inline unsigned int __dmt(void)
{
int res;
__asm__ __volatile__(
" .set push \n"
" .set mips32r2 \n"
" .set noat \n"
" .word 0x41610BC1 # dmt $1 \n"
" ehb \n"
" move %0, $1 \n"
" .set pop \n"
: "=r" (res));
instruction_hazard();
return res;
}
#define __VPECONTROL_TE_SHIFT 15
#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT)
#define __EMT_ENABLE __VPECONTROL_TE
static inline void __emt(unsigned int previous)
{
if ((previous & __EMT_ENABLE))
__asm__ __volatile__(
" .set mips32r2 \n"
" .word 0x41600be1 # emt \n"
" ehb \n"
" .set mips0 \n");
}
static inline void __ehb(void)
{
__asm__ __volatile__(
" .set mips32r2 \n"
" ehb \n" " .set mips0 \n");
}
/*
* Note that local_irq_save/restore affect TC-specific IXMT state,
* not Status.IE as in non-SMTC kernel.
*/
#define __BUILD_SET_C0(name) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
{ \
unsigned int res; \
unsigned int new; \
unsigned int omt; \
unsigned long flags; \
\
local_irq_save(flags); \
omt = __dmt(); \
res = read_c0_##name(); \
new = res | set; \
write_c0_##name(new); \
__emt(omt); \
local_irq_restore(flags); \
\
return res; \
} \
\
static inline unsigned int \
clear_c0_##name(unsigned int clear) \
{ \
unsigned int res; \
unsigned int new; \
unsigned int omt; \
unsigned long flags; \
\
local_irq_save(flags); \
omt = __dmt(); \
res = read_c0_##name(); \
new = res & ~clear; \
write_c0_##name(new); \
__emt(omt); \
local_irq_restore(flags); \
\
return res; \
} \
\
static inline unsigned int \
change_c0_##name(unsigned int change, unsigned int newbits) \
{ \
unsigned int res; \
unsigned int new; \
unsigned int omt; \
unsigned long flags; \
\
local_irq_save(flags); \
\
omt = __dmt(); \
res = read_c0_##name(); \
new = res & ~change; \
new |= (newbits & change); \
write_c0_##name(new); \
__emt(omt); \
local_irq_restore(flags); \
\
return res; \
}
#endif
__BUILD_SET_C0(status)
__BUILD_SET_C0(cause)
__BUILD_SET_C0(config)
@@ -1916,6 +1792,15 @@ __BUILD_SET_C0(brcm_cmt_ctrl)
__BUILD_SET_C0(brcm_config)
__BUILD_SET_C0(brcm_mode)
/*
* Return low 10 bits of ebase.
* Note that under KVM (MIPSVZ) this returns vcpu id.
*/
static inline unsigned int get_ebase_cpunum(void)
{
return read_c0_ebase() & 0x3ff;
}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_MIPSREGS_H */

View File

@@ -18,10 +18,6 @@
#include <asm/cacheflush.h>
#include <asm/hazards.h>
#include <asm/tlbflush.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#include <asm/smtc.h>
#endif /* SMTC */
#include <asm-generic/mm_hooks.h>
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
@@ -31,11 +27,15 @@ do { \
} while (0)
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
#define TLBMISS_HANDLER_RESTORE() \
write_c0_xcontext((unsigned long) smp_processor_id() << \
SMP_CPUID_REGSHIFT)
#define TLBMISS_HANDLER_SETUP() \
do { \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
write_c0_xcontext((unsigned long) smp_processor_id() << \
SMP_CPUID_REGSHIFT); \
TLBMISS_HANDLER_RESTORE(); \
} while (0)
#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
@@ -47,9 +47,12 @@ do { \
*/
extern unsigned long pgd_current[];
#define TLBMISS_HANDLER_SETUP() \
#define TLBMISS_HANDLER_RESTORE() \
write_c0_context((unsigned long) smp_processor_id() << \
SMP_CPUID_REGSHIFT); \
SMP_CPUID_REGSHIFT)
#define TLBMISS_HANDLER_SETUP() \
TLBMISS_HANDLER_RESTORE(); \
back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
@@ -63,13 +66,6 @@ extern unsigned long pgd_current[];
#define ASID_INC 0x10
#define ASID_MASK 0xff0
#elif defined(CONFIG_MIPS_MT_SMTC)
#define ASID_INC 0x1
extern unsigned long smtc_asid_mask;
#define ASID_MASK (smtc_asid_mask)
#define HW_ASID_MASK 0xff
/* End SMTC/34K debug hack */
#else /* FIXME: not correct for R6000 */
#define ASID_INC 0x1
@@ -92,7 +88,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
#ifndef CONFIG_MIPS_MT_SMTC
/* Normal, classic MIPS get_new_mmu_context */
static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
@@ -115,12 +110,6 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}
#else /* CONFIG_MIPS_MT_SMTC */
#define get_new_mmu_context(mm, cpu) smtc_get_new_mmu_context((mm), (cpu))
#endif /* CONFIG_MIPS_MT_SMTC */
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -141,46 +130,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
{
unsigned int cpu = smp_processor_id();
unsigned long flags;
#ifdef CONFIG_MIPS_MT_SMTC
unsigned long oldasid;
unsigned long mtflags;
int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
local_irq_save(flags);
mtflags = dvpe();
#else /* Not SMTC */
local_irq_save(flags);
#endif /* CONFIG_MIPS_MT_SMTC */
/* Check if our ASID is of an older version and thus invalid */
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
get_new_mmu_context(next, cpu);
#ifdef CONFIG_MIPS_MT_SMTC
/*
* If the EntryHi ASID being replaced happens to be
* the value flagged at ASID recycling time as having
* an extended life, clear the bit showing it being
* in use by this "CPU", and if that's the last bit,
* free up the ASID value for use and flush any old
* instances of it from the TLB.
*/
oldasid = (read_c0_entryhi() & ASID_MASK);
if(smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
smtc_flush_tlb_asid(oldasid);
}
/*
* Tread softly on EntryHi, and so long as we support
* having ASID_MASK smaller than the hardware maximum,
* make sure no "soft" bits become "hard"...
*/
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
#else
write_c0_entryhi(cpu_asid(cpu, next));
#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/*
@@ -213,34 +168,12 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
unsigned long flags;
unsigned int cpu = smp_processor_id();
#ifdef CONFIG_MIPS_MT_SMTC
unsigned long oldasid;
unsigned long mtflags;
int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
#endif /* CONFIG_MIPS_MT_SMTC */
local_irq_save(flags);
/* Unconditionally get a new ASID. */
get_new_mmu_context(next, cpu);
#ifdef CONFIG_MIPS_MT_SMTC
/* See comments for similar code above */
mtflags = dvpe();
oldasid = read_c0_entryhi() & ASID_MASK;
if(smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
smtc_flush_tlb_asid(oldasid);
}
/* See comments for similar code above */
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
#else
write_c0_entryhi(cpu_asid(cpu, next));
#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/* mark mmu ownership change */
@@ -258,48 +191,15 @@ static inline void
drop_mmu_context(struct mm_struct *mm, unsigned cpu)
{
unsigned long flags;
#ifdef CONFIG_MIPS_MT_SMTC
unsigned long oldasid;
/* Can't use spinlock because called from TLB flush within DVPE */
unsigned int prevvpe;
int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
#endif /* CONFIG_MIPS_MT_SMTC */
local_irq_save(flags);
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
get_new_mmu_context(mm, cpu);
#ifdef CONFIG_MIPS_MT_SMTC
/* See comments for similar code above */
prevvpe = dvpe();
oldasid = (read_c0_entryhi() & ASID_MASK);
if (smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
smtc_flush_tlb_asid(oldasid);
}
/* See comments for similar code above */
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
| cpu_asid(cpu, mm));
ehb(); /* Make sure it propagates to TCStatus */
evpe(prevvpe);
#else /* not CONFIG_MIPS_MT_SMTC */
write_c0_entryhi(cpu_asid(cpu, mm));
#endif /* CONFIG_MIPS_MT_SMTC */
} else {
/* will get a new context next time */
#ifndef CONFIG_MIPS_MT_SMTC
cpu_context(cpu, mm) = 0;
#else /* SMTC */
int i;
/* SMTC shares the TLB (and ASIDs) across VPEs */
for_each_online_cpu(i) {
if((smtc_status & SMTC_TLB_SHARED)
|| (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
cpu_context(i, mm) = 0;
}
#endif /* CONFIG_MIPS_MT_SMTC */
}
local_irq_restore(flags);
}

View File

@@ -144,13 +144,7 @@ search_module_dbetables(unsigned long addr)
#define MODULE_KERNEL_TYPE "64BIT "
#endif
#ifdef CONFIG_MIPS_MT_SMTC
#define MODULE_KERNEL_SMTC "MT_SMTC "
#else
#define MODULE_KERNEL_SMTC ""
#endif
#define MODULE_ARCH_VERMAGIC \
MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC
MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
#endif /* _ASM_MODULE_H */

View File

@@ -84,7 +84,7 @@ static inline void write_msa_##name(unsigned int val) \
__asm__ __volatile__( \
" .set push\n" \
" .set msa\n" \
" cfcmsa $" #cs ", %0\n" \
" ctcmsa $" #cs ", %0\n" \
" .set pop\n" \
: : "r"(val)); \
}
@@ -96,6 +96,13 @@ static inline void write_msa_##name(unsigned int val) \
* allow compilation with toolchains that do not support MSA. Once all
* toolchains in use support MSA these can be removed.
*/
#ifdef CONFIG_CPU_MICROMIPS
#define CFC_MSA_INSN 0x587e0056
#define CTC_MSA_INSN 0x583e0816
#else
#define CFC_MSA_INSN 0x787e0059
#define CTC_MSA_INSN 0x783e0819
#endif
#define __BUILD_MSA_CTL_REG(name, cs) \
static inline unsigned int read_msa_##name(void) \
@@ -104,7 +111,8 @@ static inline unsigned int read_msa_##name(void) \
__asm__ __volatile__( \
" .set push\n" \
" .set noat\n" \
" .word 0x787e0059 | (" #cs " << 11)\n" \
" .insn\n" \
" .word #CFC_MSA_INSN | (" #cs " << 11)\n" \
" move %0, $1\n" \
" .set pop\n" \
: "=r"(reg)); \
@@ -117,7 +125,8 @@ static inline void write_msa_##name(unsigned int val) \
" .set push\n" \
" .set noat\n" \
" move $1, %0\n" \
" .word 0x783e0819 | (" #cs " << 6)\n" \
" .insn\n" \
" .word #CTC_MSA_INSN | (" #cs " << 6)\n" \
" .set pop\n" \
: : "r"(val)); \
}

View File

@@ -146,9 +146,10 @@ static inline int hard_smp_processor_id(void)
static inline int nlm_nodeid(void)
{
uint32_t prid = read_c0_prid();
uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
if ((prid & 0xff00) == PRID_IMP_NETLOGIC_XLP9XX)
if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
(prid == PRID_IMP_NETLOGIC_XLP5XX))
return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
else
return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;

View File

@@ -74,6 +74,8 @@
#define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 4)
#define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 5)
#define XLP_IO_SATA_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 2)
/* XLP2xx has an updated USB block */
#define XLP2XX_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 4, i)
#define XLP2XX_IO_USB_XHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -103,13 +105,11 @@
#define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 5)
#define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 6)
/* Flash */
#define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 0)
#define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 1)
#define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 2)
/* SD flash */
#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3)
#define XLP_IO_MMC_OFFSET(node, slot) \
((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
#define XLP_IO_MMC_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3)
/* Things have changed drastically in XLP 9XX */
#define XLP9XX_HDR_OFFSET(n, d, f) \
@@ -120,6 +120,8 @@
#define XLP9XX_IO_UART_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 2)
#define XLP9XX_IO_SYS_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 0)
#define XLP9XX_IO_FUSE_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 1)
#define XLP9XX_IO_CLOCK_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 2)
#define XLP9XX_IO_POWER_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 3)
#define XLP9XX_IO_JTAG_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 4)
#define XLP9XX_IO_PCIE_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 1, i)
@@ -135,11 +137,11 @@
/* XLP9XX on-chip SATA controller */
#define XLP9XX_IO_SATA_OFFSET(node) XLP9XX_HDR_OFFSET(node, 3, 2)
/* Flash */
#define XLP9XX_IO_NOR_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 0)
#define XLP9XX_IO_NAND_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 1)
#define XLP9XX_IO_SPI_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 2)
/* SD flash */
#define XLP9XX_IO_MMCSD_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3)
#define XLP9XX_IO_MMC_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3)
/* PCI config header register id's */
#define XLP_PCI_CFGREG0 0x00
@@ -186,8 +188,10 @@
#define PCI_DEVICE_ID_NLM_NOR 0x1015
#define PCI_DEVICE_ID_NLM_NAND 0x1016
#define PCI_DEVICE_ID_NLM_MMC 0x1018
#define PCI_DEVICE_ID_NLM_XHCI 0x101d
#define PCI_DEVICE_ID_NLM_SATA 0x101A
#define PCI_DEVICE_ID_NLM_XHCI 0x101D
#define PCI_DEVICE_ID_XLP9XX_MMC 0x9018
#define PCI_DEVICE_ID_XLP9XX_SATA 0x901A
#define PCI_DEVICE_ID_XLP9XX_XHCI 0x901D

View File

@@ -69,6 +69,20 @@
#define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e
#define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f
#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE 0x264
#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT 0x265
#define PCIE_9XX_MSI_STATUS 0x283
#define PCIE_9XX_MSI_EN 0x284
/* 128 MSIX vectors available in 9xx */
#define PCIE_9XX_MSIX_STATUS0 0x286
#define PCIE_9XX_MSIX_STATUSX(n) (n + 0x286)
#define PCIE_9XX_MSIX_VEC 0x296
#define PCIE_9XX_MSIX_VECX(n) (n + 0x296)
#define PCIE_9XX_INT_STATUS0 0x397
#define PCIE_9XX_INT_STATUS1 0x398
#define PCIE_9XX_INT_EN0 0x399
#define PCIE_9XX_INT_EN1 0x39a
/* other */
#define PCIE_NLINKS 4

View File

@@ -199,6 +199,10 @@
#define PIC_IRT_PCIE_LINK_3_INDEX 81
#define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX)
#define PIC_9XX_IRT_PCIE_LINK_0_INDEX 191
#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
#define PIC_CLOCK_TIMER 7
#if !defined(LOCORE) && !defined(__ASSEMBLY__)

View File

@@ -118,6 +118,10 @@
#define SYS_SCRTCH3 0x4c
/* PLL registers XLP2XX */
#define SYS_CPU_PLL_CTRL0(core) (0x1c0 + (core * 4))
#define SYS_CPU_PLL_CTRL1(core) (0x1c1 + (core * 4))
#define SYS_CPU_PLL_CTRL2(core) (0x1c2 + (core * 4))
#define SYS_CPU_PLL_CTRL3(core) (0x1c3 + (core * 4))
#define SYS_PLL_CTRL0 0x240
#define SYS_PLL_CTRL1 0x241
#define SYS_PLL_CTRL2 0x242
@@ -147,6 +151,32 @@
#define SYS_SYS_PLL_MEM_REQ 0x2a3
#define SYS_PLL_MEM_STAT 0x2a4
/* PLL registers XLP9XX */
#define SYS_9XX_CPU_PLL_CTRL0(core) (0xc0 + (core * 4))
#define SYS_9XX_CPU_PLL_CTRL1(core) (0xc1 + (core * 4))
#define SYS_9XX_CPU_PLL_CTRL2(core) (0xc2 + (core * 4))
#define SYS_9XX_CPU_PLL_CTRL3(core) (0xc3 + (core * 4))
#define SYS_9XX_DMC_PLL_CTRL0 0x140
#define SYS_9XX_DMC_PLL_CTRL1 0x141
#define SYS_9XX_DMC_PLL_CTRL2 0x142
#define SYS_9XX_DMC_PLL_CTRL3 0x143
#define SYS_9XX_PLL_CTRL0 0x144
#define SYS_9XX_PLL_CTRL1 0x145
#define SYS_9XX_PLL_CTRL2 0x146
#define SYS_9XX_PLL_CTRL3 0x147
#define SYS_9XX_PLL_CTRL0_DEVX(x) (0x148 + (x) * 4)
#define SYS_9XX_PLL_CTRL1_DEVX(x) (0x149 + (x) * 4)
#define SYS_9XX_PLL_CTRL2_DEVX(x) (0x14a + (x) * 4)
#define SYS_9XX_PLL_CTRL3_DEVX(x) (0x14b + (x) * 4)
#define SYS_9XX_CPU_PLL_CHG_CTRL 0x188
#define SYS_9XX_PLL_CHG_CTRL 0x189
#define SYS_9XX_CLK_DEV_DIS 0x18a
#define SYS_9XX_CLK_DEV_SEL 0x18b
#define SYS_9XX_CLK_DEV_DIV 0x18d
#define SYS_9XX_CLK_DEV_CHG 0x18f
/* Registers changed on 9XX */
#define SYS_9XX_POWER_ON_RESET_CFG 0x00
#define SYS_9XX_CHIP_RESET 0x01
@@ -170,6 +200,11 @@
#define nlm_get_fuse_regbase(node) \
(nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ)
#define nlm_get_clock_pcibase(node) \
nlm_pcicfg_base(XLP9XX_IO_CLOCK_OFFSET(node))
#define nlm_get_clock_regbase(node) \
(nlm_get_clock_pcibase(node) + XLP_IO_PCI_HDRSZ)
unsigned int nlm_get_pic_frequency(int node);
#endif
#endif

View File

@@ -58,6 +58,10 @@
#define PIC_I2C_1_IRQ 31
#define PIC_I2C_2_IRQ 32
#define PIC_I2C_3_IRQ 33
#define PIC_SPI_IRQ 34
#define PIC_NAND_IRQ 37
#define PIC_SATA_IRQ 38
#define PIC_GPIO_IRQ 39
#define PIC_PCIE_LINK_MSI_IRQ_BASE 44 /* 44 - 47 MSI IRQ */
#define PIC_PCIE_LINK_MSI_IRQ(i) (44 + (i))
@@ -66,8 +70,9 @@
#define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */
#define PIC_PCIE_MSIX_IRQ(i) (48 + (i))
#define NLM_MSIX_VEC_BASE 96 /* 96 - 127 - MSIX mapped */
#define NLM_MSI_VEC_BASE 128 /* 128 -255 - MSI mapped */
/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
#define NLM_MSIX_VEC_BASE 96 /* 96 - 223 - MSIX mapped */
#define NLM_MSI_VEC_BASE 224 /* 224 -351 - MSI mapped */
#define NLM_PIC_INDIRECT_VEC_BASE 512
#define NLM_GPIO_VEC_BASE 768
@@ -95,17 +100,19 @@ void *xlp_dt_init(void *fdtp);
static inline int cpu_is_xlpii(void)
{
int chip = read_c0_prid() & 0xff00;
int chip = read_c0_prid() & PRID_IMP_MASK;
return chip == PRID_IMP_NETLOGIC_XLP2XX ||
chip == PRID_IMP_NETLOGIC_XLP9XX;
chip == PRID_IMP_NETLOGIC_XLP9XX ||
chip == PRID_IMP_NETLOGIC_XLP5XX;
}
static inline int cpu_is_xlp9xx(void)
{
int chip = read_c0_prid() & 0xff00;
int chip = read_c0_prid() & PRID_IMP_MASK;
return chip == PRID_IMP_NETLOGIC_XLP9XX;
return chip == PRID_IMP_NETLOGIC_XLP9XX ||
chip == PRID_IMP_NETLOGIC_XLP5XX;
}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_NLM_XLP_H */

View File

@@ -1,7 +1,7 @@
/*
* asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Copyright (C) 2000 Geert Uytterhoeven <geert@linux-m68k.org>
* Sony Software Development Center Europe (SDCE), Brussels
*
* This file is based on the following documentation:

View File

@@ -211,7 +211,6 @@ union octeon_cvmemctl {
extern void octeon_write_lcd(const char *s);
extern void octeon_check_cpu_bist(void);
extern int octeon_get_boot_debug_flag(void);
extern int octeon_get_boot_uart(void);
struct uart_port;

View File

@@ -32,6 +32,8 @@ struct vm_area_struct;
_page_cachable_default)
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
_PAGE_GLOBAL | _page_cachable_default)
#define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
_PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT)
#define PAGE_USERIO __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | _PAGE_WRITE | \
_page_cachable_default)
#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __MIPS_ASM_PM_CPS_H__
#define __MIPS_ASM_PM_CPS_H__
/*
* The CM & CPC can only handle coherence & power control on a per-core basis,
* thus in an MT system the VPEs within each core are coupled and can only
* enter or exit states requiring CM or CPC assistance in unison.
*/
#ifdef CONFIG_MIPS_MT
# define coupled_coherence cpu_has_mipsmt
#else
# define coupled_coherence 0
#endif
/* Enumeration of possible PM states */
enum cps_pm_state {
CPS_PM_NC_WAIT, /* MIPS wait instruction, non-coherent */
CPS_PM_CLOCK_GATED, /* Core clock gated */
CPS_PM_POWER_GATED, /* Core power gated */
CPS_PM_STATE_COUNT,
};
/**
* cps_pm_support_state - determine whether the system supports a PM state
* @state: the state to test for support
*
* Returns true if the system supports the given state, otherwise false.
*/
extern bool cps_pm_support_state(enum cps_pm_state state);
/**
* cps_pm_enter_state - enter a PM state
* @state: the state to enter
*
* Enter the given PM state. If coupled_coherence is non-zero then it is
* expected that this function be called at approximately the same time on
* each coupled CPU. Returns 0 on successful entry & exit, otherwise -errno.
*/
extern int cps_pm_enter_state(enum cps_pm_state state);
#endif /* __MIPS_ASM_PM_CPS_H__ */

159
arch/mips/include/asm/pm.h Normal file
View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2014 Imagination Technologies Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* PM helper macros for CPU power off (e.g. Suspend-to-RAM).
*/
#ifndef __ASM_PM_H
#define __ASM_PM_H
#ifdef __ASSEMBLY__
#include <asm/asm-offsets.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
/* Save CPU state to stack for suspend to RAM */
.macro SUSPEND_SAVE_REGS
subu sp, PT_SIZE
/* Call preserved GPRs */
LONG_S $16, PT_R16(sp)
LONG_S $17, PT_R17(sp)
LONG_S $18, PT_R18(sp)
LONG_S $19, PT_R19(sp)
LONG_S $20, PT_R20(sp)
LONG_S $21, PT_R21(sp)
LONG_S $22, PT_R22(sp)
LONG_S $23, PT_R23(sp)
LONG_S $28, PT_R28(sp)
LONG_S $30, PT_R30(sp)
LONG_S $31, PT_R31(sp)
/* A couple of CP0 registers with space in pt_regs */
mfc0 k0, CP0_STATUS
LONG_S k0, PT_STATUS(sp)
.endm
/* Restore CPU state from stack after resume from RAM */
.macro RESUME_RESTORE_REGS_RETURN
.set push
.set noreorder
/* A couple of CP0 registers with space in pt_regs */
LONG_L k0, PT_STATUS(sp)
mtc0 k0, CP0_STATUS
/* Call preserved GPRs */
LONG_L $16, PT_R16(sp)
LONG_L $17, PT_R17(sp)
LONG_L $18, PT_R18(sp)
LONG_L $19, PT_R19(sp)
LONG_L $20, PT_R20(sp)
LONG_L $21, PT_R21(sp)
LONG_L $22, PT_R22(sp)
LONG_L $23, PT_R23(sp)
LONG_L $28, PT_R28(sp)
LONG_L $30, PT_R30(sp)
LONG_L $31, PT_R31(sp)
/* Pop and return */
jr ra
addiu sp, PT_SIZE
.set pop
.endm
/* Get address of static suspend state into t1 */
.macro LA_STATIC_SUSPEND
la t1, mips_static_suspend_state
.endm
/* Save important CPU state for early restoration to global data */
.macro SUSPEND_SAVE_STATIC
#ifdef CONFIG_EVA
/*
* Segment configuration is saved in global data where it can be easily
* reloaded without depending on the segment configuration.
*/
mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
LONG_S k0, SSS_SEGCTL0(t1)
mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
LONG_S k0, SSS_SEGCTL1(t1)
mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
LONG_S k0, SSS_SEGCTL2(t1)
#endif
/* save stack pointer (pointing to GPRs) */
LONG_S sp, SSS_SP(t1)
.endm
/* Restore important CPU state early from global data */
.macro RESUME_RESTORE_STATIC
#ifdef CONFIG_EVA
/*
* Segment configuration must be restored prior to any access to
* allocated memory, as it may reside outside of the legacy kernel
* segments.
*/
LONG_L k0, SSS_SEGCTL0(t1)
mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
LONG_L k0, SSS_SEGCTL1(t1)
mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
LONG_L k0, SSS_SEGCTL2(t1)
mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
tlbw_use_hazard
#endif
/* restore stack pointer (pointing to GPRs) */
LONG_L sp, SSS_SP(t1)
.endm
/* flush caches to make sure context has reached memory */
.macro SUSPEND_CACHE_FLUSH
.extern __wback_cache_all
.set push
.set noreorder
la t1, __wback_cache_all
LONG_L t0, 0(t1)
jalr t0
nop
.set pop
.endm
/* Save suspend state and flush data caches to RAM */
.macro SUSPEND_SAVE
SUSPEND_SAVE_REGS
LA_STATIC_SUSPEND
SUSPEND_SAVE_STATIC
SUSPEND_CACHE_FLUSH
.endm
/* Restore saved state after resume from RAM and return */
.macro RESUME_RESTORE_RETURN
LA_STATIC_SUSPEND
RESUME_RESTORE_STATIC
RESUME_RESTORE_REGS_RETURN
.endm
#else /* __ASSEMBLY__ */
/**
* struct mips_static_suspend_state - Core saved CPU state across S2R.
* @segctl: CP0 Segment control registers.
* @sp: Stack frame where GP register context is saved.
*
* This structure contains minimal CPU state that must be saved in static kernel
* data in order to be able to restore the rest of the state. This includes
* segmentation configuration in the case of EVA being enabled, as they must be
* restored prior to any kmalloc'd memory being referenced (even the stack
* pointer).
*/
struct mips_static_suspend_state {
#ifdef CONFIG_EVA
unsigned long segctl[3];
#endif
unsigned long sp;
};
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_PM_HELPERS_H */

View File

@@ -39,9 +39,6 @@ struct pt_regs {
unsigned long cp0_badvaddr;
unsigned long cp0_cause;
unsigned long cp0_epc;
#ifdef CONFIG_MIPS_MT_SMTC
unsigned long cp0_tcstatus;
#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_CPU_CAVIUM_OCTEON
unsigned long long mpl[3]; /* MTM{0,1,2} */
unsigned long long mtp[3]; /* MTP{0,1,2} */

View File

@@ -43,11 +43,10 @@
: "i" (op), "R" (*(unsigned char *)(addr)))
#ifdef CONFIG_MIPS_MT
/*
* Temporary hacks for SMTC debug. Optionally force single-threaded
* execution during I-cache flushes.
*/
/*
* Optionally force single-threaded execution during I-cache flushes.
*/
#define PROTECT_CACHE_FLUSHES 1
#ifdef PROTECT_CACHE_FLUSHES
@@ -524,6 +523,8 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32,
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, )
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, )
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )

View File

@@ -69,6 +69,8 @@
#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */
#define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */
#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */
#define SGI_GIOEXP0_IRQ (SGINT_LOCAL2 + 6) /* Indy GIO EXP0 */
#define SGI_GIOEXP1_IRQ (SGINT_LOCAL2 + 7) /* Indy GIO EXP1 */
#define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE)

View File

@@ -13,17 +13,28 @@
#ifndef __ASSEMBLY__
struct boot_config {
unsigned int core;
unsigned int vpe;
struct vpe_boot_config {
unsigned long pc;
unsigned long sp;
unsigned long gp;
};
extern struct boot_config mips_cps_bootcfg;
struct core_boot_config {
atomic_t vpe_mask;
struct vpe_boot_config *vpe_config;
};
extern struct core_boot_config *mips_cps_core_bootcfg;
extern void mips_cps_core_entry(void);
extern void mips_cps_core_init(void);
extern struct vpe_boot_config *mips_cps_boot_vpes(void);
extern bool mips_cps_smp_in_use(void);
extern void mips_cps_pm_save(void);
extern void mips_cps_pm_restore(void);
#else /* __ASSEMBLY__ */

View File

@@ -26,7 +26,6 @@ struct plat_smp_ops {
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
void (*init_secondary)(void);
void (*smp_finish)(void);
void (*cpus_done)(void);
void (*boot_secondary)(int cpu, struct task_struct *idle);
void (*smp_setup)(void);
void (*prepare_cpus)(unsigned int max_cpus);

View File

@@ -46,6 +46,9 @@ extern int __cpu_logical_map[NR_CPUS];
extern volatile cpumask_t cpu_callin_map;
/* Mask of CPUs which are currently definitely operating coherently */
extern cpumask_t cpu_coherent_mask;
extern void asmlinkage smp_bootstrap(void);
/*

View File

@@ -1,78 +0,0 @@
#ifndef _ASM_SMTC_MT_H
#define _ASM_SMTC_MT_H
/*
* Definitions for SMTC multitasking on MIPS MT cores
*/
#include <asm/mips_mt.h>
#include <asm/smtc_ipi.h>
/*
* System-wide SMTC status information
*/
extern unsigned int smtc_status;
#define SMTC_TLB_SHARED 0x00000001
#define SMTC_MTC_ACTIVE 0x00000002
/*
* TLB/ASID Management information
*/
#define MAX_SMTC_TLBS 2
#define MAX_SMTC_ASIDS 256
#if NR_CPUS <= 8
typedef char asiduse;
#else
#if NR_CPUS <= 16
typedef short asiduse;
#else
typedef long asiduse;
#endif
#endif
/*
* VPE Management information
*/
#define MAX_SMTC_VPES MAX_SMTC_TLBS /* FIXME: May not always be true. */
extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
struct mm_struct;
struct task_struct;
void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
void self_ipi(struct smtc_ipi *);
void smtc_flush_tlb_asid(unsigned long asid);
extern int smtc_build_cpu_map(int startslot);
extern void smtc_prepare_cpus(int cpus);
extern void smtc_smp_finish(void);
extern void smtc_boot_secondary(int cpu, struct task_struct *t);
extern void smtc_cpus_done(void);
extern void smtc_init_secondary(void);
/*
* Sharing the TLB between multiple VPEs means that the
* "random" index selection function is not allowed to
* select the current value of the Index register. To
* avoid additional TLB pressure, the Index registers
* are "parked" with an non-Valid value.
*/
#define PARKED_INDEX ((unsigned int)0x80000000)
/*
* Define low-level interrupt mask for IPIs, if necessary.
* By default, use SW interrupt 1, which requires no external
* hardware support, but which works only for single-core
* MIPS MT systems.
*/
#ifndef MIPS_CPU_IPI_IRQ
#define MIPS_CPU_IPI_IRQ 1
#endif
#endif /* _ASM_SMTC_MT_H */

View File

@@ -1,129 +0,0 @@
/*
* Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
*/
#ifndef __ASM_SMTC_IPI_H
#define __ASM_SMTC_IPI_H
#include <linux/spinlock.h>
//#define SMTC_IPI_DEBUG
#ifdef SMTC_IPI_DEBUG
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#endif /* SMTC_IPI_DEBUG */
/*
* An IPI "message"
*/
struct smtc_ipi {
struct smtc_ipi *flink;
int type;
void *arg;
int dest;
#ifdef SMTC_IPI_DEBUG
int sender;
long stamp;
#endif /* SMTC_IPI_DEBUG */
};
/*
* Defined IPI Types
*/
#define LINUX_SMP_IPI 1
#define SMTC_CLOCK_TICK 2
#define IRQ_AFFINITY_IPI 3
/*
* A queue of IPI messages
*/
struct smtc_ipi_q {
struct smtc_ipi *head;
spinlock_t lock;
struct smtc_ipi *tail;
int depth;
int resched_flag; /* reschedule already queued */
};
static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
if (q->head == NULL)
q->head = q->tail = p;
else
q->tail->flink = p;
p->flink = NULL;
q->tail = p;
q->depth++;
#ifdef SMTC_IPI_DEBUG
p->sender = read_c0_tcbind();
p->stamp = read_c0_count();
#endif /* SMTC_IPI_DEBUG */
spin_unlock_irqrestore(&q->lock, flags);
}
static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q)
{
struct smtc_ipi *p;
if (q->head == NULL)
p = NULL;
else {
p = q->head;
q->head = q->head->flink;
q->depth--;
/* Arguably unnecessary, but leaves queue cleaner */
if (q->head == NULL)
q->tail = NULL;
}
return p;
}
static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
{
unsigned long flags;
struct smtc_ipi *p;
spin_lock_irqsave(&q->lock, flags);
p = __smtc_ipi_dq(q);
spin_unlock_irqrestore(&q->lock, flags);
return p;
}
static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
if (q->head == NULL) {
q->head = q->tail = p;
p->flink = NULL;
} else {
p->flink = q->head;
q->head = p;
}
q->depth++;
spin_unlock_irqrestore(&q->lock, flags);
}
static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
{
unsigned long flags;
int retval;
spin_lock_irqsave(&q->lock, flags);
retval = q->depth;
spin_unlock_irqrestore(&q->lock, flags);
return retval;
}
extern void smtc_send_ipi(int cpu, int type, unsigned int action);
#endif /* __ASM_SMTC_IPI_H */

View File

@@ -1,23 +0,0 @@
/*
* Definitions for SMTC /proc entries
* Copyright(C) 2005 MIPS Technologies Inc.
*/
#ifndef __ASM_SMTC_PROC_H
#define __ASM_SMTC_PROC_H
/*
* per-"CPU" statistics
*/
struct smtc_cpu_proc {
unsigned long timerints;
unsigned long selfipis;
};
extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
/* Count of number of recoveries of "stolen" FPU access rights on 34K */
extern atomic_t smtc_fpu_recoveries;
#endif /* __ASM_SMTC_PROC_H */

View File

@@ -19,22 +19,12 @@
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
/*
* For SMTC kernel, global IE should be left set, and interrupts
* controlled exclusively via IXMT.
*/
#ifdef CONFIG_MIPS_MT_SMTC
#define STATMASK 0x1e
#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define STATMASK 0x3f
#else
#define STATMASK 0x1f
#endif
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */
.macro SAVE_AT
.set push
.set noat
@@ -186,16 +176,6 @@
mfc0 v1, CP0_STATUS
LONG_S $2, PT_R2(sp)
LONG_S v1, PT_STATUS(sp)
#ifdef CONFIG_MIPS_MT_SMTC
/*
* Ideally, these instructions would be shuffled in
* to cover the pipeline delay.
*/
.set mips32
mfc0 k0, CP0_TCSTATUS
.set mips0
LONG_S k0, PT_TCSTATUS(sp)
#endif /* CONFIG_MIPS_MT_SMTC */
LONG_S $4, PT_R4(sp)
mfc0 v1, CP0_CAUSE
LONG_S $5, PT_R5(sp)
@@ -321,36 +301,6 @@
.set push
.set reorder
.set noat
#ifdef CONFIG_MIPS_MT_SMTC
.set mips32r2
/*
* We need to make sure the read-modify-write
* of Status below isn't perturbed by an interrupt
* or cross-TC access, so we need to do at least a DMT,
* protected by an interrupt-inhibit. But setting IXMT
* also creates a few-cycle window where an IPI could
* be queued and not be detected before potentially
* returning to a WAIT or user-mode loop. It must be
* replayed.
*
* We're in the middle of a context switch, and
* we can't dispatch it directly without trashing
* some registers, so we'll try to detect this unlikely
* case and program a software interrupt in the VPE,
* as would be done for a cross-VPE IPI. To accommodate
* the handling of that case, we're doing a DVPE instead
* of just a DMT here to protect against other threads.
* This is a lot of cruft to cover a tiny window.
* If you can find a better design, implement it!
*
*/
mfc0 v0, CP0_TCSTATUS
ori v0, TCSTATUS_IXMT
mtc0 v0, CP0_TCSTATUS
_ehb
DVPE 5 # dvpe a1
jal mips_ihb
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 a0, CP0_STATUS
ori a0, STATMASK
xori a0, STATMASK
@@ -362,59 +312,6 @@
and v0, v1
or v0, a0
mtc0 v0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC
/*
* Only after EXL/ERL have been restored to status can we
* restore TCStatus.IXMT.
*/
LONG_L v1, PT_TCSTATUS(sp)
_ehb
mfc0 a0, CP0_TCSTATUS
andi v1, TCSTATUS_IXMT
bnez v1, 0f
/*
* We'd like to detect any IPIs queued in the tiny window
* above and request an software interrupt to service them
* when we ERET.
*
* Computing the offset into the IPIQ array of the executing
* TC's IPI queue in-line would be tedious. We use part of
* the TCContext register to hold 16 bits of offset that we
* can add in-line to find the queue head.
*/
mfc0 v0, CP0_TCCONTEXT
la a2, IPIQ
srl v0, v0, 16
addu a2, a2, v0
LONG_L v0, 0(a2)
beqz v0, 0f
/*
* If we have a queue, provoke dispatch within the VPE by setting C_SW1
*/
mfc0 v0, CP0_CAUSE
ori v0, v0, C_SW1
mtc0 v0, CP0_CAUSE
0:
/*
* This test should really never branch but
* let's be prudent here. Having atomized
* the shared register modifications, we can
* now EVPE, and must do so before interrupts
* are potentially re-enabled.
*/
andi a1, a1, MVPCONTROL_EVP
beqz a1, 1f
evpe
1:
/* We know that TCStatua.IXMT should be set from above */
xori a0, a0, TCSTATUS_IXMT
or a0, a0, v1
mtc0 a0, CP0_TCSTATUS
_ehb
.set mips0
#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v1, PT_EPC(sp)
MTC0 v1, CP0_EPC
LONG_L $31, PT_R31(sp)
@@ -467,33 +364,11 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro CLI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK
or t0, t1
xori t0, STATMASK
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
* For SMTC, we need to set privilege
* and disable interrupts only for the
* current TC, using the TCStatus register.
*/
mfc0 t0, CP0_TCSTATUS
/* Fortunately CU 0 is in the same place in both registers */
/* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
li t1, ST0_CU0 | 0x08001c00
or t0, t1
/* Clear TKSU, leave IXMT */
xori t0, 0x00001800
mtc0 t0, CP0_TCSTATUS
_ehb
/* We need to leave the global IE bit set, but clear EXL...*/
mfc0 t0, CP0_STATUS
ori t0, ST0_EXL | ST0_ERL
xori t0, ST0_EXL | ST0_ERL
mtc0 t0, CP0_STATUS
#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
@@ -502,35 +377,11 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro STI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK
or t0, t1
xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
* For SMTC, we need to set privilege
* and enable interrupts only for the
* current TC, using the TCStatus register.
*/
_ehb
mfc0 t0, CP0_TCSTATUS
/* Fortunately CU 0 is in the same place in both registers */
/* Set TCU0, TKSU (for later inversion) and IXMT */
li t1, ST0_CU0 | 0x08001c00
or t0, t1
/* Clear TKSU *and* IXMT */
xori t0, 0x00001c00
mtc0 t0, CP0_TCSTATUS
_ehb
/* We need to leave the global IE bit set, but clear EXL...*/
mfc0 t0, CP0_STATUS
ori t0, ST0_EXL
xori t0, ST0_EXL
mtc0 t0, CP0_STATUS
/* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
#endif /* CONFIG_MIPS_MT_SMTC */
irq_enable_hazard
.endm
@@ -540,32 +391,6 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
#ifdef CONFIG_MIPS_MT_SMTC
/*
* This gets baroque in SMTC. We want to
* protect the non-atomic clearing of EXL
* with DMT/EMT, but we don't want to take
* an interrupt while DMT is still in effect.
*/
/* KMODE gets invoked from both reorder and noreorder code */
.set push
.set mips32r2
.set noreorder
mfc0 v0, CP0_TCSTATUS
andi v1, v0, TCSTATUS_IXMT
ori v0, TCSTATUS_IXMT
mtc0 v0, CP0_TCSTATUS
_ehb
DMT 2 # dmt v0
/*
* We don't know a priori if ra is "live"
*/
move t0, ra
jal mips_ihb
nop /* delay slot */
move ra, t0
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | (STATMASK & ~1)
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
@@ -576,25 +401,6 @@
or t0, t1
xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC
_ehb
andi v0, v0, VPECONTROL_TE
beqz v0, 2f
nop /* delay slot */
emt
2:
mfc0 v0, CP0_TCSTATUS
/* Clear IXMT, then OR in previous value */
ori v0, TCSTATUS_IXMT
xori v0, TCSTATUS_IXMT
or v0, v1, v0
mtc0 v0, CP0_TCSTATUS
/*
* irq_disable_hazard below should expand to EHB
* on 24K/34K CPUS
*/
.set pop
#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm

View File

@@ -159,11 +159,7 @@ static inline struct thread_info *current_thread_info(void)
* We stash processor id into a COP0 register to retrieve it fast
* at kernel exception entry.
*/
#if defined(CONFIG_MIPS_MT_SMTC)
#define SMP_CPUID_REG 2, 2 /* TCBIND */
#define ASM_SMP_CPUID_REG $2, 2
#define SMP_CPUID_PTRSHIFT 19
#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
#define SMP_CPUID_REG 20, 0 /* XCONTEXT */
#define ASM_SMP_CPUID_REG $20
#define SMP_CPUID_PTRSHIFT 48
@@ -179,13 +175,8 @@ static inline struct thread_info *current_thread_info(void)
#define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 2)
#endif
#ifdef CONFIG_MIPS_MT_SMTC
#define ASM_CPUID_MFC0 mfc0
#define UASM_i_CPUID_MFC0 uasm_i_mfc0
#else
#define ASM_CPUID_MFC0 MFC0
#define UASM_i_CPUID_MFC0 UASM_i_MFC0
#endif
#endif /* __KERNEL__ */
#endif /* _ASM_THREAD_INFO_H */

View File

@@ -52,14 +52,11 @@ extern int (*perf_irq)(void);
*/
extern unsigned int __weak get_c0_compare_int(void);
extern int r4k_clockevent_init(void);
extern int smtc_clockevent_init(void);
extern int gic_clockevent_init(void);
static inline int mips_clockevent_init(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
return smtc_clockevent_init();
#elif defined(CONFIG_CEVT_GIC)
#if defined(CONFIG_CEVT_GIC)
return (gic_clockevent_init() | r4k_clockevent_init());
#elif defined(CONFIG_CEVT_R4K)
return r4k_clockevent_init();

View File

@@ -4,12 +4,16 @@
* for more details.
*
* Copyright (C) 1998, 1999, 2003 by Ralf Baechle
* Copyright (C) 2014 by Maciej W. Rozycki
*/
#ifndef _ASM_TIMEX_H
#define _ASM_TIMEX_H
#ifdef __KERNEL__
#include <linux/compiler.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/mipsregs.h>
#include <asm/cpu-type.h>
@@ -45,30 +49,55 @@ typedef unsigned int cycles_t;
* However for now the implementaton of this function doesn't get these
* fine details right.
*/
static inline int can_use_mips_counter(unsigned int prid)
{
int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY;
if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter)
return 0;
else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r)
return 1;
else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp))
return 1;
/* Make sure we don't peek at cpu_data[0].options in the fast path! */
if (!__builtin_constant_p(cpu_has_counter))
asm volatile("" : "=m" (cpu_data[0].options));
if (likely(cpu_has_counter &&
prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0))))
return 1;
else
return 0;
}
static inline cycles_t get_cycles(void)
{
switch (boot_cpu_type()) {
case CPU_R4400PC:
case CPU_R4400SC:
case CPU_R4400MC:
if ((read_c0_prid() & 0xff) >= 0x0050)
return read_c0_count();
break;
case CPU_R4000PC:
case CPU_R4000SC:
case CPU_R4000MC:
break;
default:
if (cpu_has_counter)
return read_c0_count();
break;
}
return 0; /* no usable counter */
if (can_use_mips_counter(read_c0_prid()))
return read_c0_count();
else
return 0; /* no usable counter */
}
/*
* Like get_cycles - but where c0_count is not available we desperately
* use c0_random in an attempt to get at least a little bit of entropy.
*
* R6000 and R6000A neither have a count register nor a random register.
* That leaves no entropy source in the CPU itself.
*/
static inline unsigned long random_get_entropy(void)
{
unsigned int prid = read_c0_prid();
unsigned int imp = prid & PRID_IMP_MASK;
if (can_use_mips_counter(prid))
return read_c0_count();
else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
return read_c0_random();
else
return 0; /* no usable register */
}
#define random_get_entropy random_get_entropy
#endif /* __KERNEL__ */
#endif /* _ASM_TIMEX_H */

View File

@@ -55,6 +55,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u2u1u3(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u3u2u1(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u3u1u2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
@@ -74,6 +77,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
#define Ip_u1u2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
#define Ip_u2u1(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
#define Ip_u1s2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, signed int b)
@@ -99,6 +105,7 @@ Ip_u2u1s3(_daddiu);
Ip_u3u1u2(_daddu);
Ip_u2u1msbu3(_dins);
Ip_u2u1msbu3(_dinsm);
Ip_u1u2(_divu);
Ip_u1u2u3(_dmfc0);
Ip_u1u2u3(_dmtc0);
Ip_u2u1u3(_drotr);
@@ -114,16 +121,22 @@ Ip_u2u1msbu3(_ext);
Ip_u2u1msbu3(_ins);
Ip_u1(_j);
Ip_u1(_jal);
Ip_u2u1(_jalr);
Ip_u1(_jr);
Ip_u2s3u1(_lb);
Ip_u2s3u1(_ld);
Ip_u3u1u2(_ldx);
Ip_u2s3u1(_lh);
Ip_u2s3u1(_ll);
Ip_u2s3u1(_lld);
Ip_u1s2(_lui);
Ip_u2s3u1(_lw);
Ip_u3u1u2(_lwx);
Ip_u1u2u3(_mfc0);
Ip_u1(_mfhi);
Ip_u1(_mflo);
Ip_u1u2u3(_mtc0);
Ip_u3u1u2(_mul);
Ip_u3u1u2(_or);
Ip_u2u1u3(_ori);
Ip_u2s3u1(_pref);
@@ -133,17 +146,25 @@ Ip_u2s3u1(_sc);
Ip_u2s3u1(_scd);
Ip_u2s3u1(_sd);
Ip_u2u1u3(_sll);
Ip_u3u2u1(_sllv);
Ip_u2u1s3(_sltiu);
Ip_u3u1u2(_sltu);
Ip_u2u1u3(_sra);
Ip_u2u1u3(_srl);
Ip_u3u2u1(_srlv);
Ip_u3u1u2(_subu);
Ip_u2s3u1(_sw);
Ip_u1(_sync);
Ip_u1(_syscall);
Ip_0(_tlbp);
Ip_0(_tlbr);
Ip_0(_tlbwi);
Ip_0(_tlbwr);
Ip_u1(_wait);
Ip_u2u1(_wsbh);
Ip_u3u1u2(_xor);
Ip_u2u1u3(_xori);
Ip_u2u1(_yield);
/* Handle labels. */
@@ -264,6 +285,8 @@ void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1,
unsigned int r2, int lid);
void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);