diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/include/asm/timex.h | 65 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 1 |
2 files changed, 48 insertions, 18 deletions
diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h index c5424757da65..b05bb70a2e46 100644 --- a/arch/mips/include/asm/timex.h +++ b/arch/mips/include/asm/timex.h | |||
@@ -4,12 +4,16 @@ | |||
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 1998, 1999, 2003 by Ralf Baechle | 6 | * Copyright (C) 1998, 1999, 2003 by Ralf Baechle |
7 | * Copyright (C) 2014 by Maciej W. Rozycki | ||
7 | */ | 8 | */ |
8 | #ifndef _ASM_TIMEX_H | 9 | #ifndef _ASM_TIMEX_H |
9 | #define _ASM_TIMEX_H | 10 | #define _ASM_TIMEX_H |
10 | 11 | ||
11 | #ifdef __KERNEL__ | 12 | #ifdef __KERNEL__ |
12 | 13 | ||
14 | #include <linux/compiler.h> | ||
15 | |||
16 | #include <asm/cpu.h> | ||
13 | #include <asm/cpu-features.h> | 17 | #include <asm/cpu-features.h> |
14 | #include <asm/mipsregs.h> | 18 | #include <asm/mipsregs.h> |
15 | #include <asm/cpu-type.h> | 19 | #include <asm/cpu-type.h> |
@@ -45,29 +49,54 @@ typedef unsigned int cycles_t; | |||
45 | * However for now the implementaton of this function doesn't get these | 49 | * However for now the implementaton of this function doesn't get these |
46 | * fine details right. | 50 | * fine details right. |
47 | */ | 51 | */ |
48 | static inline cycles_t get_cycles(void) | 52 | static inline int can_use_mips_counter(unsigned int prid) |
49 | { | 53 | { |
50 | switch (boot_cpu_type()) { | 54 | int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY; |
51 | case CPU_R4400PC: | ||
52 | case CPU_R4400SC: | ||
53 | case CPU_R4400MC: | ||
54 | if ((read_c0_prid() & 0xff) >= 0x0050) | ||
55 | return read_c0_count(); | ||
56 | break; | ||
57 | 55 | ||
58 | case CPU_R4000PC: | 56 | if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter) |
59 | case CPU_R4000SC: | 57 | return 0; |
60 | case CPU_R4000MC: | 58 | else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) |
61 | break; | 59 | return 1; |
60 | else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp)) | ||
61 | return 1; | ||
62 | /* Make sure we don't peek at cpu_data[0].options in the fast path! */ | ||
63 | if (!__builtin_constant_p(cpu_has_counter)) | ||
64 | asm volatile("" : "=m" (cpu_data[0].options)); | ||
65 | if (likely(cpu_has_counter && | ||
66 | prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0)))) | ||
67 | return 1; | ||
68 | else | ||
69 | return 0; | ||
70 | } | ||
62 | 71 | ||
63 | default: | 72 | static inline cycles_t get_cycles(void) |
64 | if (cpu_has_counter) | 73 | { |
65 | return read_c0_count(); | 74 | if (can_use_mips_counter(read_c0_prid())) |
66 | break; | 75 | return read_c0_count(); |
67 | } | 76 | else |
77 | return 0; /* no usable counter */ | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Like get_cycles - but where c0_count is not available we desperately | ||
82 | * use c0_random in an attempt to get at least a little bit of entropy. | ||
83 | * | ||
84 | * R6000 and R6000A neither have a count register nor a random register. | ||
85 | * That leaves no entropy source in the CPU itself. | ||
86 | */ | ||
87 | static inline unsigned long random_get_entropy(void) | ||
88 | { | ||
89 | unsigned int prid = read_c0_prid(); | ||
90 | unsigned int imp = prid & PRID_IMP_MASK; | ||
68 | 91 | ||
69 | return 0; /* no usable counter */ | 92 | if (can_use_mips_counter(prid)) |
93 | return read_c0_count(); | ||
94 | else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A)) | ||
95 | return read_c0_random(); | ||
96 | else | ||
97 | return 0; /* no usable register */ | ||
70 | } | 98 | } |
99 | #define random_get_entropy random_get_entropy | ||
71 | 100 | ||
72 | #endif /* __KERNEL__ */ | 101 | #endif /* __KERNEL__ */ |
73 | 102 | ||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f34000b27bf1..b1b580d69db0 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -1026,6 +1026,7 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) | |||
1026 | decode_configs(c); | 1026 | decode_configs(c); |
1027 | /* JZRISC does not implement the CP0 counter. */ | 1027 | /* JZRISC does not implement the CP0 counter. */ |
1028 | c->options &= ~MIPS_CPU_COUNTER; | 1028 | c->options &= ~MIPS_CPU_COUNTER; |
1029 | BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter); | ||
1029 | switch (c->processor_id & PRID_IMP_MASK) { | 1030 | switch (c->processor_id & PRID_IMP_MASK) { |
1030 | case PRID_IMP_JZRISC: | 1031 | case PRID_IMP_JZRISC: |
1031 | c->cputype = CPU_JZRISC; | 1032 | c->cputype = CPU_JZRISC; |