| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | #include <linux/sched.h> | 
|---|
| 3 | #include <linux/sched/clock.h> | 
|---|
| 4 |  | 
|---|
| 5 | #include <asm/cpu.h> | 
|---|
| 6 | #include <asm/cpufeature.h> | 
|---|
| 7 | #include <asm/msr.h> | 
|---|
| 8 |  | 
|---|
| 9 | #include "cpu.h" | 
|---|
| 10 |  | 
|---|
| 11 | #define MSR_ZHAOXIN_FCR57 0x00001257 | 
|---|
| 12 |  | 
|---|
| 13 | #define ACE_PRESENT	(1 << 6) | 
|---|
| 14 | #define ACE_ENABLED	(1 << 7) | 
|---|
| 15 | #define ACE_FCR		(1 << 7)	/* MSR_ZHAOXIN_FCR */ | 
|---|
| 16 |  | 
|---|
| 17 | #define RNG_PRESENT	(1 << 2) | 
|---|
| 18 | #define RNG_ENABLED	(1 << 3) | 
|---|
| 19 | #define RNG_ENABLE	(1 << 8)	/* MSR_ZHAOXIN_RNG */ | 
|---|
| 20 |  | 
|---|
| 21 | static void init_zhaoxin_cap(struct cpuinfo_x86 *c) | 
|---|
| 22 | { | 
|---|
| 23 | u32  lo, hi; | 
|---|
| 24 |  | 
|---|
| 25 | /* Test for Extended Feature Flags presence */ | 
|---|
| 26 | if (cpuid_eax(op: 0xC0000000) >= 0xC0000001) { | 
|---|
| 27 | u32 tmp = cpuid_edx(op: 0xC0000001); | 
|---|
| 28 |  | 
|---|
| 29 | /* Enable ACE unit, if present and disabled */ | 
|---|
| 30 | if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) { | 
|---|
| 31 | rdmsr(MSR_ZHAOXIN_FCR57, lo, hi); | 
|---|
| 32 | /* Enable ACE unit */ | 
|---|
| 33 | lo |= ACE_FCR; | 
|---|
| 34 | wrmsr(MSR_ZHAOXIN_FCR57, low: lo, high: hi); | 
|---|
| 35 | pr_info( "CPU: Enabled ACE h/w crypto\n"); | 
|---|
| 36 | } | 
|---|
| 37 |  | 
|---|
| 38 | /* Enable RNG unit, if present and disabled */ | 
|---|
| 39 | if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) { | 
|---|
| 40 | rdmsr(MSR_ZHAOXIN_FCR57, lo, hi); | 
|---|
| 41 | /* Enable RNG unit */ | 
|---|
| 42 | lo |= RNG_ENABLE; | 
|---|
| 43 | wrmsr(MSR_ZHAOXIN_FCR57, low: lo, high: hi); | 
|---|
| 44 | pr_info( "CPU: Enabled h/w RNG\n"); | 
|---|
| 45 | } | 
|---|
| 46 |  | 
|---|
| 47 | /* | 
|---|
| 48 | * Store Extended Feature Flags as word 5 of the CPU | 
|---|
| 49 | * capability bit array | 
|---|
| 50 | */ | 
|---|
| 51 | c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(op: 0xC0000001); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | if (c->x86 >= 0x6) | 
|---|
| 55 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | 
|---|
| 56 | } | 
|---|
| 57 |  | 
|---|
| 58 | static void early_init_zhaoxin(struct cpuinfo_x86 *c) | 
|---|
| 59 | { | 
|---|
| 60 | if (c->x86 >= 0x6) | 
|---|
| 61 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 
|---|
| 62 | #ifdef CONFIG_X86_64 | 
|---|
| 63 | set_cpu_cap(c, X86_FEATURE_SYSENTER32); | 
|---|
| 64 | #endif | 
|---|
| 65 | if (c->x86_power & (1 << 8)) { | 
|---|
| 66 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 
|---|
| 67 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); | 
|---|
| 68 | } | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | static void init_zhaoxin(struct cpuinfo_x86 *c) | 
|---|
| 72 | { | 
|---|
| 73 | early_init_zhaoxin(c); | 
|---|
| 74 | init_intel_cacheinfo(c); | 
|---|
| 75 |  | 
|---|
| 76 | if (c->cpuid_level > 9) { | 
|---|
| 77 | unsigned int eax = cpuid_eax(op: 10); | 
|---|
| 78 |  | 
|---|
| 79 | /* | 
|---|
| 80 | * Check for version and the number of counters | 
|---|
| 81 | * Version(eax[7:0]) can't be 0; | 
|---|
| 82 | * Counters(eax[15:8]) should be greater than 1; | 
|---|
| 83 | */ | 
|---|
| 84 | if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1)) | 
|---|
| 85 | set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | if (c->x86 >= 0x6) | 
|---|
| 89 | init_zhaoxin_cap(c); | 
|---|
| 90 | #ifdef CONFIG_X86_64 | 
|---|
| 91 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | 
|---|
| 92 | #endif | 
|---|
| 93 |  | 
|---|
| 94 | init_ia32_feat_ctl(c); | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | #ifdef CONFIG_X86_32 | 
|---|
| 98 | static unsigned int | 
|---|
| 99 | zhaoxin_size_cache(struct cpuinfo_x86 *c, unsigned int size) | 
|---|
| 100 | { | 
|---|
| 101 | return size; | 
|---|
| 102 | } | 
|---|
| 103 | #endif | 
|---|
| 104 |  | 
|---|
| 105 | static const struct cpu_dev zhaoxin_cpu_dev = { | 
|---|
| 106 | .c_vendor	= "zhaoxin", | 
|---|
| 107 | .c_ident	= { "  Shanghai  "}, | 
|---|
| 108 | .c_early_init	= early_init_zhaoxin, | 
|---|
| 109 | .c_init		= init_zhaoxin, | 
|---|
| 110 | #ifdef CONFIG_X86_32 | 
|---|
| 111 | .legacy_cache_size = zhaoxin_size_cache, | 
|---|
| 112 | #endif | 
|---|
| 113 | .c_x86_vendor	= X86_VENDOR_ZHAOXIN, | 
|---|
| 114 | }; | 
|---|
| 115 |  | 
|---|
| 116 | cpu_dev_register(zhaoxin_cpu_dev); | 
|---|
| 117 |  | 
|---|