From b01da9f130adbf69cfbad2a65f1327f1382bf4ae Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 5 Jul 2012 18:12:38 +0200 Subject: MIPS: Prune some target specific code out of prom.c This code is not common enough to be in a shared file. It is also not used by any existing boards, so just remove it. [ralf@linux-mips.org: Dropped removal of irq_create_of_mapping which was already removed by abd2363f6a5f1030b935e0bdc15cf917313b3b10 [irq_domain/mips: Allow irq_domain on MIPS]. Moved device_tree_init() and dependencies to its sole user, the XLP code.] Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: devicetree-discuss@lists.ozlabs.org Cc: grant.likely@secretlab.ca Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/2946/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/prom.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index f11b2bbb826d..028f6f837ef9 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -35,16 +35,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) return add_memory_region(base, size, BOOT_MEM_RAM); } -int __init reserve_mem_mach(unsigned long addr, unsigned long size) -{ - return reserve_bootmem(addr, size, BOOTMEM_DEFAULT); -} - -void __init free_mem_mach(unsigned long addr, unsigned long size) -{ - return free_bootmem(addr, size); -} - void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); @@ -77,25 +67,6 @@ void __init early_init_devtree(void *params) of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); } -void __init device_tree_init(void) -{ - unsigned long base, size; - - if (!initial_boot_params) - return; - - base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); - - /* Before we do anything, lets reserve the dt blob */ - reserve_mem_mach(base, size); - - unflatten_device_tree(); - - /* free the space reserved for the dt blob */ - free_mem_mach(base, size); -} - void __init __dt_setup_arch(struct boot_param_header *bph) { if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { -- cgit v1.2.3 From 889a4c7b33607bf03c04b8f2d5607fd4274f47f3 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Mon, 9 Apr 2012 10:58:39 -0500 Subject: MIPS: SMTC: Support for Multi-threaded FPUs Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3603/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsmtregs.h | 13 +++++++ arch/mips/include/asm/smtc.h | 6 +++ arch/mips/kernel/smp.c | 4 +- arch/mips/kernel/smtc.c | 76 ++++++++++++++++++++++++++++++++++---- 4 files changed, 90 insertions(+), 9 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h index e71ff4c317f2..5b3cb8553e9a 100644 --- a/arch/mips/include/asm/mipsmtregs.h +++ b/arch/mips/include/asm/mipsmtregs.h @@ -28,6 +28,9 @@ #define read_c0_vpeconf0() __read_32bit_c0_register($1, 2) #define write_c0_vpeconf0(val) __write_32bit_c0_register($1, 2, val) +#define read_c0_vpeconf1() __read_32bit_c0_register($1, 3) +#define write_c0_vpeconf1(val) __write_32bit_c0_register($1, 3, val) + #define read_c0_tcstatus() __read_32bit_c0_register($2, 1) #define write_c0_tcstatus(val) __write_32bit_c0_register($2, 1, val) @@ -124,6 +127,14 @@ #define VPECONF0_XTC_SHIFT 21 #define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT) +/* VPEConf1 fields (per VPE) */ +#define VPECONF1_NCP1_SHIFT 0 +#define VPECONF1_NCP1 (_ULCAST_(0xff) << VPECONF1_NCP1_SHIFT) +#define VPECONF1_NCP2_SHIFT 10 +#define VPECONF1_NCP2 (_ULCAST_(0xff) << VPECONF1_NCP2_SHIFT) +#define VPECONF1_NCX_SHIFT 20 +#define VPECONF1_NCX (_ULCAST_(0xff) << VPECONF1_NCX_SHIFT) + /* TCStatus fields (per TC) */ #define TCSTATUS_TASID (_ULCAST_(0xff)) #define TCSTATUS_IXMT_SHIFT 10 @@ -350,6 +361,8 @@ do { \ #define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val) #define read_vpe_c0_vpeconf0() mftc0(1, 2) #define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val) +#define read_vpe_c0_vpeconf1() mftc0(1, 3) +#define write_vpe_c0_vpeconf1(val) mttc0(1, 3, val) #define read_vpe_c0_count() mftc0(9, 0) #define write_vpe_c0_count(val) mttc0(9, 0, val) #define read_vpe_c0_status() mftc0(12, 0) diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h index c9736fc06325..8935426a56ab 100644 --- a/arch/mips/include/asm/smtc.h +++ b/arch/mips/include/asm/smtc.h @@ -33,6 +33,12 @@ 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; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1268392f1d27..31637d8c8738 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void) #ifdef CONFIG_MIPS_MT_SMTC /* Only do cpu_probe for first TC of CPU */ - if ((read_c0_tcbind() & TCBIND_CURTC) == 0) + if ((read_c0_tcbind() & TCBIND_CURTC) != 0) + __cpu_name[smp_processor_id()] = __cpu_name[0]; + else #endif /* CONFIG_MIPS_MT_SMTC */ cpu_probe(); cpu_report(); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 15b5f3cfd20c..1d47843d3cc0 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS]; static struct smtc_ipi_q freeIPIq; +/* + * Number of FPU contexts for each VPE + */ + +static int smtc_nconf1[MAX_SMTC_VPES]; + + /* Forward declarations */ void ipi_decode(struct smtc_ipi *); @@ -174,9 +181,9 @@ static int __init tintq(char *str) __setup("tintq=", tintq); -static int imstuckcount[2][8]; +static int imstuckcount[MAX_SMTC_VPES][8]; /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ -static int vpemask[2][8] = { +static int vpemask[MAX_SMTC_VPES][8] = { {0, 0, 1, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 1} }; @@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot) static void smtc_tc_setup(int vpe, int tc, int cpu) { + static int cp1contexts[MAX_SMTC_VPES]; + + /* + * Make a local copy of the available FPU contexts in order + * to keep track of TCs that can have one. + */ + if (tc == 1) + { + /* + * FIXME: Multi-core SMTC hasn't been tested and the + * maximum number of VPEs may change. + */ + cp1contexts[0] = smtc_nconf1[0] - 1; + cp1contexts[1] = smtc_nconf1[1]; + } + settc(tc); write_tc_c0_tchalt(TCHALT_H); mips_ihb(); @@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) * an active IPI queue. */ write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); - /* Bind tc to vpe */ + + /* Bind TC to VPE. */ write_tc_c0_tcbind(vpe); + /* In general, all TCs should have the same cpu_data indications. */ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); - /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */ - if (cpu_data[0].cputype == CPU_34K || - cpu_data[0].cputype == CPU_1004K) + + /* Check to see if there is a FPU context available for this TC. */ + if (!cp1contexts[vpe]) cpu_data[cpu].options &= ~MIPS_CPU_FPU; + else + cp1contexts[vpe]--; + + /* Store the TC and VPE into the cpu_data structure. */ cpu_data[cpu].vpe_id = vpe; cpu_data[cpu].tc_id = tc; - /* Multi-core SMTC hasn't been tested, but be prepared */ + + /* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */ cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; } /* - * Tweak to get Count registes in as close a sync as possible. The + * Tweak to get Count registers synced as closely as possible. The * value seems good for 34K-class cores. */ @@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus) smtc_configure_tlb(); for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { + /* Get number of CP1 contexts for each VPE. */ + if (tc == 0) + { + /* + * Do not call settc() for TC0 or the FPU context + * value will be incorrect. Besides, we know that + * we are TC0 anyway. + */ + smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + if (nvpe == 2) + { + settc(1); + smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + settc(0); + } + } if (tcpervpe[vpe] == 0) continue; if (vpe != 0) @@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus) */ if (tc != 0) { smtc_tc_setup(vpe, tc, cpu); + if (vpe != 0) { + /* + * Set MVP bit (possibly again). Do it + * here to catch CPUs that have no TCs + * bound to the VPE at reset. In that + * case, a TC must be bound to the VPE + * before we can set VPEControl[MVP] + */ + write_vpe_c0_vpeconf0( + read_vpe_c0_vpeconf0() | + VPECONF0_MVP); + } cpu++; } printk(" %d", tc); -- cgit v1.2.3 From 2fa36399e63c911134f28b6878aada9b395c4209 Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 20 Jun 2012 20:05:32 +0100 Subject: MIPS: Add CPU support for Loongson1B Loongson 1B is a 32-bit SoC designed by Institute of Computing Technology (ICT) and the Chinese Academy of Sciences (CAS), which implements the MIPS32 release 2 instruction set. [ralf@linux-mips.org: But which is not strictly a MIPS32 compliant device which also is why it identifies itself with the Legacy Vendor ID in the PrID register. When applying the patch I shoveled some code around to keep things in alphabetical order and avoid forward declarations.] Signed-off-by: Kelvin Cheung Cc: To: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: wuzhangjin@gmail.com Cc: zhzhl555@gmail.com Cc: Kelvin Cheung Patchwork: https://patchwork.linux-mips.org/patch/3976/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 3 +- arch/mips/include/asm/module.h | 2 + arch/mips/kernel/cpu-probe.c | 299 ++++++++++++++++++----------------- arch/mips/kernel/perf_event_mipsxx.c | 5 + arch/mips/kernel/traps.c | 1 + arch/mips/oprofile/common.c | 1 + arch/mips/oprofile/op_model_mipsxx.c | 4 + 7 files changed, 171 insertions(+), 144 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 95e40c1e8ed1..f21b7c04e95a 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -197,6 +197,7 @@ #define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ #define PRID_REV_VR4130 0x0080 #define PRID_REV_34K_V1_0_2 0x0022 +#define PRID_REV_LOONGSON1B 0x0020 #define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2F 0x0003 @@ -261,7 +262,7 @@ enum cpu_type_enum { */ CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, - CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC, + CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, /* * MIPS64 class processors diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index 530008048c62..7531ecd654d6 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -117,6 +117,8 @@ search_module_dbetables(unsigned long addr) #define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 #define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON1 +#define MODULE_PROC_FAMILY "LOONGSON1 " #elif defined CONFIG_CPU_LOONGSON2 #define MODULE_PROC_FAMILY "LOONGSON2 " #elif defined CONFIG_CPU_CAVIUM_OCTEON diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f4630e1082ab..1b51046191e8 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -190,6 +190,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: case CPU_JZRISC: + case CPU_LOONGSON1: case CPU_XLR: case CPU_XLP: cpu_wait = r4k_wait; @@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) #endif } +static char unknown_isa[] __cpuinitdata = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + +static inline unsigned int decode_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + int isa; + + config0 = read_c0_config(); + + if (((config0 & MIPS_CONF_MT) >> 7) == 1) + c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; + switch (isa) { + case 0: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } + break; + case 2: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } + break; + default: + goto unknown; + } + + return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); +} + +static inline unsigned int decode_config1(struct cpuinfo_mips *c) +{ + unsigned int config1; + + config1 = read_c0_config1(); + + if (config1 & MIPS_CONF1_MD) + c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_WR) + c->options |= MIPS_CPU_WATCH; + if (config1 & MIPS_CONF1_CA) + c->ases |= MIPS_ASE_MIPS16; + if (config1 & MIPS_CONF1_EP) + c->options |= MIPS_CPU_EJTAG; + if (config1 & MIPS_CONF1_FP) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + if (cpu_has_tlb) + c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; + + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + config2 = read_c0_config2(); + + if (config2 & MIPS_CONF2_SL) + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_config3(struct cpuinfo_mips *c) +{ + unsigned int config3; + + config3 = read_c0_config3(); + + if (config3 & MIPS_CONF3_SM) + c->ases |= MIPS_ASE_SMARTMIPS; + if (config3 & MIPS_CONF3_DSP) + c->ases |= MIPS_ASE_DSP; + if (config3 & MIPS_CONF3_VINT) + c->options |= MIPS_CPU_VINT; + if (config3 & MIPS_CONF3_VEIC) + c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_MT) + c->ases |= MIPS_ASE_MIPSMT; + if (config3 & MIPS_CONF3_ULRI) + c->options |= MIPS_CPU_ULRI; + + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + config4 = read_c0_config4(); + + if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT + && cpu_has_tlb) + c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + + c->kscratch_mask = (config4 >> 16) & 0xff; + + return config4 & MIPS_CONF_M; +} + +static void __cpuinit decode_configs(struct cpuinfo_mips *c) +{ + int ok; + + /* MIPS32 or MIPS64 compliant CPU. */ + c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + ok = decode_config0(c); /* Read Config registers. */ + BUG_ON(!ok); /* Arch spec violation! */ + if (ok) + ok = decode_config1(c); + if (ok) + ok = decode_config2(c); + if (ok) + ok = decode_config3(c); + if (ok) + ok = decode_config4(c); + + mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) MIPS_CPU_32FPR; c->tlbsize = 64; break; - } -} - -static char unknown_isa[] __cpuinitdata = KERN_ERR \ - "Unsupported ISA type, c0.config0: %d."; + case PRID_IMP_LOONGSON1: + decode_configs(c); -static inline unsigned int decode_config0(struct cpuinfo_mips *c) -{ - unsigned int config0; - int isa; + c->cputype = CPU_LOONGSON1; - config0 = read_c0_config(); - - if (((config0 & MIPS_CONF_MT) >> 7) == 1) - c->options |= MIPS_CPU_TLB; - isa = (config0 & MIPS_CONF_AT) >> 13; - switch (isa) { - case 0: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M32R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M32R2; + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON1B: + __cpu_name[cpu] = "Loongson 1B"; break; - default: - goto unknown; } - break; - case 2: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M64R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M64R2; - break; - default: - goto unknown; - } - break; - default: - goto unknown; - } - - return config0 & MIPS_CONF_M; - -unknown: - panic(unknown_isa, config0); -} -static inline unsigned int decode_config1(struct cpuinfo_mips *c) -{ - unsigned int config1; - - config1 = read_c0_config1(); - - if (config1 & MIPS_CONF1_MD) - c->ases |= MIPS_ASE_MDMX; - if (config1 & MIPS_CONF1_WR) - c->options |= MIPS_CPU_WATCH; - if (config1 & MIPS_CONF1_CA) - c->ases |= MIPS_ASE_MIPS16; - if (config1 & MIPS_CONF1_EP) - c->options |= MIPS_CPU_EJTAG; - if (config1 & MIPS_CONF1_FP) { - c->options |= MIPS_CPU_FPU; - c->options |= MIPS_CPU_32FPR; + break; } - if (cpu_has_tlb) - c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; - - return config1 & MIPS_CONF_M; -} - -static inline unsigned int decode_config2(struct cpuinfo_mips *c) -{ - unsigned int config2; - - config2 = read_c0_config2(); - - if (config2 & MIPS_CONF2_SL) - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; - - return config2 & MIPS_CONF_M; -} - -static inline unsigned int decode_config3(struct cpuinfo_mips *c) -{ - unsigned int config3; - - config3 = read_c0_config3(); - - if (config3 & MIPS_CONF3_SM) - c->ases |= MIPS_ASE_SMARTMIPS; - if (config3 & MIPS_CONF3_DSP) - c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_VINT) - c->options |= MIPS_CPU_VINT; - if (config3 & MIPS_CONF3_VEIC) - c->options |= MIPS_CPU_VEIC; - if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; - if (config3 & MIPS_CONF3_ULRI) - c->options |= MIPS_CPU_ULRI; - - return config3 & MIPS_CONF_M; -} - -static inline unsigned int decode_config4(struct cpuinfo_mips *c) -{ - unsigned int config4; - - config4 = read_c0_config4(); - - if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT - && cpu_has_tlb) - c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; - - c->kscratch_mask = (config4 >> 16) & 0xff; - - return config4 & MIPS_CONF_M; -} - -static void __cpuinit decode_configs(struct cpuinfo_mips *c) -{ - int ok; - - /* MIPS32 or MIPS64 compliant CPU. */ - c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; - - c->scache.flags = MIPS_CACHE_NOT_PRESENT; - - ok = decode_config0(c); /* Read Config registers. */ - BUG_ON(!ok); /* Arch spec violation! */ - if (ok) - ok = decode_config1(c); - if (ok) - ok = decode_config2(c); - if (ok) - ok = decode_config3(c); - if (ok) - ok = decode_config4(c); - - mips_probe_watch_registers(c); - - if (cpu_has_mips_r2) - c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index eb5e394a4650..2f28d3b55687 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1559,6 +1559,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.cache_event_map = &mipsxxcore_cache_map; break; + case CPU_LOONGSON1: + mipspmu.name = "mips/loongson1"; + mipspmu.general_event_map = &mipsxxcore_event_map; + mipspmu.cache_event_map = &mipsxxcore_cache_map; + break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c3c293543703..9be3df1fa8a4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void) case CPU_5KC: case CPU_5KE: + case CPU_LOONGSON1: write_c0_ecc(0x80000000); back_to_back_c0_hazard(); /* Set the PE bit (bit 31) in the c0_errctl register. */ diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index b6e378211a2c..f80480a5a032 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_34K: case CPU_1004K: case CPU_74K: + case CPU_LOONGSON1: case CPU_SB1: case CPU_SB1A: case CPU_R10000: diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 4d80a856048d..056da6224163 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -374,6 +374,10 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/sb1"; break; + case CPU_LOONGSON1: + op_model_mipsxx_ops.cpu_type = "mips/loongson1"; + break; + default: printk(KERN_ERR "Profiling unsupported for this CPU\n"); -- cgit v1.2.3 From 95cf1468f712df516cc471adcd1c861df4e3d371 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 1 Aug 2012 17:15:32 +0200 Subject: MIPS: Loongson 2: Sort out clock managment. For unexplainable reasons the Loongson 2 clock API was implemented in a module so fixing this involved shifting large amounts of code around. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/clock.h | 11 -- arch/mips/include/asm/mach-loongson/loongson.h | 1 - arch/mips/kernel/cpufreq/Makefile | 2 +- arch/mips/kernel/cpufreq/loongson2_clock.c | 171 ------------------------- arch/mips/kernel/cpufreq/loongson2_cpufreq.c | 21 ++- arch/mips/loongson/Kconfig | 1 + arch/mips/loongson/lemote-2f/Makefile | 2 +- arch/mips/loongson/lemote-2f/clock.c | 145 +++++++++++++++++++++ 8 files changed, 168 insertions(+), 186 deletions(-) delete mode 100644 arch/mips/kernel/cpufreq/loongson2_clock.c create mode 100644 arch/mips/loongson/lemote-2f/clock.c (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h index 83894aa7932c..c9456e7a7283 100644 --- a/arch/mips/include/asm/clock.h +++ b/arch/mips/include/asm/clock.h @@ -50,15 +50,4 @@ void clk_recalc_rate(struct clk *); int clk_register(struct clk *); void clk_unregister(struct clk *); -/* the exported API, in addition to clk_set_rate */ -/** - * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter - * @clk: clock source - * @rate: desired clock rate in Hz - * @algo_id: algorithm id to be passed down to ops->set_rate - * - * Returns success (0) or negative errno. - */ -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); - #endif /* __ASM_MIPS_CLOCK_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 06367c37e1b2..5222a007bc21 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -245,7 +245,6 @@ static inline void do_perfcnt_IRQ(void) #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ #include -extern void loongson2_cpu_wait(void); extern struct cpufreq_frequency_table loongson2_clockmod_table[]; /* Chip Config */ diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile index c3479a432efe..05a5715ee38c 100644 --- a/arch/mips/kernel/cpufreq/Makefile +++ b/arch/mips/kernel/cpufreq/Makefile @@ -2,4 +2,4 @@ # Makefile for the Linux/MIPS cpufreq. # -obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o +obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c deleted file mode 100644 index 5426779d9fdb..000000000000 --- a/arch/mips/kernel/cpufreq/loongson2_clock.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology - * Author: Yanhua, yanh@lemote.com - * - * 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. - */ - -#include -#include -#include - -#include - -#include - -static LIST_HEAD(clock_list); -static DEFINE_SPINLOCK(clock_lock); -static DEFINE_MUTEX(clock_list_sem); - -/* Minimum CLK support */ -enum { - DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT, - DC_87PT, DC_DISABLE, DC_RESV -}; - -struct cpufreq_frequency_table loongson2_clockmod_table[] = { - {DC_RESV, CPUFREQ_ENTRY_INVALID}, - {DC_ZERO, CPUFREQ_ENTRY_INVALID}, - {DC_25PT, 0}, - {DC_37PT, 0}, - {DC_50PT, 0}, - {DC_62PT, 0}, - {DC_75PT, 0}, - {DC_87PT, 0}, - {DC_DISABLE, 0}, - {DC_RESV, CPUFREQ_TABLE_END}, -}; -EXPORT_SYMBOL_GPL(loongson2_clockmod_table); - -static struct clk cpu_clk = { - .name = "cpu_clk", - .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, - .rate = 800000000, -}; - -struct clk *clk_get(struct device *dev, const char *id) -{ - return &cpu_clk; -} -EXPORT_SYMBOL(clk_get); - -static void propagate_rate(struct clk *clk) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->parent != clk)) - continue; - if (likely(clkp->ops && clkp->ops->recalc)) - clkp->ops->recalc(clkp); - if (unlikely(clkp->flags & CLK_RATE_PROPAGATES)) - propagate_rate(clkp); - } -} - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return (unsigned long)clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return clk_set_rate_ex(clk, rate, 0); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) -{ - int ret = 0; - int regval; - int i; - - if (likely(clk->ops && clk->ops->set_rate)) { - unsigned long flags; - - spin_lock_irqsave(&clock_lock, flags); - ret = clk->ops->set_rate(clk, rate, algo_id); - spin_unlock_irqrestore(&clock_lock, flags); - } - - if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) - propagate_rate(clk); - - for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END; - i++) { - if (loongson2_clockmod_table[i].frequency == - CPUFREQ_ENTRY_INVALID) - continue; - if (rate == loongson2_clockmod_table[i].frequency) - break; - } - if (rate != loongson2_clockmod_table[i].frequency) - return -ENOTSUPP; - - clk->rate = rate; - - regval = LOONGSON_CHIPCFG0; - regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1); - LOONGSON_CHIPCFG0 = regval; - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate_ex); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (likely(clk->ops && clk->ops->round_rate)) { - unsigned long flags, rounded; - - spin_lock_irqsave(&clock_lock, flags); - rounded = clk->ops->round_rate(clk, rate); - spin_unlock_irqrestore(&clock_lock, flags); - - return rounded; - } - - return rate; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -/* - * This is the simple version of Loongson-2 wait, Maybe we need do this in - * interrupt disabled content - */ - -DEFINE_SPINLOCK(loongson2_wait_lock); -void loongson2_cpu_wait(void) -{ - u32 cpu_freq; - unsigned long flags; - - spin_lock_irqsave(&loongson2_wait_lock, flags); - cpu_freq = LOONGSON_CHIPCFG0; - LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ - LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ - spin_unlock_irqrestore(&loongson2_wait_lock, flags); -} -EXPORT_SYMBOL_GPL(loongson2_cpu_wait); - -MODULE_AUTHOR("Yanhua "); -MODULE_DESCRIPTION("cpufreq driver for Loongson 2F"); -MODULE_LICENSE("GPL"); diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c index ae5db206347c..e7c98e2b78b6 100644 --- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c +++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c @@ -19,7 +19,7 @@ #include -#include +#include static uint nowait; @@ -181,6 +181,25 @@ static struct platform_driver platform_driver = { .id_table = platform_device_ids, }; +/* + * This is the simple version of Loongson-2 wait, Maybe we need do this in + * interrupt disabled context. + */ + +static DEFINE_SPINLOCK(loongson2_wait_lock); + +static void loongson2_cpu_wait(void) +{ + unsigned long flags; + u32 cpu_freq; + + spin_lock_irqsave(&loongson2_wait_lock, flags); + cpu_freq = LOONGSON_CHIPCFG0; + LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ + LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ + spin_unlock_irqrestore(&loongson2_wait_lock, flags); +} + static int __init cpufreq_init(void) { int ret; diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index aca93eed8779..263beb9322a8 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -41,6 +41,7 @@ config LEMOTE_MACH2F select CSRC_R4K if ! MIPS_EXTERNAL_TIMER select DMA_NONCOHERENT select GENERIC_ISA_DMA_SUPPORT_BROKEN + select HAVE_CLK select HW_HAS_PCI select I8259 select IRQ_CPU diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index 8699a53f0477..4f9eaa328a16 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -2,7 +2,7 @@ # Makefile for lemote loongson2f family machines # -obj-y += machtype.o irq.o reset.o ec_kb3310b.o +obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o # # Suspend Support diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c new file mode 100644 index 000000000000..bc739d4bab2e --- /dev/null +++ b/arch/mips/loongson/lemote-2f/clock.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Author: Yanhua, yanh@lemote.com + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DEFINE_MUTEX(clock_list_sem); + +/* Minimum CLK support */ +enum { + DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT, + DC_87PT, DC_DISABLE, DC_RESV +}; + +struct cpufreq_frequency_table loongson2_clockmod_table[] = { + {DC_RESV, CPUFREQ_ENTRY_INVALID}, + {DC_ZERO, CPUFREQ_ENTRY_INVALID}, + {DC_25PT, 0}, + {DC_37PT, 0}, + {DC_50PT, 0}, + {DC_62PT, 0}, + {DC_75PT, 0}, + {DC_87PT, 0}, + {DC_DISABLE, 0}, + {DC_RESV, CPUFREQ_TABLE_END}, +}; +EXPORT_SYMBOL_GPL(loongson2_clockmod_table); + +static struct clk cpu_clk = { + .name = "cpu_clk", + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, + .rate = 800000000, +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + return &cpu_clk; +} +EXPORT_SYMBOL(clk_get); + +static void propagate_rate(struct clk *clk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->parent != clk)) + continue; + if (likely(clkp->ops && clkp->ops->recalc)) + clkp->ops->recalc(clkp); + if (unlikely(clkp->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clkp); + } +} + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return (unsigned long)clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + int regval; + int i; + + if (likely(clk->ops && clk->ops->set_rate)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_rate(clk, rate, 0); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + + for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END; + i++) { + if (loongson2_clockmod_table[i].frequency == + CPUFREQ_ENTRY_INVALID) + continue; + if (rate == loongson2_clockmod_table[i].frequency) + break; + } + if (rate != loongson2_clockmod_table[i].frequency) + return -ENOTSUPP; + + clk->rate = rate; + + regval = LOONGSON_CHIPCFG0; + regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1); + LOONGSON_CHIPCFG0 = regval; + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (likely(clk->ops && clk->ops->round_rate)) { + unsigned long flags, rounded; + + spin_lock_irqsave(&clock_lock, flags); + rounded = clk->ops->round_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + + return rounded; + } + + return rate; +} +EXPORT_SYMBOL_GPL(clk_round_rate); -- cgit v1.2.3