xref: /linux/drivers/cpufreq/ti-cpufreq.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
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/platform_device.h>
16 #include <linux/pm_opp.h>
17 #include <linux/regmap.h>
18 #include <linux/slab.h>
19 #include <linux/sys_soc.h>
20 
21 #define REVISION_MASK				0xF
22 #define REVISION_SHIFT				28
23 
24 #define AM33XX_800M_ARM_MPU_MAX_FREQ		0x1E2F
25 #define AM43XX_600M_ARM_MPU_MAX_FREQ		0xFFA
26 
27 #define DRA7_EFUSE_HAS_OD_MPU_OPP		11
28 #define DRA7_EFUSE_HAS_HIGH_MPU_OPP		15
29 #define DRA76_EFUSE_HAS_PLUS_MPU_OPP		18
30 #define DRA7_EFUSE_HAS_ALL_MPU_OPP		23
31 #define DRA76_EFUSE_HAS_ALL_MPU_OPP		24
32 
33 #define DRA7_EFUSE_NOM_MPU_OPP			BIT(0)
34 #define DRA7_EFUSE_OD_MPU_OPP			BIT(1)
35 #define DRA7_EFUSE_HIGH_MPU_OPP			BIT(2)
36 #define DRA76_EFUSE_PLUS_MPU_OPP		BIT(3)
37 
38 #define OMAP3_CONTROL_DEVICE_STATUS		0x4800244C
39 #define OMAP3_CONTROL_IDCODE			0x4830A204
40 #define OMAP34xx_ProdID_SKUID			0x4830A20C
41 #define OMAP3_SYSCON_BASE	(0x48000000 + 0x2000 + 0x270)
42 
43 #define AM625_EFUSE_K_MPU_OPP			11
44 #define AM625_EFUSE_S_MPU_OPP			19
45 #define AM625_EFUSE_T_MPU_OPP			20
46 
47 #define AM625_SUPPORT_K_MPU_OPP			BIT(0)
48 #define AM625_SUPPORT_S_MPU_OPP			BIT(1)
49 #define AM625_SUPPORT_T_MPU_OPP			BIT(2)
50 
51 enum {
52 	AM62A7_EFUSE_M_MPU_OPP =		13,
53 	AM62A7_EFUSE_N_MPU_OPP,
54 	AM62A7_EFUSE_O_MPU_OPP,
55 	AM62A7_EFUSE_P_MPU_OPP,
56 	AM62A7_EFUSE_Q_MPU_OPP,
57 	AM62A7_EFUSE_R_MPU_OPP,
58 	AM62A7_EFUSE_S_MPU_OPP,
59 	/*
60 	 * The V, U, and T speed grade numbering is out of order
61 	 * to align with the AM625 more uniformly. I promise I know
62 	 * my ABCs ;)
63 	 */
64 	AM62A7_EFUSE_V_MPU_OPP,
65 	AM62A7_EFUSE_U_MPU_OPP,
66 	AM62A7_EFUSE_T_MPU_OPP,
67 };
68 
69 #define AM62A7_SUPPORT_N_MPU_OPP		BIT(0)
70 #define AM62A7_SUPPORT_R_MPU_OPP		BIT(1)
71 #define AM62A7_SUPPORT_V_MPU_OPP		BIT(2)
72 
73 #define AM62P5_EFUSE_O_MPU_OPP			15
74 #define AM62P5_EFUSE_S_MPU_OPP			19
75 #define AM62P5_EFUSE_U_MPU_OPP			21
76 
77 #define AM62P5_SUPPORT_O_MPU_OPP		BIT(0)
78 #define AM62P5_SUPPORT_U_MPU_OPP		BIT(2)
79 
80 #define VERSION_COUNT				2
81 
82 struct ti_cpufreq_data;
83 
84 struct ti_cpufreq_soc_data {
85 	const char * const *reg_names;
86 	unsigned long (*efuse_xlate)(struct ti_cpufreq_data *opp_data,
87 				     unsigned long efuse);
88 	unsigned long efuse_fallback;
89 	unsigned long efuse_offset;
90 	unsigned long efuse_mask;
91 	unsigned long efuse_shift;
92 	unsigned long rev_offset;
93 	bool multi_regulator;
94 /* Backward compatibility hack: Might have missing syscon */
95 #define TI_QUIRK_SYSCON_MAY_BE_MISSING	0x1
96 /* Backward compatibility hack: new syscon size is 1 register wide */
97 #define TI_QUIRK_SYSCON_IS_SINGLE_REG	0x2
98 	u8 quirks;
99 };
100 
101 struct ti_cpufreq_data {
102 	struct device *cpu_dev;
103 	struct device_node *opp_node;
104 	struct regmap *syscon;
105 	const struct ti_cpufreq_soc_data *soc_data;
106 };
107 
108 static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
109 				      unsigned long efuse)
110 {
111 	if (!efuse)
112 		efuse = opp_data->soc_data->efuse_fallback;
113 	/* AM335x and AM437x use "OPP disable" bits, so invert */
114 	return ~efuse;
115 }
116 
117 static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data,
118 				      unsigned long efuse)
119 {
120 	unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
121 
122 	/*
123 	 * The efuse on dra7 and am57 parts contains a specific
124 	 * value indicating the highest available OPP.
125 	 */
126 
127 	switch (efuse) {
128 	case DRA76_EFUSE_HAS_PLUS_MPU_OPP:
129 	case DRA76_EFUSE_HAS_ALL_MPU_OPP:
130 		calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP;
131 		fallthrough;
132 	case DRA7_EFUSE_HAS_ALL_MPU_OPP:
133 	case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
134 		calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
135 		fallthrough;
136 	case DRA7_EFUSE_HAS_OD_MPU_OPP:
137 		calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
138 	}
139 
140 	return calculated_efuse;
141 }
142 
143 static unsigned long omap3_efuse_xlate(struct ti_cpufreq_data *opp_data,
144 				      unsigned long efuse)
145 {
146 	/* OPP enable bit ("Speed Binned") */
147 	return BIT(efuse);
148 }
149 
150 static unsigned long am62p5_efuse_xlate(struct ti_cpufreq_data *opp_data,
151 					unsigned long efuse)
152 {
153 	unsigned long calculated_efuse = AM62P5_SUPPORT_O_MPU_OPP;
154 
155 	switch (efuse) {
156 	case AM62P5_EFUSE_U_MPU_OPP:
157 	case AM62P5_EFUSE_S_MPU_OPP:
158 		calculated_efuse |= AM62P5_SUPPORT_U_MPU_OPP;
159 		fallthrough;
160 	case AM62P5_EFUSE_O_MPU_OPP:
161 		calculated_efuse |= AM62P5_SUPPORT_O_MPU_OPP;
162 	}
163 
164 	return calculated_efuse;
165 }
166 
167 static unsigned long am62a7_efuse_xlate(struct ti_cpufreq_data *opp_data,
168 					unsigned long efuse)
169 {
170 	unsigned long calculated_efuse = AM62A7_SUPPORT_N_MPU_OPP;
171 
172 	switch (efuse) {
173 	case AM62A7_EFUSE_V_MPU_OPP:
174 	case AM62A7_EFUSE_U_MPU_OPP:
175 	case AM62A7_EFUSE_T_MPU_OPP:
176 	case AM62A7_EFUSE_S_MPU_OPP:
177 		calculated_efuse |= AM62A7_SUPPORT_V_MPU_OPP;
178 		fallthrough;
179 	case AM62A7_EFUSE_R_MPU_OPP:
180 	case AM62A7_EFUSE_Q_MPU_OPP:
181 	case AM62A7_EFUSE_P_MPU_OPP:
182 	case AM62A7_EFUSE_O_MPU_OPP:
183 		calculated_efuse |= AM62A7_SUPPORT_R_MPU_OPP;
184 		fallthrough;
185 	case AM62A7_EFUSE_N_MPU_OPP:
186 	case AM62A7_EFUSE_M_MPU_OPP:
187 		calculated_efuse |= AM62A7_SUPPORT_N_MPU_OPP;
188 	}
189 
190 	return calculated_efuse;
191 }
192 
193 static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data,
194 				       unsigned long efuse)
195 {
196 	unsigned long calculated_efuse = AM625_SUPPORT_K_MPU_OPP;
197 
198 	switch (efuse) {
199 	case AM625_EFUSE_T_MPU_OPP:
200 		calculated_efuse |= AM625_SUPPORT_T_MPU_OPP;
201 		fallthrough;
202 	case AM625_EFUSE_S_MPU_OPP:
203 		calculated_efuse |= AM625_SUPPORT_S_MPU_OPP;
204 		fallthrough;
205 	case AM625_EFUSE_K_MPU_OPP:
206 		calculated_efuse |= AM625_SUPPORT_K_MPU_OPP;
207 	}
208 
209 	return calculated_efuse;
210 }
211 
212 static struct ti_cpufreq_soc_data am3x_soc_data = {
213 	.efuse_xlate = amx3_efuse_xlate,
214 	.efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
215 	.efuse_offset = 0x07fc,
216 	.efuse_mask = 0x1fff,
217 	.rev_offset = 0x600,
218 	.multi_regulator = false,
219 };
220 
221 static struct ti_cpufreq_soc_data am4x_soc_data = {
222 	.efuse_xlate = amx3_efuse_xlate,
223 	.efuse_fallback = AM43XX_600M_ARM_MPU_MAX_FREQ,
224 	.efuse_offset = 0x0610,
225 	.efuse_mask = 0x3f,
226 	.rev_offset = 0x600,
227 	.multi_regulator = false,
228 };
229 
230 static struct ti_cpufreq_soc_data dra7_soc_data = {
231 	.efuse_xlate = dra7_efuse_xlate,
232 	.efuse_offset = 0x020c,
233 	.efuse_mask = 0xf80000,
234 	.efuse_shift = 19,
235 	.rev_offset = 0x204,
236 	.multi_regulator = true,
237 };
238 
239 /*
240  * OMAP35x TRM (SPRUF98K):
241  *  CONTROL_IDCODE (0x4830 A204) describes Silicon revisions.
242  *  Control OMAP Status Register 15:0 (Address 0x4800 244C)
243  *    to separate between omap3503, omap3515, omap3525, omap3530
244  *    and feature presence.
245  *    There are encodings for versions limited to 400/266MHz
246  *    but we ignore.
247  *    Not clear if this also holds for omap34xx.
248  *  some eFuse values e.g. CONTROL_FUSE_OPP1_VDD1
249  *    are stored in the SYSCON register range
250  *  Register 0x4830A20C [ProdID.SKUID] [0:3]
251  *    0x0 for normal 600/430MHz device.
252  *    0x8 for 720/520MHz device.
253  *    Not clear what omap34xx value is.
254  */
255 
256 static struct ti_cpufreq_soc_data omap34xx_soc_data = {
257 	.efuse_xlate = omap3_efuse_xlate,
258 	.efuse_offset = OMAP34xx_ProdID_SKUID - OMAP3_SYSCON_BASE,
259 	.efuse_shift = 3,
260 	.efuse_mask = BIT(3),
261 	.rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
262 	.multi_regulator = false,
263 	.quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING,
264 };
265 
266 /*
267  * AM/DM37x TRM (SPRUGN4M)
268  *  CONTROL_IDCODE (0x4830 A204) describes Silicon revisions.
269  *  Control Device Status Register 15:0 (Address 0x4800 244C)
270  *    to separate between am3703, am3715, dm3725, dm3730
271  *    and feature presence.
272  *   Speed Binned = Bit 9
273  *     0 800/600 MHz
274  *     1 1000/800 MHz
275  *  some eFuse values e.g. CONTROL_FUSE_OPP 1G_VDD1
276  *    are stored in the SYSCON register range.
277  *  There is no 0x4830A20C [ProdID.SKUID] register (exists but
278  *    seems to always read as 0).
279  */
280 
281 static const char * const omap3_reg_names[] = {"cpu0", "vbb", NULL};
282 
283 static struct ti_cpufreq_soc_data omap36xx_soc_data = {
284 	.reg_names = omap3_reg_names,
285 	.efuse_xlate = omap3_efuse_xlate,
286 	.efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE,
287 	.efuse_shift = 9,
288 	.efuse_mask = BIT(9),
289 	.rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
290 	.multi_regulator = true,
291 	.quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING,
292 };
293 
294 /*
295  * AM3517 is quite similar to AM/DM37x except that it has no
296  * high speed grade eFuse and no abb ldo
297  */
298 
299 static struct ti_cpufreq_soc_data am3517_soc_data = {
300 	.efuse_xlate = omap3_efuse_xlate,
301 	.efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE,
302 	.efuse_shift = 0,
303 	.efuse_mask = 0,
304 	.rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE,
305 	.multi_regulator = false,
306 	.quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING,
307 };
308 
309 static const struct soc_device_attribute k3_cpufreq_soc[] = {
310 	{ .family = "AM62X", .revision = "SR1.0" },
311 	{ .family = "AM62AX", .revision = "SR1.0" },
312 	{ .family = "AM62PX", .revision = "SR1.0" },
313 	{ /* sentinel */ }
314 };
315 
316 static struct ti_cpufreq_soc_data am625_soc_data = {
317 	.efuse_xlate = am625_efuse_xlate,
318 	.efuse_offset = 0x0018,
319 	.efuse_mask = 0x07c0,
320 	.efuse_shift = 0x6,
321 	.multi_regulator = false,
322 	.quirks = TI_QUIRK_SYSCON_IS_SINGLE_REG,
323 };
324 
325 static struct ti_cpufreq_soc_data am62a7_soc_data = {
326 	.efuse_xlate = am62a7_efuse_xlate,
327 	.efuse_offset = 0x0,
328 	.efuse_mask = 0x07c0,
329 	.efuse_shift = 0x6,
330 	.multi_regulator = false,
331 };
332 
333 static struct ti_cpufreq_soc_data am62p5_soc_data = {
334 	.efuse_xlate = am62p5_efuse_xlate,
335 	.efuse_offset = 0x0,
336 	.efuse_mask = 0x07c0,
337 	.efuse_shift = 0x6,
338 	.multi_regulator = false,
339 };
340 
341 /**
342  * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
343  * @opp_data: pointer to ti_cpufreq_data context
344  * @efuse_value: Set to the value parsed from efuse
345  *
346  * Returns error code if efuse not read properly.
347  */
348 static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data,
349 				u32 *efuse_value)
350 {
351 	struct device *dev = opp_data->cpu_dev;
352 	u32 efuse;
353 	int ret;
354 
355 	ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset,
356 			  &efuse);
357 
358 	if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_IS_SINGLE_REG && ret == -EIO)
359 		ret = regmap_read(opp_data->syscon, 0x0, &efuse);
360 
361 	if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) {
362 		/* not a syscon register! */
363 		void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
364 				opp_data->soc_data->efuse_offset, 4);
365 
366 		if (!regs)
367 			return -ENOMEM;
368 		efuse = readl(regs);
369 		iounmap(regs);
370 		}
371 	else if (ret) {
372 		dev_err(dev,
373 			"Failed to read the efuse value from syscon: %d\n",
374 			ret);
375 		return ret;
376 	}
377 
378 	efuse = (efuse & opp_data->soc_data->efuse_mask);
379 	efuse >>= opp_data->soc_data->efuse_shift;
380 
381 	*efuse_value = opp_data->soc_data->efuse_xlate(opp_data, efuse);
382 
383 	return 0;
384 }
385 
386 /**
387  * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
388  * @opp_data: pointer to ti_cpufreq_data context
389  * @revision_value: Set to the value parsed from revision register
390  *
391  * Returns error code if revision not read properly.
392  */
393 static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
394 			      u32 *revision_value)
395 {
396 	struct device *dev = opp_data->cpu_dev;
397 	u32 revision;
398 	int ret;
399 	if (soc_device_match(k3_cpufreq_soc)) {
400 		/*
401 		 * Since the SR is 1.0, hard code the revision_value as
402 		 * 0x1 here. This way we avoid re using the same register
403 		 * that is giving us required information inside socinfo
404 		 * anyway.
405 		 */
406 		*revision_value = 0x1;
407 		goto done;
408 	}
409 
410 	ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset,
411 			  &revision);
412 	if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) {
413 		/* not a syscon register! */
414 		void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
415 				opp_data->soc_data->rev_offset, 4);
416 
417 		if (!regs)
418 			return -ENOMEM;
419 		revision = readl(regs);
420 		iounmap(regs);
421 		}
422 	else if (ret) {
423 		dev_err(dev,
424 			"Failed to read the revision number from syscon: %d\n",
425 			ret);
426 		return ret;
427 	}
428 
429 	*revision_value = BIT((revision >> REVISION_SHIFT) & REVISION_MASK);
430 
431 done:
432 	return 0;
433 }
434 
435 static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data)
436 {
437 	struct device *dev = opp_data->cpu_dev;
438 	struct device_node *np = opp_data->opp_node;
439 
440 	opp_data->syscon = syscon_regmap_lookup_by_phandle(np,
441 							"syscon");
442 	if (IS_ERR(opp_data->syscon)) {
443 		dev_err(dev,
444 			"\"syscon\" is missing, cannot use OPPv2 table.\n");
445 		return PTR_ERR(opp_data->syscon);
446 	}
447 
448 	return 0;
449 }
450 
451 static const struct of_device_id ti_cpufreq_of_match[]  __maybe_unused = {
452 	{ .compatible = "ti,am33xx", .data = &am3x_soc_data, },
453 	{ .compatible = "ti,am3517", .data = &am3517_soc_data, },
454 	{ .compatible = "ti,am43", .data = &am4x_soc_data, },
455 	{ .compatible = "ti,dra7", .data = &dra7_soc_data },
456 	{ .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, },
457 	{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
458 	{ .compatible = "ti,am625", .data = &am625_soc_data, },
459 	{ .compatible = "ti,am62a7", .data = &am62a7_soc_data, },
460 	{ .compatible = "ti,am62p5", .data = &am62p5_soc_data, },
461 	/* legacy */
462 	{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
463 	{ .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
464 	{},
465 };
466 
467 static const struct of_device_id *ti_cpufreq_match_node(void)
468 {
469 	struct device_node *np __free(device_node) = of_find_node_by_path("/");
470 	const struct of_device_id *match;
471 
472 	match = of_match_node(ti_cpufreq_of_match, np);
473 
474 	return match;
475 }
476 
477 static int ti_cpufreq_probe(struct platform_device *pdev)
478 {
479 	u32 version[VERSION_COUNT];
480 	const struct of_device_id *match;
481 	struct ti_cpufreq_data *opp_data;
482 	const char * const default_reg_names[] = {"vdd", "vbb", NULL};
483 	int ret;
484 	struct dev_pm_opp_config config = {
485 		.supported_hw = version,
486 		.supported_hw_count = ARRAY_SIZE(version),
487 	};
488 
489 	match = dev_get_platdata(&pdev->dev);
490 	if (!match)
491 		return -ENODEV;
492 
493 	opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL);
494 	if (!opp_data)
495 		return -ENOMEM;
496 
497 	opp_data->soc_data = match->data;
498 
499 	opp_data->cpu_dev = get_cpu_device(0);
500 	if (!opp_data->cpu_dev) {
501 		pr_err("%s: Failed to get device for CPU0\n", __func__);
502 		return -ENODEV;
503 	}
504 
505 	opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev);
506 	if (!opp_data->opp_node) {
507 		dev_info(opp_data->cpu_dev,
508 			 "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
509 		goto register_cpufreq_dt;
510 	}
511 
512 	ret = ti_cpufreq_setup_syscon_register(opp_data);
513 	if (ret)
514 		goto fail_put_node;
515 
516 	/*
517 	 * OPPs determine whether or not they are supported based on
518 	 * two metrics:
519 	 *	0 - SoC Revision
520 	 *	1 - eFuse value
521 	 */
522 	ret = ti_cpufreq_get_rev(opp_data, &version[0]);
523 	if (ret)
524 		goto fail_put_node;
525 
526 	ret = ti_cpufreq_get_efuse(opp_data, &version[1]);
527 	if (ret)
528 		goto fail_put_node;
529 
530 	if (opp_data->soc_data->multi_regulator) {
531 		if (opp_data->soc_data->reg_names)
532 			config.regulator_names = opp_data->soc_data->reg_names;
533 		else
534 			config.regulator_names = default_reg_names;
535 	}
536 
537 	ret = dev_pm_opp_set_config(opp_data->cpu_dev, &config);
538 	if (ret < 0) {
539 		dev_err_probe(opp_data->cpu_dev, ret, "Failed to set OPP config\n");
540 		goto fail_put_node;
541 	}
542 
543 	of_node_put(opp_data->opp_node);
544 
545 register_cpufreq_dt:
546 	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
547 
548 	return 0;
549 
550 fail_put_node:
551 	of_node_put(opp_data->opp_node);
552 
553 	return ret;
554 }
555 
556 static int __init ti_cpufreq_init(void)
557 {
558 	const struct of_device_id *match;
559 
560 	/* Check to ensure we are on a compatible platform */
561 	match = ti_cpufreq_match_node();
562 	if (match)
563 		platform_device_register_data(NULL, "ti-cpufreq", -1, match,
564 					      sizeof(*match));
565 
566 	return 0;
567 }
568 module_init(ti_cpufreq_init);
569 
570 static struct platform_driver ti_cpufreq_driver = {
571 	.probe = ti_cpufreq_probe,
572 	.driver = {
573 		.name = "ti-cpufreq",
574 	},
575 };
576 builtin_platform_driver(ti_cpufreq_driver);
577 
578 MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
579 MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
580 MODULE_LICENSE("GPL v2");
581