Commit 7507445b authored by Huacai Chen's avatar Huacai Chen Committed by Paul Burton

MIPS: Loongson: Add Loongson-3A R4 basic support

All Loongson-3 CPU family:

Code-name         Brand-name       PRId
Loongson-3A R1    Loongson-3A1000  0x6305
Loongson-3A R2    Loongson-3A2000  0x6308
Loongson-3A R2.1  Loongson-3A2000  0x630c
Loongson-3A R3    Loongson-3A3000  0x6309
Loongson-3A R3.1  Loongson-3A3000  0x630d
Loongson-3A R4    Loongson-3A4000  0xc000
Loongson-3B R1    Loongson-3B1000  0x6306
Loongson-3B R2    Loongson-3B1500  0x6307

Features of R4 revision of Loongson-3A:

  - All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
  - Support variable ASID bits.
  - Support MSA and VZ extensions.
  - Support CPUCFG (CPU config) and CSR (Control and Status Register)
      extensions.
  - 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
      set-associative).

Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: default avatarHuacai Chen <chenhc@lemote.com>
Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
parent 6a6f9b7d
...@@ -1387,9 +1387,11 @@ config CPU_LOONGSON3 ...@@ -1387,9 +1387,11 @@ config CPU_LOONGSON3
select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES select CPU_SUPPORTS_HUGEPAGES
select CPU_SUPPORTS_MSA
select CPU_HAS_LOAD_STORE_LR select CPU_HAS_LOAD_STORE_LR
select WEAK_ORDERING select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC select WEAK_REORDERING_BEYOND_LLSC
select MIPS_ASID_BITS_VARIABLE
select MIPS_PGD_C0_CONTEXT select MIPS_PGD_C0_CONTEXT
select MIPS_L1_CACHE_SHIFT_6 select MIPS_L1_CACHE_SHIFT_6
select GPIOLIB select GPIOLIB
......
...@@ -91,7 +91,9 @@ ...@@ -91,7 +91,9 @@
#define PRID_IMP_LOONGSON_32 0x4200 /* Loongson-1 */ #define PRID_IMP_LOONGSON_32 0x4200 /* Loongson-1 */
#define PRID_IMP_R5432 0x5400 #define PRID_IMP_R5432 0x5400
#define PRID_IMP_R5500 0x5500 #define PRID_IMP_R5500 0x5500
#define PRID_IMP_LOONGSON_64 0x6300 /* Loongson-2/3 */ #define PRID_IMP_LOONGSON_64R 0x6100 /* Reduced Loongson-2 */
#define PRID_IMP_LOONGSON_64C 0x6300 /* Classic Loongson-2 and Loongson-3 */
#define PRID_IMP_LOONGSON_64G 0xc000 /* Generic Loongson-2 and Loongson-3 */
#define PRID_IMP_UNKNOWN 0xff00 #define PRID_IMP_UNKNOWN 0xff00
......
...@@ -30,13 +30,21 @@ ...@@ -30,13 +30,21 @@
mtc0 t0, CP0_PAGEGRAIN mtc0 t0, CP0_PAGEGRAIN
/* Enable STFill Buffer */ /* Enable STFill Buffer */
mfc0 t0, CP0_PRID mfc0 t0, CP0_PRID
/* Loongson-3A R4+ */
andi t1, t0, PRID_IMP_MASK
li t2, PRID_IMP_LOONGSON_64G
beq t1, t2, 1f
nop
/* Loongson-3A R2/R3 */
andi t0, (PRID_IMP_MASK | PRID_REV_MASK) andi t0, (PRID_IMP_MASK | PRID_REV_MASK)
slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0) slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
bnez t0, 1f bnez t0, 2f
nop
1:
mfc0 t0, CP0_CONFIG6 mfc0 t0, CP0_CONFIG6
or t0, 0x100 or t0, 0x100
mtc0 t0, CP0_CONFIG6 mtc0 t0, CP0_CONFIG6
1: 2:
_ehb _ehb
.set pop .set pop
#endif #endif
...@@ -59,13 +67,21 @@ ...@@ -59,13 +67,21 @@
mtc0 t0, CP0_PAGEGRAIN mtc0 t0, CP0_PAGEGRAIN
/* Enable STFill Buffer */ /* Enable STFill Buffer */
mfc0 t0, CP0_PRID mfc0 t0, CP0_PRID
/* Loongson-3A R4+ */
andi t1, t0, PRID_IMP_MASK
li t2, PRID_IMP_LOONGSON_64G
beq t1, t2, 1f
nop
/* Loongson-3A R2/R3 */
andi t0, (PRID_IMP_MASK | PRID_REV_MASK) andi t0, (PRID_IMP_MASK | PRID_REV_MASK)
slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0) slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
bnez t0, 1f bnez t0, 2f
nop
1:
mfc0 t0, CP0_CONFIG6 mfc0 t0, CP0_CONFIG6
or t0, 0x100 or t0, 0x100
mtc0 t0, CP0_CONFIG6 mtc0 t0, CP0_CONFIG6
1: 2:
_ehb _ehb
.set pop .set pop
#endif #endif
......
...@@ -1526,7 +1526,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -1526,7 +1526,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST; MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
c->tlbsize = 64; c->tlbsize = 64;
break; break;
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ case PRID_IMP_LOONGSON_64C: /* Loongson-2/3 */
switch (c->processor_id & PRID_REV_MASK) { switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON2E: case PRID_REV_LOONGSON2E:
c->cputype = CPU_LOONGSON2; c->cputype = CPU_LOONGSON2;
...@@ -1565,6 +1565,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -1565,6 +1565,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_FPU | MIPS_CPU_LLSC | MIPS_CPU_FPU | MIPS_CPU_LLSC |
MIPS_CPU_32FPR; MIPS_CPU_32FPR;
c->tlbsize = 64; c->tlbsize = 64;
set_cpu_asid_mask(c, MIPS_ENTRYHI_ASID);
c->writecombine = _CACHE_UNCACHED_ACCELERATED; c->writecombine = _CACHE_UNCACHED_ACCELERATED;
break; break;
case PRID_IMP_LOONGSON_32: /* Loongson-1 */ case PRID_IMP_LOONGSON_32: /* Loongson-1 */
...@@ -1903,7 +1904,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -1903,7 +1904,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
{ {
switch (c->processor_id & PRID_IMP_MASK) { switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ case PRID_IMP_LOONGSON_64C: /* Loongson-2/3 */
switch (c->processor_id & PRID_REV_MASK) { switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON3A_R2_0: case PRID_REV_LOONGSON3A_R2_0:
case PRID_REV_LOONGSON3A_R2_1: case PRID_REV_LOONGSON3A_R2_1:
...@@ -1921,6 +1922,17 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -1921,6 +1922,17 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
break; break;
} }
decode_configs(c);
c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
break;
case PRID_IMP_LOONGSON_64G:
c->cputype = CPU_LOONGSON3;
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3a");
set_isa(c, MIPS_CPU_ISA_M64R2);
decode_configs(c); decode_configs(c);
c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
c->writecombine = _CACHE_UNCACHED_ACCELERATED; c->writecombine = _CACHE_UNCACHED_ACCELERATED;
......
...@@ -179,7 +179,8 @@ void __init check_wait(void) ...@@ -179,7 +179,8 @@ void __init check_wait(void)
cpu_wait = r4k_wait; cpu_wait = r4k_wait;
break; break;
case CPU_LOONGSON3: case CPU_LOONGSON3:
if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0) if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
cpu_wait = r4k_wait; cpu_wait = r4k_wait;
break; break;
......
...@@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu) ...@@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu)
* flush all L1 entries at first. Then, another core (usually Core 0) can * flush all L1 entries at first. Then, another core (usually Core 0) can
* safely disable the clock of the target core. loongson3_play_dead() is * safely disable the clock of the target core. loongson3_play_dead() is
* called via CKSEG1 (uncached and unmmaped) */ * called via CKSEG1 (uncached and unmmaped) */
static void loongson3a_r1_play_dead(int *state_addr) static void loongson3_type1_play_dead(int *state_addr)
{ {
register int val; register int val;
register long cpuid, core, node, count; register long cpuid, core, node, count;
...@@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr) ...@@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr)
: "a1"); : "a1");
} }
static void loongson3a_r2r3_play_dead(int *state_addr) static void loongson3_type2_play_dead(int *state_addr)
{ {
register int val; register int val;
register long cpuid, core, node, count; register long cpuid, core, node, count;
...@@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr) ...@@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
" cache 1, 3(%[addr]) \n" " cache 1, 3(%[addr]) \n"
" addiu %[sets], %[sets], -1 \n" " addiu %[sets], %[sets], -1 \n"
" bnez %[sets], 1b \n" " bnez %[sets], 1b \n"
" addiu %[addr], %[addr], 0x40 \n" " addiu %[addr], %[addr], 0x20 \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */
" cache 2, 1(%[addr]) \n"
" cache 2, 2(%[addr]) \n"
" cache 2, 3(%[addr]) \n"
" cache 2, 4(%[addr]) \n"
" cache 2, 5(%[addr]) \n"
" cache 2, 6(%[addr]) \n"
" cache 2, 7(%[addr]) \n"
" cache 2, 8(%[addr]) \n"
" cache 2, 9(%[addr]) \n"
" cache 2, 10(%[addr]) \n"
" cache 2, 11(%[addr]) \n"
" cache 2, 12(%[addr]) \n"
" cache 2, 13(%[addr]) \n"
" cache 2, 14(%[addr]) \n"
" cache 2, 15(%[addr]) \n"
" addiu %[vsets], %[vsets], -1 \n"
" bnez %[vsets], 2b \n"
" addiu %[addr], %[addr], 0x40 \n"
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n" " sw %[val], (%[state_addr]) \n"
" sync \n" " sync \n"
...@@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr) ...@@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
" .set pop \n" " .set pop \n"
: [addr] "=&r" (addr), [val] "=&r" (val) : [addr] "=&r" (addr), [val] "=&r" (val)
: [state_addr] "r" (state_addr), : [state_addr] "r" (state_addr),
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets), [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
[vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
__asm__ __volatile__( __asm__ __volatile__(
" .set push \n" " .set push \n"
...@@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr) ...@@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
" andi %[node], %[cpuid], 0xc \n" " andi %[node], %[cpuid], 0xc \n"
" dsll %[node], 42 \n" /* get node id */ " dsll %[node], 42 \n" /* get node id */
" or %[base], %[base], %[node] \n" " or %[base], %[base], %[node] \n"
" dsrl %[node], 30 \n" /* 15:14 */
" or %[base], %[base], %[node] \n"
"1: li %[count], 0x100 \n" /* wait for init loop */ "1: li %[count], 0x100 \n" /* wait for init loop */
"2: bnez %[count], 2b \n" /* limit mailbox access */ "2: bnez %[count], 2b \n" /* limit mailbox access */
" addiu %[count], -1 \n" " addiu %[count], -1 \n"
...@@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr) ...@@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
: "a1"); : "a1");
} }
static void loongson3b_play_dead(int *state_addr) static void loongson3_type3_play_dead(int *state_addr)
{ {
register int val; register int val;
register long cpuid, core, node, count; register long cpuid, core, node, count;
...@@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr) ...@@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr)
" cache 1, 3(%[addr]) \n" " cache 1, 3(%[addr]) \n"
" addiu %[sets], %[sets], -1 \n" " addiu %[sets], %[sets], -1 \n"
" bnez %[sets], 1b \n" " bnez %[sets], 1b \n"
" addiu %[addr], %[addr], 0x20 \n" " addiu %[addr], %[addr], 0x40 \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */
" cache 2, 1(%[addr]) \n"
" cache 2, 2(%[addr]) \n"
" cache 2, 3(%[addr]) \n"
" cache 2, 4(%[addr]) \n"
" cache 2, 5(%[addr]) \n"
" cache 2, 6(%[addr]) \n"
" cache 2, 7(%[addr]) \n"
" cache 2, 8(%[addr]) \n"
" cache 2, 9(%[addr]) \n"
" cache 2, 10(%[addr]) \n"
" cache 2, 11(%[addr]) \n"
" cache 2, 12(%[addr]) \n"
" cache 2, 13(%[addr]) \n"
" cache 2, 14(%[addr]) \n"
" cache 2, 15(%[addr]) \n"
" addiu %[vsets], %[vsets], -1 \n"
" bnez %[vsets], 2b \n"
" addiu %[addr], %[addr], 0x40 \n"
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n" " sw %[val], (%[state_addr]) \n"
" sync \n" " sync \n"
...@@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr) ...@@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr)
" .set pop \n" " .set pop \n"
: [addr] "=&r" (addr), [val] "=&r" (val) : [addr] "=&r" (addr), [val] "=&r" (val)
: [state_addr] "r" (state_addr), : [state_addr] "r" (state_addr),
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets)); [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
[vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
__asm__ __volatile__( __asm__ __volatile__(
" .set push \n" " .set push \n"
...@@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr) ...@@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr)
" andi %[node], %[cpuid], 0xc \n" " andi %[node], %[cpuid], 0xc \n"
" dsll %[node], 42 \n" /* get node id */ " dsll %[node], 42 \n" /* get node id */
" or %[base], %[base], %[node] \n" " or %[base], %[base], %[node] \n"
" dsrl %[node], 30 \n" /* 15:14 */
" or %[base], %[base], %[node] \n"
"1: li %[count], 0x100 \n" /* wait for init loop */ "1: li %[count], 0x100 \n" /* wait for init loop */
"2: bnez %[count], 2b \n" /* limit mailbox access */ "2: bnez %[count], 2b \n" /* limit mailbox access */
" addiu %[count], -1 \n" " addiu %[count], -1 \n"
...@@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr) ...@@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr)
void play_dead(void) void play_dead(void)
{ {
int *state_addr; int prid_imp, prid_rev, *state_addr;
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
void (*play_dead_at_ckseg1)(int *); void (*play_dead_at_ckseg1)(int *);
idle_task_exit(); idle_task_exit();
switch (read_c0_prid() & PRID_REV_MASK) {
prid_imp = read_c0_prid() & PRID_IMP_MASK;
prid_rev = read_c0_prid() & PRID_REV_MASK;
if (prid_imp == PRID_IMP_LOONGSON_64G) {
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
goto out;
}
switch (prid_rev) {
case PRID_REV_LOONGSON3A_R1: case PRID_REV_LOONGSON3A_R1:
default: default:
play_dead_at_ckseg1 = play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead); (void *)CKSEG1ADDR((unsigned long)loongson3_type1_play_dead);
break;
case PRID_REV_LOONGSON3B_R1:
case PRID_REV_LOONGSON3B_R2:
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3_type2_play_dead);
break; break;
case PRID_REV_LOONGSON3A_R2_0: case PRID_REV_LOONGSON3A_R2_0:
case PRID_REV_LOONGSON3A_R2_1: case PRID_REV_LOONGSON3A_R2_1:
case PRID_REV_LOONGSON3A_R3_0: case PRID_REV_LOONGSON3A_R3_0:
case PRID_REV_LOONGSON3A_R3_1: case PRID_REV_LOONGSON3A_R3_1:
play_dead_at_ckseg1 = play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead); (void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
break;
case PRID_REV_LOONGSON3B_R1:
case PRID_REV_LOONGSON3B_R2:
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
break; break;
} }
out:
state_addr = &per_cpu(cpu_state, cpu); state_addr = &per_cpu(cpu_state, cpu);
mb(); mb();
play_dead_at_ckseg1(state_addr); play_dead_at_ckseg1(state_addr);
......
...@@ -1267,7 +1267,8 @@ static void probe_pcache(void) ...@@ -1267,7 +1267,8 @@ static void probe_pcache(void)
c->dcache.ways * c->dcache.ways *
c->dcache.linesz; c->dcache.linesz;
c->dcache.waybit = 0; c->dcache.waybit = 0;
if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0) if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
c->options |= MIPS_CPU_PREFETCH; c->options |= MIPS_CPU_PREFETCH;
break; break;
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include <loongson.h> #include <loongson.h>
#include <boot_param.h> #include <boot_param.h>
#include <loongson_hwmon.h> #include <loongson_hwmon.h>
#include <loongson_regs.h>
static int csr_temp_enable = 0;
/* /*
* Loongson-3 series cpu has two sensors inside, * Loongson-3 series cpu has two sensors inside,
...@@ -20,8 +23,14 @@ int loongson3_cpu_temp(int cpu) ...@@ -20,8 +23,14 @@ int loongson3_cpu_temp(int cpu)
{ {
u32 reg, prid_rev; u32 reg, prid_rev;
if (csr_temp_enable) {
reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
goto out;
}
reg = LOONGSON_CHIPTEMP(cpu); reg = LOONGSON_CHIPTEMP(cpu);
prid_rev = read_c0_prid() & PRID_REV_MASK; prid_rev = read_c0_prid() & PRID_REV_MASK;
switch (prid_rev) { switch (prid_rev) {
case PRID_REV_LOONGSON3A_R1: case PRID_REV_LOONGSON3A_R1:
reg = (reg >> 8) & 0xff; reg = (reg >> 8) & 0xff;
...@@ -34,9 +43,12 @@ int loongson3_cpu_temp(int cpu) ...@@ -34,9 +43,12 @@ int loongson3_cpu_temp(int cpu)
break; break;
case PRID_REV_LOONGSON3A_R3_0: case PRID_REV_LOONGSON3A_R3_0:
case PRID_REV_LOONGSON3A_R3_1: case PRID_REV_LOONGSON3A_R3_1:
default:
reg = (reg & 0xffff)*731/0x4000 - 273; reg = (reg & 0xffff)*731/0x4000 - 273;
break; break;
} }
out:
return (int)reg * 1000; return (int)reg * 1000;
} }
...@@ -159,6 +171,9 @@ static int __init loongson_hwmon_init(void) ...@@ -159,6 +171,9 @@ static int __init loongson_hwmon_init(void)
pr_info("Loongson Hwmon Enter...\n"); pr_info("Loongson Hwmon Enter...\n");
if (cpu_has_csr())
csr_temp_enable = csr_readl(LOONGSON_CSR_FEATURES) & LOONGSON_CSRF_TEMP;
cpu_hwmon_dev = hwmon_device_register(NULL); cpu_hwmon_dev = hwmon_device_register(NULL);
if (IS_ERR(cpu_hwmon_dev)) { if (IS_ERR(cpu_hwmon_dev)) {
ret = -ENOMEM; ret = -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment