2 * Utility functions for parsing Tegra CVB voltage tables
4 * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 #include <linux/err.h>
17 #include <linux/kernel.h>
18 #include <linux/pm_opp.h>
22 /* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */
23 static inline int get_cvb_voltage(int speedo
, int s_scale
,
24 const struct cvb_coefficients
*cvb
)
28 /* apply only speedo scale: output mv = cvb_mv * v_scale */
29 mv
= DIV_ROUND_CLOSEST(cvb
->c2
* speedo
, s_scale
);
30 mv
= DIV_ROUND_CLOSEST((mv
+ cvb
->c1
) * speedo
, s_scale
) + cvb
->c0
;
34 static int round_cvb_voltage(int mv
, int v_scale
,
35 const struct rail_alignment
*align
)
37 /* combined: apply voltage scale and round to cvb alignment step */
39 int step
= (align
->step_uv
? : 1000) * v_scale
;
40 int offset
= align
->offset_uv
* v_scale
;
42 uv
= max(mv
* 1000, offset
) - offset
;
43 uv
= DIV_ROUND_UP(uv
, step
) * align
->step_uv
+ align
->offset_uv
;
52 static int round_voltage(int mv
, const struct rail_alignment
*align
, int up
)
57 uv
= max(mv
* 1000, align
->offset_uv
) - align
->offset_uv
;
58 uv
= (uv
+ (up
? align
->step_uv
- 1 : 0)) / align
->step_uv
;
59 return (uv
* align
->step_uv
+ align
->offset_uv
) / 1000;
64 static int build_opp_table(const struct cvb_table
*d
,
66 unsigned long max_freq
,
67 struct device
*opp_dev
)
69 int i
, ret
, dfll_mv
, min_mv
, max_mv
;
70 const struct cvb_table_freq_entry
*table
= NULL
;
71 const struct rail_alignment
*align
= &d
->alignment
;
73 min_mv
= round_voltage(d
->min_millivolts
, align
, UP
);
74 max_mv
= round_voltage(d
->max_millivolts
, align
, DOWN
);
76 for (i
= 0; i
< MAX_DVFS_FREQS
; i
++) {
77 table
= &d
->cvb_table
[i
];
78 if (!table
->freq
|| (table
->freq
> max_freq
))
81 dfll_mv
= get_cvb_voltage(
82 speedo_value
, d
->speedo_scale
, &table
->coefficients
);
83 dfll_mv
= round_cvb_voltage(dfll_mv
, d
->voltage_scale
, align
);
84 dfll_mv
= clamp(dfll_mv
, min_mv
, max_mv
);
86 ret
= dev_pm_opp_add(opp_dev
, table
->freq
, dfll_mv
* 1000);
95 * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables
96 * @cvb_tables: array of CVB tables
97 * @sz: size of the previously mentioned array
98 * @process_id: process id of the HW module
99 * @speedo_id: speedo id of the HW module
100 * @speedo_value: speedo value of the HW module
101 * @max_rate: highest safe clock rate
102 * @opp_dev: the struct device * for which the OPP table is built
104 * On Tegra, a CVB table encodes the relationship between operating voltage
105 * and safe maximal frequency for a given module (e.g. GPU or CPU). This
106 * function calculates the optimal voltage-frequency operating points
107 * for the given arguments and exports them via the OPP library for the
108 * given @opp_dev. Returns a pointer to the struct cvb_table that matched
109 * or an ERR_PTR on failure.
111 const struct cvb_table
*tegra_cvb_build_opp_table(
112 const struct cvb_table
*cvb_tables
,
113 size_t sz
, int process_id
,
114 int speedo_id
, int speedo_value
,
115 unsigned long max_rate
,
116 struct device
*opp_dev
)
120 for (i
= 0; i
< sz
; i
++) {
121 const struct cvb_table
*d
= &cvb_tables
[i
];
123 if (d
->speedo_id
!= -1 && d
->speedo_id
!= speedo_id
)
125 if (d
->process_id
!= -1 && d
->process_id
!= process_id
)
128 ret
= build_opp_table(d
, speedo_value
, max_rate
, opp_dev
);
129 return ret
? ERR_PTR(ret
) : d
;
132 return ERR_PTR(-EINVAL
);