|
10 | 10 |
|
11 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
12 | 12 |
|
| 13 | +#include <linux/arm-smccc.h> |
13 | 14 | #include <linux/cpu.h>
|
14 | 15 | #include <linux/module.h>
|
15 | 16 | #include <linux/nvmem-consumer.h>
|
@@ -46,14 +47,77 @@ static u32 sun50i_h6_efuse_xlate(u32 speedbin)
|
46 | 47 | return 0;
|
47 | 48 | }
|
48 | 49 |
|
| 50 | +static int get_soc_id_revision(void) |
| 51 | +{ |
| 52 | +#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY |
| 53 | + return arm_smccc_get_soc_id_revision(); |
| 54 | +#else |
| 55 | + return SMCCC_RET_NOT_SUPPORTED; |
| 56 | +#endif |
| 57 | +} |
| 58 | + |
| 59 | +/* |
| 60 | + * Judging by the OPP tables in the vendor BSP, the quality order of the |
| 61 | + * returned speedbin index is 4 -> 0/2 -> 3 -> 1, from worst to best. |
| 62 | + * 0 and 2 seem identical from the OPP tables' point of view. |
| 63 | + */ |
| 64 | +static u32 sun50i_h616_efuse_xlate(u32 speedbin) |
| 65 | +{ |
| 66 | + int ver_bits = get_soc_id_revision(); |
| 67 | + u32 value = 0; |
| 68 | + |
| 69 | + switch (speedbin & 0xffff) { |
| 70 | + case 0x2000: |
| 71 | + value = 0; |
| 72 | + break; |
| 73 | + case 0x2400: |
| 74 | + case 0x7400: |
| 75 | + case 0x2c00: |
| 76 | + case 0x7c00: |
| 77 | + if (ver_bits != SMCCC_RET_NOT_SUPPORTED && ver_bits <= 1) { |
| 78 | + /* ic version A/B */ |
| 79 | + value = 1; |
| 80 | + } else { |
| 81 | + /* ic version C and later version */ |
| 82 | + value = 2; |
| 83 | + } |
| 84 | + break; |
| 85 | + case 0x5000: |
| 86 | + case 0x5400: |
| 87 | + case 0x6000: |
| 88 | + value = 3; |
| 89 | + break; |
| 90 | + case 0x5c00: |
| 91 | + value = 4; |
| 92 | + break; |
| 93 | + case 0x5d00: |
| 94 | + value = 0; |
| 95 | + break; |
| 96 | + default: |
| 97 | + pr_warn("sun50i-cpufreq-nvmem: unknown speed bin 0x%x, using default bin 0\n", |
| 98 | + speedbin & 0xffff); |
| 99 | + value = 0; |
| 100 | + break; |
| 101 | + } |
| 102 | + |
| 103 | + return value; |
| 104 | +} |
| 105 | + |
49 | 106 | static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
|
50 | 107 | .efuse_xlate = sun50i_h6_efuse_xlate,
|
51 | 108 | };
|
52 | 109 |
|
| 110 | +static struct sunxi_cpufreq_data sun50i_h616_cpufreq_data = { |
| 111 | + .efuse_xlate = sun50i_h616_efuse_xlate, |
| 112 | +}; |
| 113 | + |
53 | 114 | static const struct of_device_id cpu_opp_match_list[] = {
|
54 | 115 | { .compatible = "allwinner,sun50i-h6-operating-points",
|
55 | 116 | .data = &sun50i_h6_cpufreq_data,
|
56 | 117 | },
|
| 118 | + { .compatible = "allwinner,sun50i-h616-operating-points", |
| 119 | + .data = &sun50i_h616_cpufreq_data, |
| 120 | + }, |
57 | 121 | {}
|
58 | 122 | };
|
59 | 123 |
|
@@ -230,6 +294,9 @@ static struct platform_driver sun50i_cpufreq_driver = {
|
230 | 294 |
|
231 | 295 | static const struct of_device_id sun50i_cpufreq_match_list[] = {
|
232 | 296 | { .compatible = "allwinner,sun50i-h6" },
|
| 297 | + { .compatible = "allwinner,sun50i-h616" }, |
| 298 | + { .compatible = "allwinner,sun50i-h618" }, |
| 299 | + { .compatible = "allwinner,sun50i-h700" }, |
233 | 300 | {}
|
234 | 301 | };
|
235 | 302 | MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list);
|
|
0 commit comments