1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2016 Linaro.
4*4882a593Smuzhiyun * Viresh Kumar <viresh.kumar@linaro.org>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/err.h>
8*4882a593Smuzhiyun #include <linux/of.h>
9*4882a593Smuzhiyun #include <linux/of_device.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "cpufreq-dt.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun /*
15*4882a593Smuzhiyun * Machines for which the cpufreq device is *always* created, mostly used for
16*4882a593Smuzhiyun * platforms using "operating-points" (V1) property.
17*4882a593Smuzhiyun */
18*4882a593Smuzhiyun static const struct of_device_id whitelist[] __initconst = {
19*4882a593Smuzhiyun { .compatible = "allwinner,sun4i-a10", },
20*4882a593Smuzhiyun { .compatible = "allwinner,sun5i-a10s", },
21*4882a593Smuzhiyun { .compatible = "allwinner,sun5i-a13", },
22*4882a593Smuzhiyun { .compatible = "allwinner,sun5i-r8", },
23*4882a593Smuzhiyun { .compatible = "allwinner,sun6i-a31", },
24*4882a593Smuzhiyun { .compatible = "allwinner,sun6i-a31s", },
25*4882a593Smuzhiyun { .compatible = "allwinner,sun7i-a20", },
26*4882a593Smuzhiyun { .compatible = "allwinner,sun8i-a23", },
27*4882a593Smuzhiyun { .compatible = "allwinner,sun8i-a83t", },
28*4882a593Smuzhiyun { .compatible = "allwinner,sun8i-h3", },
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun { .compatible = "apm,xgene-shadowcat", },
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun { .compatible = "arm,integrator-ap", },
33*4882a593Smuzhiyun { .compatible = "arm,integrator-cp", },
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun { .compatible = "hisilicon,hi3660", },
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun { .compatible = "fsl,imx27", },
38*4882a593Smuzhiyun { .compatible = "fsl,imx51", },
39*4882a593Smuzhiyun { .compatible = "fsl,imx53", },
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun { .compatible = "marvell,berlin", },
42*4882a593Smuzhiyun { .compatible = "marvell,pxa250", },
43*4882a593Smuzhiyun { .compatible = "marvell,pxa270", },
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun { .compatible = "samsung,exynos3250", },
46*4882a593Smuzhiyun { .compatible = "samsung,exynos4210", },
47*4882a593Smuzhiyun { .compatible = "samsung,exynos5250", },
48*4882a593Smuzhiyun #ifndef CONFIG_BL_SWITCHER
49*4882a593Smuzhiyun { .compatible = "samsung,exynos5800", },
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun { .compatible = "renesas,emev2", },
53*4882a593Smuzhiyun { .compatible = "renesas,r7s72100", },
54*4882a593Smuzhiyun { .compatible = "renesas,r8a73a4", },
55*4882a593Smuzhiyun { .compatible = "renesas,r8a7740", },
56*4882a593Smuzhiyun { .compatible = "renesas,r8a7742", },
57*4882a593Smuzhiyun { .compatible = "renesas,r8a7743", },
58*4882a593Smuzhiyun { .compatible = "renesas,r8a7744", },
59*4882a593Smuzhiyun { .compatible = "renesas,r8a7745", },
60*4882a593Smuzhiyun { .compatible = "renesas,r8a7778", },
61*4882a593Smuzhiyun { .compatible = "renesas,r8a7779", },
62*4882a593Smuzhiyun { .compatible = "renesas,r8a7790", },
63*4882a593Smuzhiyun { .compatible = "renesas,r8a7791", },
64*4882a593Smuzhiyun { .compatible = "renesas,r8a7792", },
65*4882a593Smuzhiyun { .compatible = "renesas,r8a7793", },
66*4882a593Smuzhiyun { .compatible = "renesas,r8a7794", },
67*4882a593Smuzhiyun { .compatible = "renesas,sh73a0", },
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun { .compatible = "st-ericsson,u8500", },
70*4882a593Smuzhiyun { .compatible = "st-ericsson,u8540", },
71*4882a593Smuzhiyun { .compatible = "st-ericsson,u9500", },
72*4882a593Smuzhiyun { .compatible = "st-ericsson,u9540", },
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun { .compatible = "ti,omap2", },
75*4882a593Smuzhiyun { .compatible = "ti,omap4", },
76*4882a593Smuzhiyun { .compatible = "ti,omap5", },
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun { .compatible = "xlnx,zynq-7000", },
79*4882a593Smuzhiyun { .compatible = "xlnx,zynqmp", },
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun { }
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /*
85*4882a593Smuzhiyun * Machines for which the cpufreq device is *not* created, mostly used for
86*4882a593Smuzhiyun * platforms using "operating-points-v2" property.
87*4882a593Smuzhiyun */
88*4882a593Smuzhiyun static const struct of_device_id blacklist[] __initconst = {
89*4882a593Smuzhiyun { .compatible = "allwinner,sun50i-h6", },
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun { .compatible = "arm,vexpress", },
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun { .compatible = "calxeda,highbank", },
94*4882a593Smuzhiyun { .compatible = "calxeda,ecx-2000", },
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun { .compatible = "fsl,imx7ulp", },
97*4882a593Smuzhiyun { .compatible = "fsl,imx7d", },
98*4882a593Smuzhiyun { .compatible = "fsl,imx8mq", },
99*4882a593Smuzhiyun { .compatible = "fsl,imx8mm", },
100*4882a593Smuzhiyun { .compatible = "fsl,imx8mn", },
101*4882a593Smuzhiyun { .compatible = "fsl,imx8mp", },
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun { .compatible = "marvell,armadaxp", },
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun { .compatible = "mediatek,mt2701", },
106*4882a593Smuzhiyun { .compatible = "mediatek,mt2712", },
107*4882a593Smuzhiyun { .compatible = "mediatek,mt7622", },
108*4882a593Smuzhiyun { .compatible = "mediatek,mt7623", },
109*4882a593Smuzhiyun { .compatible = "mediatek,mt817x", },
110*4882a593Smuzhiyun { .compatible = "mediatek,mt8173", },
111*4882a593Smuzhiyun { .compatible = "mediatek,mt8176", },
112*4882a593Smuzhiyun { .compatible = "mediatek,mt8183", },
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun { .compatible = "nvidia,tegra20", },
115*4882a593Smuzhiyun { .compatible = "nvidia,tegra30", },
116*4882a593Smuzhiyun { .compatible = "nvidia,tegra124", },
117*4882a593Smuzhiyun { .compatible = "nvidia,tegra210", },
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun { .compatible = "qcom,apq8096", },
120*4882a593Smuzhiyun { .compatible = "qcom,msm8996", },
121*4882a593Smuzhiyun { .compatible = "qcom,qcs404", },
122*4882a593Smuzhiyun { .compatible = "qcom,sc7180", },
123*4882a593Smuzhiyun { .compatible = "qcom,sdm845", },
124*4882a593Smuzhiyun { .compatible = "qcom,sm8150", },
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun { .compatible = "rockchip,px30", },
127*4882a593Smuzhiyun { .compatible = "rockchip,rk2928", },
128*4882a593Smuzhiyun { .compatible = "rockchip,rk3036", },
129*4882a593Smuzhiyun { .compatible = "rockchip,rk3066a", },
130*4882a593Smuzhiyun { .compatible = "rockchip,rk3066b", },
131*4882a593Smuzhiyun { .compatible = "rockchip,rk3126", },
132*4882a593Smuzhiyun { .compatible = "rockchip,rk3128", },
133*4882a593Smuzhiyun { .compatible = "rockchip,rk3188", },
134*4882a593Smuzhiyun { .compatible = "rockchip,rk3228", },
135*4882a593Smuzhiyun { .compatible = "rockchip,rk3229", },
136*4882a593Smuzhiyun { .compatible = "rockchip,rk3288", },
137*4882a593Smuzhiyun { .compatible = "rockchip,rk3288w", },
138*4882a593Smuzhiyun { .compatible = "rockchip,rk3308", },
139*4882a593Smuzhiyun { .compatible = "rockchip,rk3326", },
140*4882a593Smuzhiyun { .compatible = "rockchip,rk3328", },
141*4882a593Smuzhiyun { .compatible = "rockchip,rk3366", },
142*4882a593Smuzhiyun { .compatible = "rockchip,rk3368", },
143*4882a593Smuzhiyun { .compatible = "rockchip,rk3399", },
144*4882a593Smuzhiyun { .compatible = "rockchip,rk3399pro", },
145*4882a593Smuzhiyun { .compatible = "rockchip,rk3528", },
146*4882a593Smuzhiyun { .compatible = "rockchip,rk3562", },
147*4882a593Smuzhiyun { .compatible = "rockchip,rk3566", },
148*4882a593Smuzhiyun { .compatible = "rockchip,rk3568", },
149*4882a593Smuzhiyun { .compatible = "rockchip,rk3588", },
150*4882a593Smuzhiyun { .compatible = "rockchip,rv1103", },
151*4882a593Smuzhiyun { .compatible = "rockchip,rv1106", },
152*4882a593Smuzhiyun { .compatible = "rockchip,rv1109", },
153*4882a593Smuzhiyun { .compatible = "rockchip,rv1126", },
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun { .compatible = "st,stih407", },
156*4882a593Smuzhiyun { .compatible = "st,stih410", },
157*4882a593Smuzhiyun { .compatible = "st,stih418", },
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun { .compatible = "sigma,tango4", },
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun { .compatible = "ti,am33xx", },
162*4882a593Smuzhiyun { .compatible = "ti,am43", },
163*4882a593Smuzhiyun { .compatible = "ti,dra7", },
164*4882a593Smuzhiyun { .compatible = "ti,omap3", },
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun { .compatible = "qcom,ipq8064", },
167*4882a593Smuzhiyun { .compatible = "qcom,apq8064", },
168*4882a593Smuzhiyun { .compatible = "qcom,msm8974", },
169*4882a593Smuzhiyun { .compatible = "qcom,msm8960", },
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun { }
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun
cpu0_node_has_opp_v2_prop(void)174*4882a593Smuzhiyun static bool __init cpu0_node_has_opp_v2_prop(void)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun struct device_node *np = of_cpu_device_node_get(0);
177*4882a593Smuzhiyun bool ret = false;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (of_get_property(np, "operating-points-v2", NULL))
180*4882a593Smuzhiyun ret = true;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun of_node_put(np);
183*4882a593Smuzhiyun return ret;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
cpufreq_dt_platdev_init(void)186*4882a593Smuzhiyun static int __init cpufreq_dt_platdev_init(void)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun struct device_node *np = of_find_node_by_path("/");
189*4882a593Smuzhiyun const struct of_device_id *match;
190*4882a593Smuzhiyun const void *data = NULL;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (!np)
193*4882a593Smuzhiyun return -ENODEV;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun match = of_match_node(whitelist, np);
196*4882a593Smuzhiyun if (match) {
197*4882a593Smuzhiyun data = match->data;
198*4882a593Smuzhiyun goto create_pdev;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (cpu0_node_has_opp_v2_prop() && !of_match_node(blacklist, np))
202*4882a593Smuzhiyun goto create_pdev;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun of_node_put(np);
205*4882a593Smuzhiyun return -ENODEV;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun create_pdev:
208*4882a593Smuzhiyun of_node_put(np);
209*4882a593Smuzhiyun return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq-dt",
210*4882a593Smuzhiyun -1, data,
211*4882a593Smuzhiyun sizeof(struct cpufreq_dt_platform_data)));
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun core_initcall(cpufreq_dt_platdev_init);
214