GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / cpufreq / ti-cpufreq.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * TI CPUFreq/OPP hw-supported driver
4  *
5  * Copyright (C) 2016-2017 Texas Instruments, Inc.
6  *       Dave Gerlach <d-gerlach@ti.com>
7  */
8
9 #include <linux/cpu.h>
10 #include <linux/io.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/of.h>
15 #include <linux/of_platform.h>
16 #include <linux/pm_opp.h>
17 #include <linux/regmap.h>
18 #include <linux/slab.h>
19
20 #define REVISION_MASK                           0xF
21 #define REVISION_SHIFT                          28
22
23 #define AM33XX_800M_ARM_MPU_MAX_FREQ            0x1E2F
24 #define AM43XX_600M_ARM_MPU_MAX_FREQ            0xFFA
25
26 #define DRA7_EFUSE_HAS_OD_MPU_OPP               11
27 #define DRA7_EFUSE_HAS_HIGH_MPU_OPP             15
28 #define DRA76_EFUSE_HAS_PLUS_MPU_OPP            18
29 #define DRA7_EFUSE_HAS_ALL_MPU_OPP              23
30 #define DRA76_EFUSE_HAS_ALL_MPU_OPP             24
31
32 #define DRA7_EFUSE_NOM_MPU_OPP                  BIT(0)
33 #define DRA7_EFUSE_OD_MPU_OPP                   BIT(1)
34 #define DRA7_EFUSE_HIGH_MPU_OPP                 BIT(2)
35 #define DRA76_EFUSE_PLUS_MPU_OPP                BIT(3)
36
37 #define OMAP3_CONTROL_DEVICE_STATUS             0x4800244C
38 #define OMAP3_CONTROL_IDCODE                    0x4830A204
39 #define OMAP34xx_ProdID_SKUID                   0x4830A20C
40 #define OMAP3_SYSCON_BASE       (0x48000000 + 0x2000 + 0x270)
41
42 #define VERSION_COUNT                           2
43
44 struct ti_cpufreq_data;
45
46 struct ti_cpufreq_soc_data {
47         const char * const *reg_names;
48         unsigned long (*efuse_xlate)(struct ti_cpufreq_data *opp_data,
49                                      unsigned long efuse);
50         unsigned long efuse_fallback;
51         unsigned long efuse_offset;
52         unsigned long efuse_mask;
53         unsigned long efuse_shift;
54         unsigned long rev_offset;
55         bool multi_regulator;
56 };
57
58 struct ti_cpufreq_data {
59         struct device *cpu_dev;
60         struct device_node *opp_node;
61         struct regmap *syscon;
62         const struct ti_cpufreq_soc_data *soc_data;
63         struct opp_table *opp_table;
64 };
65
66 static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
67                                       unsigned long efuse)
68 {
69         if (!efuse)
70                 efuse = opp_data->soc_data->efuse_fallback;
71         /* AM335x and AM437x use "OPP disable" bits, so invert */
72         return ~efuse;
73 }
74
75 static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data,
76                                       unsigned long efuse)
77 {
78         unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
79
80         /*
81          * The efuse on dra7 and am57 parts contains a specific
82          * value indicating the highest available OPP.
83          */
84
85         switch (efuse) {
86         case DRA76_EFUSE_HAS_PLUS_MPU_OPP:
87         case DRA76_EFUSE_HAS_ALL_MPU_OPP:
88                 calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP;
89                 fallthrough;
90         case DRA7_EFUSE_HAS_ALL_MPU_OPP:
91         case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
92                 calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
93                 fallthrough;
94         case DRA7_EFUSE_HAS_OD_MPU_OPP:
95                 calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
96         }
97
98         return calculated_efuse;
99 }
100
101 static unsigned long omap3_efuse_xlate(struct ti_cpufreq_data *opp_data,
102                                       unsigned long efuse)
103 {
104         /* OPP enable bit ("Speed Binned") */
105         return BIT(efuse);
106 }
107
108 static struct ti_cpufreq_soc_data am3x_soc_data = {
109         .efuse_xlate = amx3_efuse_xlate,
110         .efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
111         .efuse_offset = 0x07fc,
112         .efuse_mask = 0x1fff,
113         .rev_offset = 0x600,
114         .multi_regulator = false,
115 };
116
117 static struct ti_cpufreq_soc_data am4x_soc_data = {
118         .efuse_xlate = amx3_efuse_xlate,
119         .efuse_fallback = AM43XX_600M_ARM_MPU_MAX_FREQ,
120         .efuse_offset = 0x0610,
121         .efuse_mask = 0x3f,
122         .rev_offset = 0x600,
123         .multi_regulator = false,
124 };
125
126 static struct ti_cpufreq_soc_data dra7_soc_data = {
127         .efuse_xlate = dra7_efuse_xlate,
128         .efuse_offset = 0x020c,
129         .efuse_mask = 0xf80000,
130         .efuse_shift = 19,
131         .rev_offset = 0x204,
132         .multi_regulator = true,
133 };
134
135 /*
136  * OMAP35x TRM (SPRUF98K):
137  *  CONTROL_IDCODE (0x4830 A204) describes Silicon revisions.
138  *  Control OMAP Status Register 15:0 (Address 0x4800 244C)
139  *    to separate between omap3503, omap3515, omap3525, omap3530
140  *    and feature presence.
141  *    There are encodings for versions limited to 400/266MHz
142  *    but we ignore.
143  *    Not clear if this also holds for omap34xx.
144  *  some eFuse values e.g. CONTROL_FUSE_OPP1_VDD1
145  *    are stored in the SYSCON register range
146  *  Register 0x4830A20C [ProdID.SKUID] [0:3]
147  *    0x0 for normal 600/430MHz device.
148  *    0x8 for 720/520MHz device.
149  *    Not clear what omap34xx value is.
150  */
151
152 static struct ti_cpufreq_soc_data omap34xx_soc_data = {
153         .efuse_xlate = omap3_efuse_xlate,
154         .efuse_offset = OMAP34xx_ProdID_SKUID - OMAP3_SYSCON_BASE,
155         .efuse_shift = 3,
156         .efuse_mask = BIT(3),
157         .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
158         .multi_regulator = false,
159 };
160
161 /*
162  * AM/DM37x TRM (SPRUGN4M)
163  *  CONTROL_IDCODE (0x4830 A204) describes Silicon revisions.
164  *  Control Device Status Register 15:0 (Address 0x4800 244C)
165  *    to separate between am3703, am3715, dm3725, dm3730
166  *    and feature presence.
167  *   Speed Binned = Bit 9
168  *     0 800/600 MHz
169  *     1 1000/800 MHz
170  *  some eFuse values e.g. CONTROL_FUSE_OPP 1G_VDD1
171  *    are stored in the SYSCON register range.
172  *  There is no 0x4830A20C [ProdID.SKUID] register (exists but
173  *    seems to always read as 0).
174  */
175
176 static const char * const omap3_reg_names[] = {"cpu0", "vbb"};
177
178 static struct ti_cpufreq_soc_data omap36xx_soc_data = {
179         .reg_names = omap3_reg_names,
180         .efuse_xlate = omap3_efuse_xlate,
181         .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE,
182         .efuse_shift = 9,
183         .efuse_mask = BIT(9),
184         .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
185         .multi_regulator = true,
186 };
187
188 /*
189  * AM3517 is quite similar to AM/DM37x except that it has no
190  * high speed grade eFuse and no abb ldo
191  */
192
193 static struct ti_cpufreq_soc_data am3517_soc_data = {
194         .efuse_xlate = omap3_efuse_xlate,
195         .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE,
196         .efuse_shift = 0,
197         .efuse_mask = 0,
198         .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
199         .multi_regulator = false,
200 };
201
202
203 /**
204  * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
205  * @opp_data: pointer to ti_cpufreq_data context
206  * @efuse_value: Set to the value parsed from efuse
207  *
208  * Returns error code if efuse not read properly.
209  */
210 static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data,
211                                 u32 *efuse_value)
212 {
213         struct device *dev = opp_data->cpu_dev;
214         u32 efuse;
215         int ret;
216
217         ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset,
218                           &efuse);
219         if (ret == -EIO) {
220                 /* not a syscon register! */
221                 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
222                                 opp_data->soc_data->efuse_offset, 4);
223
224                 if (!regs)
225                         return -ENOMEM;
226                 efuse = readl(regs);
227                 iounmap(regs);
228                 }
229         else if (ret) {
230                 dev_err(dev,
231                         "Failed to read the efuse value from syscon: %d\n",
232                         ret);
233                 return ret;
234         }
235
236         efuse = (efuse & opp_data->soc_data->efuse_mask);
237         efuse >>= opp_data->soc_data->efuse_shift;
238
239         *efuse_value = opp_data->soc_data->efuse_xlate(opp_data, efuse);
240
241         return 0;
242 }
243
244 /**
245  * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
246  * @opp_data: pointer to ti_cpufreq_data context
247  * @revision_value: Set to the value parsed from revision register
248  *
249  * Returns error code if revision not read properly.
250  */
251 static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
252                               u32 *revision_value)
253 {
254         struct device *dev = opp_data->cpu_dev;
255         u32 revision;
256         int ret;
257
258         ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset,
259                           &revision);
260         if (ret == -EIO) {
261                 /* not a syscon register! */
262                 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
263                                 opp_data->soc_data->rev_offset, 4);
264
265                 if (!regs)
266                         return -ENOMEM;
267                 revision = readl(regs);
268                 iounmap(regs);
269                 }
270         else if (ret) {
271                 dev_err(dev,
272                         "Failed to read the revision number from syscon: %d\n",
273                         ret);
274                 return ret;
275         }
276
277         *revision_value = BIT((revision >> REVISION_SHIFT) & REVISION_MASK);
278
279         return 0;
280 }
281
282 static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data)
283 {
284         struct device *dev = opp_data->cpu_dev;
285         struct device_node *np = opp_data->opp_node;
286
287         opp_data->syscon = syscon_regmap_lookup_by_phandle(np,
288                                                         "syscon");
289         if (IS_ERR(opp_data->syscon)) {
290                 dev_err(dev,
291                         "\"syscon\" is missing, cannot use OPPv2 table.\n");
292                 return PTR_ERR(opp_data->syscon);
293         }
294
295         return 0;
296 }
297
298 static const struct of_device_id ti_cpufreq_of_match[] = {
299         { .compatible = "ti,am33xx", .data = &am3x_soc_data, },
300         { .compatible = "ti,am3517", .data = &am3517_soc_data, },
301         { .compatible = "ti,am43", .data = &am4x_soc_data, },
302         { .compatible = "ti,dra7", .data = &dra7_soc_data },
303         { .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, },
304         { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
305         /* legacy */
306         { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
307         { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
308         {},
309 };
310
311 static const struct of_device_id *ti_cpufreq_match_node(void)
312 {
313         struct device_node *np;
314         const struct of_device_id *match;
315
316         np = of_find_node_by_path("/");
317         match = of_match_node(ti_cpufreq_of_match, np);
318         of_node_put(np);
319
320         return match;
321 }
322
323 static int ti_cpufreq_probe(struct platform_device *pdev)
324 {
325         u32 version[VERSION_COUNT];
326         const struct of_device_id *match;
327         struct opp_table *ti_opp_table;
328         struct ti_cpufreq_data *opp_data;
329         const char * const default_reg_names[] = {"vdd", "vbb"};
330         int ret;
331
332         match = dev_get_platdata(&pdev->dev);
333         if (!match)
334                 return -ENODEV;
335
336         opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL);
337         if (!opp_data)
338                 return -ENOMEM;
339
340         opp_data->soc_data = match->data;
341
342         opp_data->cpu_dev = get_cpu_device(0);
343         if (!opp_data->cpu_dev) {
344                 pr_err("%s: Failed to get device for CPU0\n", __func__);
345                 return -ENODEV;
346         }
347
348         opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev);
349         if (!opp_data->opp_node) {
350                 dev_info(opp_data->cpu_dev,
351                          "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
352                 goto register_cpufreq_dt;
353         }
354
355         ret = ti_cpufreq_setup_syscon_register(opp_data);
356         if (ret)
357                 goto fail_put_node;
358
359         /*
360          * OPPs determine whether or not they are supported based on
361          * two metrics:
362          *      0 - SoC Revision
363          *      1 - eFuse value
364          */
365         ret = ti_cpufreq_get_rev(opp_data, &version[0]);
366         if (ret)
367                 goto fail_put_node;
368
369         ret = ti_cpufreq_get_efuse(opp_data, &version[1]);
370         if (ret)
371                 goto fail_put_node;
372
373         ti_opp_table = dev_pm_opp_set_supported_hw(opp_data->cpu_dev,
374                                                    version, VERSION_COUNT);
375         if (IS_ERR(ti_opp_table)) {
376                 dev_err(opp_data->cpu_dev,
377                         "Failed to set supported hardware\n");
378                 ret = PTR_ERR(ti_opp_table);
379                 goto fail_put_node;
380         }
381
382         opp_data->opp_table = ti_opp_table;
383
384         if (opp_data->soc_data->multi_regulator) {
385                 const char * const *reg_names = default_reg_names;
386
387                 if (opp_data->soc_data->reg_names)
388                         reg_names = opp_data->soc_data->reg_names;
389                 ti_opp_table = dev_pm_opp_set_regulators(opp_data->cpu_dev,
390                                                          reg_names,
391                                                          ARRAY_SIZE(default_reg_names));
392                 if (IS_ERR(ti_opp_table)) {
393                         dev_pm_opp_put_supported_hw(opp_data->opp_table);
394                         ret =  PTR_ERR(ti_opp_table);
395                         goto fail_put_node;
396                 }
397         }
398
399         of_node_put(opp_data->opp_node);
400 register_cpufreq_dt:
401         platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
402
403         return 0;
404
405 fail_put_node:
406         of_node_put(opp_data->opp_node);
407
408         return ret;
409 }
410
411 static int ti_cpufreq_init(void)
412 {
413         const struct of_device_id *match;
414
415         /* Check to ensure we are on a compatible platform */
416         match = ti_cpufreq_match_node();
417         if (match)
418                 platform_device_register_data(NULL, "ti-cpufreq", -1, match,
419                                               sizeof(*match));
420
421         return 0;
422 }
423 module_init(ti_cpufreq_init);
424
425 static struct platform_driver ti_cpufreq_driver = {
426         .probe = ti_cpufreq_probe,
427         .driver = {
428                 .name = "ti-cpufreq",
429         },
430 };
431 builtin_platform_driver(ti_cpufreq_driver);
432
433 MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
434 MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
435 MODULE_LICENSE("GPL v2");