blob: 648d396e2a5101faa613858d7e6d8e4487ea2b33 [file] [log] [blame]
David Collins7370f1a2017-01-18 16:21:53 -08001/*
2 * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/*
15 * This file contains utility functions to be used by platform specific CPR3
16 * regulator drivers.
17 */
18
19#define pr_fmt(fmt) "%s: " fmt, __func__
20
21#include <linux/cpumask.h>
22#include <linux/device.h>
23#include <linux/io.h>
24#include <linux/kernel.h>
25#include <linux/of.h>
26#include <linux/platform_device.h>
27#include <linux/slab.h>
28#include <linux/types.h>
29
30#include "cpr3-regulator.h"
31
32#define BYTES_PER_FUSE_ROW 8
33#define MAX_FUSE_ROW_BIT 63
34
35#define CPR3_CONSECUTIVE_UP_DOWN_MIN 0
36#define CPR3_CONSECUTIVE_UP_DOWN_MAX 15
37#define CPR3_UP_DOWN_THRESHOLD_MIN 0
38#define CPR3_UP_DOWN_THRESHOLD_MAX 31
39#define CPR3_STEP_QUOT_MIN 0
40#define CPR3_STEP_QUOT_MAX 63
41#define CPR3_IDLE_CLOCKS_MIN 0
42#define CPR3_IDLE_CLOCKS_MAX 31
43
44/* This constant has units of uV/mV so 1000 corresponds to 100%. */
45#define CPR3_AGING_DERATE_UNITY 1000
46
47/**
48 * cpr3_allocate_regulators() - allocate and initialize CPR3 regulators for a
49 * given thread based upon device tree data
50 * @thread: Pointer to the CPR3 thread
51 *
52 * This function allocates the thread->vreg array based upon the number of
53 * device tree regulator subnodes. It also initializes generic elements of each
54 * regulator struct such as name, of_node, and thread.
55 *
56 * Return: 0 on success, errno on failure
57 */
58static int cpr3_allocate_regulators(struct cpr3_thread *thread)
59{
60 struct device_node *node;
61 int i, rc;
62
63 thread->vreg_count = 0;
64
65 for_each_available_child_of_node(thread->of_node, node) {
66 thread->vreg_count++;
67 }
68
69 thread->vreg = devm_kcalloc(thread->ctrl->dev, thread->vreg_count,
70 sizeof(*thread->vreg), GFP_KERNEL);
71 if (!thread->vreg)
72 return -ENOMEM;
73
74 i = 0;
75 for_each_available_child_of_node(thread->of_node, node) {
76 thread->vreg[i].of_node = node;
77 thread->vreg[i].thread = thread;
78
79 rc = of_property_read_string(node, "regulator-name",
80 &thread->vreg[i].name);
81 if (rc) {
82 dev_err(thread->ctrl->dev, "could not find regulator name, rc=%d\n",
83 rc);
84 return rc;
85 }
86
87 i++;
88 }
89
90 return 0;
91}
92
93/**
94 * cpr3_allocate_threads() - allocate and initialize CPR3 threads for a given
95 * controller based upon device tree data
96 * @ctrl: Pointer to the CPR3 controller
97 * @min_thread_id: Minimum allowed hardware thread ID for this controller
98 * @max_thread_id: Maximum allowed hardware thread ID for this controller
99 *
100 * This function allocates the ctrl->thread array based upon the number of
101 * device tree thread subnodes. It also initializes generic elements of each
102 * thread struct such as thread_id, of_node, ctrl, and vreg array.
103 *
104 * Return: 0 on success, errno on failure
105 */
106int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id,
107 u32 max_thread_id)
108{
109 struct device *dev = ctrl->dev;
110 struct device_node *thread_node;
111 int i, j, rc;
112
113 ctrl->thread_count = 0;
114
115 for_each_available_child_of_node(dev->of_node, thread_node) {
116 ctrl->thread_count++;
117 }
118
119 ctrl->thread = devm_kcalloc(dev, ctrl->thread_count,
120 sizeof(*ctrl->thread), GFP_KERNEL);
121 if (!ctrl->thread)
122 return -ENOMEM;
123
124 i = 0;
125 for_each_available_child_of_node(dev->of_node, thread_node) {
126 ctrl->thread[i].of_node = thread_node;
127 ctrl->thread[i].ctrl = ctrl;
128
129 rc = of_property_read_u32(thread_node, "qcom,cpr-thread-id",
130 &ctrl->thread[i].thread_id);
131 if (rc) {
132 dev_err(dev, "could not read DT property qcom,cpr-thread-id, rc=%d\n",
133 rc);
134 return rc;
135 }
136
137 if (ctrl->thread[i].thread_id < min_thread_id ||
138 ctrl->thread[i].thread_id > max_thread_id) {
139 dev_err(dev, "invalid thread id = %u; not within [%u, %u]\n",
140 ctrl->thread[i].thread_id, min_thread_id,
141 max_thread_id);
142 return -EINVAL;
143 }
144
145 /* Verify that the thread ID is unique for all child nodes. */
146 for (j = 0; j < i; j++) {
147 if (ctrl->thread[j].thread_id
148 == ctrl->thread[i].thread_id) {
149 dev_err(dev, "duplicate thread id = %u found\n",
150 ctrl->thread[i].thread_id);
151 return -EINVAL;
152 }
153 }
154
155 rc = cpr3_allocate_regulators(&ctrl->thread[i]);
156 if (rc)
157 return rc;
158
159 i++;
160 }
161
162 return 0;
163}
164
165/**
166 * cpr3_map_fuse_base() - ioremap the base address of the fuse region
167 * @ctrl: Pointer to the CPR3 controller
168 * @pdev: Platform device pointer for the CPR3 controller
169 *
170 * Return: 0 on success, errno on failure
171 */
172int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
173 struct platform_device *pdev)
174{
175 struct resource *res;
176
177 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse_base");
178 if (!res || !res->start) {
179 dev_err(&pdev->dev, "fuse base address is missing\n");
180 return -ENXIO;
181 }
182
183 ctrl->fuse_base = devm_ioremap(&pdev->dev, res->start,
184 resource_size(res));
185
186 return 0;
187}
188
189/**
190 * cpr3_read_fuse_param() - reads a CPR3 fuse parameter out of eFuses
191 * @fuse_base_addr: Virtual memory address of the eFuse base address
192 * @param: Null terminated array of fuse param segments to read
193 * from
194 * @param_value: Output with value read from the eFuses
195 *
196 * This function reads from each of the parameter segments listed in the param
197 * array and concatenates their values together. Reading stops when an element
198 * is reached which has all 0 struct values. The total number of bits specified
199 * for the fuse parameter across all segments must be less than or equal to 64.
200 *
201 * Return: 0 on success, errno on failure
202 */
203int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
204 const struct cpr3_fuse_param *param, u64 *param_value)
205{
206 u64 fuse_val, val;
207 int bits;
208 int bits_total = 0;
209
210 *param_value = 0;
211
212 while (param->row || param->bit_start || param->bit_end) {
213 if (param->bit_start > param->bit_end
214 || param->bit_end > MAX_FUSE_ROW_BIT) {
215 pr_err("Invalid fuse parameter segment: row=%u, start=%u, end=%u\n",
216 param->row, param->bit_start, param->bit_end);
217 return -EINVAL;
218 }
219
220 bits = param->bit_end - param->bit_start + 1;
221 if (bits_total + bits > 64) {
222 pr_err("Invalid fuse parameter segments; total bits = %d\n",
223 bits_total + bits);
224 return -EINVAL;
225 }
226
227 fuse_val = readq_relaxed(fuse_base_addr
228 + param->row * BYTES_PER_FUSE_ROW);
229 val = (fuse_val >> param->bit_start) & ((1ULL << bits) - 1);
230 *param_value |= val << bits_total;
231 bits_total += bits;
232
233 param++;
234 }
235
236 return 0;
237}
238
239/**
240 * cpr3_convert_open_loop_voltage_fuse() - converts an open loop voltage fuse
241 * value into an absolute voltage with units of microvolts
242 * @ref_volt: Reference voltage in microvolts
243 * @step_volt: The step size in microvolts of the fuse LSB
244 * @fuse: Open loop voltage fuse value
245 * @fuse_len: The bit length of the fuse value
246 *
247 * The MSB of the fuse parameter corresponds to a sign bit. If it is set, then
248 * the lower bits correspond to the number of steps to go down from the
249 * reference voltage. If it is not set, then the lower bits correspond to the
250 * number of steps to go up from the reference voltage.
251 */
252int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse,
253 int fuse_len)
254{
255 int sign, steps;
256
257 sign = (fuse & (1 << (fuse_len - 1))) ? -1 : 1;
258 steps = fuse & ((1 << (fuse_len - 1)) - 1);
259
260 return ref_volt + sign * steps * step_volt;
261}
262
263/**
264 * cpr3_interpolate() - performs linear interpolation
265 * @x1 Lower known x value
266 * @y1 Lower known y value
267 * @x2 Upper known x value
268 * @y2 Upper known y value
269 * @x Intermediate x value
270 *
271 * Returns y where (x, y) falls on the line between (x1, y1) and (x2, y2).
272 * It is required that x1 < x2, y1 <= y2, and x1 <= x <= x2. If these
273 * conditions are not met, then y2 will be returned.
274 */
275u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x)
276{
277 u64 temp;
278
279 if (x1 >= x2 || y1 > y2 || x1 > x || x > x2)
280 return y2;
281
282 temp = (x2 - x) * (y2 - y1);
283 do_div(temp, (u32)(x2 - x1));
284
285 return y2 - temp;
286}
287
288/**
289 * cpr3_parse_array_property() - fill an array from a portion of the values
290 * specified for a device tree property
291 * @vreg: Pointer to the CPR3 regulator
292 * @prop_name: The name of the device tree property to read from
293 * @tuple_size: The number of elements in each tuple
294 * @out: Output data array which must be of size tuple_size
295 *
296 * cpr3_parse_common_corner_data() must be called for vreg before this function
297 * is called so that fuse combo and speed bin size elements are initialized.
298 *
299 * Three formats are supported for the device tree property:
300 * 1. Length == tuple_size
301 * (reading begins at index 0)
302 * 2. Length == tuple_size * vreg->fuse_combos_supported
303 * (reading begins at index tuple_size * vreg->fuse_combo)
304 * 3. Length == tuple_size * vreg->speed_bins_supported
305 * (reading begins at index tuple_size * vreg->speed_bin_fuse)
306 *
307 * All other property lengths are treated as errors.
308 *
309 * Return: 0 on success, errno on failure
310 */
311int cpr3_parse_array_property(struct cpr3_regulator *vreg,
312 const char *prop_name, int tuple_size, u32 *out)
313{
314 struct device_node *node = vreg->of_node;
315 int len = 0;
316 int i, offset, rc;
317
318 if (!of_find_property(node, prop_name, &len)) {
319 cpr3_err(vreg, "property %s is missing\n", prop_name);
320 return -EINVAL;
321 }
322
323 if (len == tuple_size * sizeof(u32)) {
324 offset = 0;
325 } else if (len == tuple_size * vreg->fuse_combos_supported
326 * sizeof(u32)) {
327 offset = tuple_size * vreg->fuse_combo;
328 } else if (vreg->speed_bins_supported > 0 &&
329 len == tuple_size * vreg->speed_bins_supported * sizeof(u32)) {
330 offset = tuple_size * vreg->speed_bin_fuse;
331 } else {
332 if (vreg->speed_bins_supported > 0)
333 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
334 prop_name, len,
335 tuple_size * sizeof(u32),
336 tuple_size * vreg->speed_bins_supported
337 * sizeof(u32),
338 tuple_size * vreg->fuse_combos_supported
339 * sizeof(u32));
340 else
341 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
342 prop_name, len,
343 tuple_size * sizeof(u32),
344 tuple_size * vreg->fuse_combos_supported
345 * sizeof(u32));
346 return -EINVAL;
347 }
348
349 for (i = 0; i < tuple_size; i++) {
350 rc = of_property_read_u32_index(node, prop_name, offset + i,
351 &out[i]);
352 if (rc) {
353 cpr3_err(vreg, "error reading property %s, rc=%d\n",
354 prop_name, rc);
355 return rc;
356 }
357 }
358
359 return 0;
360}
361
362/**
363 * cpr3_parse_corner_array_property() - fill a per-corner array from a portion
364 * of the values specified for a device tree property
365 * @vreg: Pointer to the CPR3 regulator
366 * @prop_name: The name of the device tree property to read from
367 * @tuple_size: The number of elements in each per-corner tuple
368 * @out: Output data array which must be of size:
369 * tuple_size * vreg->corner_count
370 *
371 * cpr3_parse_common_corner_data() must be called for vreg before this function
372 * is called so that fuse combo and speed bin size elements are initialized.
373 *
374 * Three formats are supported for the device tree property:
375 * 1. Length == tuple_size * vreg->corner_count
376 * (reading begins at index 0)
377 * 2. Length == tuple_size * vreg->fuse_combo_corner_sum
378 * (reading begins at index tuple_size * vreg->fuse_combo_offset)
379 * 3. Length == tuple_size * vreg->speed_bin_corner_sum
380 * (reading begins at index tuple_size * vreg->speed_bin_offset)
381 *
382 * All other property lengths are treated as errors.
383 *
384 * Return: 0 on success, errno on failure
385 */
386int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
387 const char *prop_name, int tuple_size, u32 *out)
388{
389 struct device_node *node = vreg->of_node;
390 int len = 0;
391 int i, offset, rc;
392
393 if (!of_find_property(node, prop_name, &len)) {
394 cpr3_err(vreg, "property %s is missing\n", prop_name);
395 return -EINVAL;
396 }
397
398 if (len == tuple_size * vreg->corner_count * sizeof(u32)) {
399 offset = 0;
400 } else if (len == tuple_size * vreg->fuse_combo_corner_sum
401 * sizeof(u32)) {
402 offset = tuple_size * vreg->fuse_combo_offset;
403 } else if (vreg->speed_bin_corner_sum > 0 &&
404 len == tuple_size * vreg->speed_bin_corner_sum * sizeof(u32)) {
405 offset = tuple_size * vreg->speed_bin_offset;
406 } else {
407 if (vreg->speed_bin_corner_sum > 0)
408 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
409 prop_name, len,
410 tuple_size * vreg->corner_count * sizeof(u32),
411 tuple_size * vreg->speed_bin_corner_sum
412 * sizeof(u32),
413 tuple_size * vreg->fuse_combo_corner_sum
414 * sizeof(u32));
415 else
416 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
417 prop_name, len,
418 tuple_size * vreg->corner_count * sizeof(u32),
419 tuple_size * vreg->fuse_combo_corner_sum
420 * sizeof(u32));
421 return -EINVAL;
422 }
423
424 for (i = 0; i < tuple_size * vreg->corner_count; i++) {
425 rc = of_property_read_u32_index(node, prop_name, offset + i,
426 &out[i]);
427 if (rc) {
428 cpr3_err(vreg, "error reading property %s, rc=%d\n",
429 prop_name, rc);
430 return rc;
431 }
432 }
433
434 return 0;
435}
436
437/**
438 * cpr3_parse_corner_band_array_property() - fill a per-corner band array
439 * from a portion of the values specified for a device tree
440 * property
441 * @vreg: Pointer to the CPR3 regulator
442 * @prop_name: The name of the device tree property to read from
443 * @tuple_size: The number of elements in each per-corner band tuple
444 * @out: Output data array which must be of size:
445 * tuple_size * vreg->corner_band_count
446 *
447 * cpr3_parse_common_corner_data() must be called for vreg before this function
448 * is called so that fuse combo and speed bin size elements are initialized.
449 * In addition, corner band fuse combo and speed bin sum and offset elements
450 * must be initialized prior to executing this function.
451 *
452 * Three formats are supported for the device tree property:
453 * 1. Length == tuple_size * vreg->corner_band_count
454 * (reading begins at index 0)
455 * 2. Length == tuple_size * vreg->fuse_combo_corner_band_sum
456 * (reading begins at index tuple_size *
457 * vreg->fuse_combo_corner_band_offset)
458 * 3. Length == tuple_size * vreg->speed_bin_corner_band_sum
459 * (reading begins at index tuple_size *
460 * vreg->speed_bin_corner_band_offset)
461 *
462 * All other property lengths are treated as errors.
463 *
464 * Return: 0 on success, errno on failure
465 */
466int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg,
467 const char *prop_name, int tuple_size, u32 *out)
468{
469 struct device_node *node = vreg->of_node;
470 int len = 0;
471 int i, offset, rc;
472
473 if (!of_find_property(node, prop_name, &len)) {
474 cpr3_err(vreg, "property %s is missing\n", prop_name);
475 return -EINVAL;
476 }
477
478 if (len == tuple_size * vreg->corner_band_count * sizeof(u32)) {
479 offset = 0;
480 } else if (len == tuple_size * vreg->fuse_combo_corner_band_sum
481 * sizeof(u32)) {
482 offset = tuple_size * vreg->fuse_combo_corner_band_offset;
483 } else if (vreg->speed_bin_corner_band_sum > 0 &&
484 len == tuple_size * vreg->speed_bin_corner_band_sum *
485 sizeof(u32)) {
486 offset = tuple_size * vreg->speed_bin_corner_band_offset;
487 } else {
488 if (vreg->speed_bin_corner_band_sum > 0)
489 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
490 prop_name, len,
491 tuple_size * vreg->corner_band_count *
492 sizeof(u32),
493 tuple_size * vreg->speed_bin_corner_band_sum
494 * sizeof(u32),
495 tuple_size * vreg->fuse_combo_corner_band_sum
496 * sizeof(u32));
497 else
498 cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
499 prop_name, len,
500 tuple_size * vreg->corner_band_count *
501 sizeof(u32),
502 tuple_size * vreg->fuse_combo_corner_band_sum
503 * sizeof(u32));
504 return -EINVAL;
505 }
506
507 for (i = 0; i < tuple_size * vreg->corner_band_count; i++) {
508 rc = of_property_read_u32_index(node, prop_name, offset + i,
509 &out[i]);
510 if (rc) {
511 cpr3_err(vreg, "error reading property %s, rc=%d\n",
512 prop_name, rc);
513 return rc;
514 }
515 }
516
517 return 0;
518}
519
520/**
521 * cpr3_parse_common_corner_data() - parse common CPR3 properties relating to
522 * the corners supported by a CPR3 regulator from device tree
523 * @vreg: Pointer to the CPR3 regulator
524 *
525 * This function reads, validates, and utilizes the following device tree
526 * properties: qcom,cpr-fuse-corners, qcom,cpr-fuse-combos, qcom,cpr-speed-bins,
527 * qcom,cpr-speed-bin-corners, qcom,cpr-corners, qcom,cpr-voltage-ceiling,
528 * qcom,cpr-voltage-floor, qcom,corner-frequencies,
529 * and qcom,cpr-corner-fmax-map.
530 *
531 * It initializes these CPR3 regulator elements: corner, corner_count,
532 * fuse_combos_supported, fuse_corner_map, and speed_bins_supported. It
533 * initializes these elements for each corner: ceiling_volt, floor_volt,
534 * proc_freq, and cpr_fuse_corner.
535 *
536 * It requires that the following CPR3 regulator elements be initialized before
537 * being called: fuse_corner_count, fuse_combo, and speed_bin_fuse.
538 *
539 * Return: 0 on success, errno on failure
540 */
541int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
542{
543 struct device_node *node = vreg->of_node;
544 struct cpr3_controller *ctrl = vreg->thread->ctrl;
545 u32 max_fuse_combos, fuse_corners, aging_allowed = 0;
546 u32 max_speed_bins = 0;
547 u32 *combo_corners;
548 u32 *speed_bin_corners;
549 u32 *temp;
550 int i, j, rc;
551
552 rc = of_property_read_u32(node, "qcom,cpr-fuse-corners", &fuse_corners);
553 if (rc) {
554 cpr3_err(vreg, "error reading property qcom,cpr-fuse-corners, rc=%d\n",
555 rc);
556 return rc;
557 }
558
559 if (vreg->fuse_corner_count != fuse_corners) {
560 cpr3_err(vreg, "device tree config supports %d fuse corners but the hardware has %d fuse corners\n",
561 fuse_corners, vreg->fuse_corner_count);
562 return -EINVAL;
563 }
564
565 rc = of_property_read_u32(node, "qcom,cpr-fuse-combos",
566 &max_fuse_combos);
567 if (rc) {
568 cpr3_err(vreg, "error reading property qcom,cpr-fuse-combos, rc=%d\n",
569 rc);
570 return rc;
571 }
572
573 /*
574 * Sanity check against arbitrarily large value to avoid excessive
575 * memory allocation.
576 */
577 if (max_fuse_combos > 100 || max_fuse_combos == 0) {
578 cpr3_err(vreg, "qcom,cpr-fuse-combos is invalid: %u\n",
579 max_fuse_combos);
580 return -EINVAL;
581 }
582
583 if (vreg->fuse_combo >= max_fuse_combos) {
584 cpr3_err(vreg, "device tree config supports fuse combos 0-%u but the hardware has combo %d\n",
585 max_fuse_combos - 1, vreg->fuse_combo);
586 BUG_ON(1);
587 return -EINVAL;
588 }
589
590 vreg->fuse_combos_supported = max_fuse_combos;
591
592 of_property_read_u32(node, "qcom,cpr-speed-bins", &max_speed_bins);
593
594 /*
595 * Sanity check against arbitrarily large value to avoid excessive
596 * memory allocation.
597 */
598 if (max_speed_bins > 100) {
599 cpr3_err(vreg, "qcom,cpr-speed-bins is invalid: %u\n",
600 max_speed_bins);
601 return -EINVAL;
602 }
603
604 if (max_speed_bins && vreg->speed_bin_fuse >= max_speed_bins) {
605 cpr3_err(vreg, "device tree config supports speed bins 0-%u but the hardware has speed bin %d\n",
606 max_speed_bins - 1, vreg->speed_bin_fuse);
607 BUG();
608 return -EINVAL;
609 }
610
611 vreg->speed_bins_supported = max_speed_bins;
612
613 combo_corners = kcalloc(vreg->fuse_combos_supported,
614 sizeof(*combo_corners), GFP_KERNEL);
615 if (!combo_corners)
616 return -ENOMEM;
617
618 rc = of_property_read_u32_array(node, "qcom,cpr-corners", combo_corners,
619 vreg->fuse_combos_supported);
620 if (rc == -EOVERFLOW) {
621 /* Single value case */
622 rc = of_property_read_u32(node, "qcom,cpr-corners",
623 combo_corners);
624 for (i = 1; i < vreg->fuse_combos_supported; i++)
625 combo_corners[i] = combo_corners[0];
626 }
627 if (rc) {
628 cpr3_err(vreg, "error reading property qcom,cpr-corners, rc=%d\n",
629 rc);
630 kfree(combo_corners);
631 return rc;
632 }
633
634 vreg->fuse_combo_offset = 0;
635 vreg->fuse_combo_corner_sum = 0;
636 for (i = 0; i < vreg->fuse_combos_supported; i++) {
637 vreg->fuse_combo_corner_sum += combo_corners[i];
638 if (i < vreg->fuse_combo)
639 vreg->fuse_combo_offset += combo_corners[i];
640 }
641
642 vreg->corner_count = combo_corners[vreg->fuse_combo];
643
644 kfree(combo_corners);
645
646 vreg->speed_bin_offset = 0;
647 vreg->speed_bin_corner_sum = 0;
648 if (vreg->speed_bins_supported > 0) {
649 speed_bin_corners = kcalloc(vreg->speed_bins_supported,
650 sizeof(*speed_bin_corners), GFP_KERNEL);
651 if (!speed_bin_corners)
652 return -ENOMEM;
653
654 rc = of_property_read_u32_array(node,
655 "qcom,cpr-speed-bin-corners", speed_bin_corners,
656 vreg->speed_bins_supported);
657 if (rc) {
658 cpr3_err(vreg, "error reading property qcom,cpr-speed-bin-corners, rc=%d\n",
659 rc);
660 kfree(speed_bin_corners);
661 return rc;
662 }
663
664 for (i = 0; i < vreg->speed_bins_supported; i++) {
665 vreg->speed_bin_corner_sum += speed_bin_corners[i];
666 if (i < vreg->speed_bin_fuse)
667 vreg->speed_bin_offset += speed_bin_corners[i];
668 }
669
670 if (speed_bin_corners[vreg->speed_bin_fuse]
671 != vreg->corner_count) {
672 cpr3_err(vreg, "qcom,cpr-corners and qcom,cpr-speed-bin-corners conflict on number of corners: %d vs %u\n",
673 vreg->corner_count,
674 speed_bin_corners[vreg->speed_bin_fuse]);
675 kfree(speed_bin_corners);
676 return -EINVAL;
677 }
678
679 kfree(speed_bin_corners);
680 }
681
682 /*
683 * For CPRh compliant controllers two additional corners are
684 * allocated to correspond to the APM crossover voltage and the MEM ACC
685 * crossover voltage.
686 */
687 vreg->corner = devm_kcalloc(ctrl->dev, ctrl->ctrl_type ==
688 CPR_CTRL_TYPE_CPRH ?
689 vreg->corner_count + 2 :
690 vreg->corner_count,
691 sizeof(*vreg->corner), GFP_KERNEL);
692 temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
693 if (!vreg->corner || !temp)
694 return -ENOMEM;
695
696 rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-ceiling",
697 1, temp);
698 if (rc)
699 goto free_temp;
700 for (i = 0; i < vreg->corner_count; i++) {
701 vreg->corner[i].ceiling_volt
702 = CPR3_ROUND(temp[i], ctrl->step_volt);
703 vreg->corner[i].abs_ceiling_volt = vreg->corner[i].ceiling_volt;
704 }
705
706 rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-floor",
707 1, temp);
708 if (rc)
709 goto free_temp;
710 for (i = 0; i < vreg->corner_count; i++)
711 vreg->corner[i].floor_volt
712 = CPR3_ROUND(temp[i], ctrl->step_volt);
713
714 /* Validate ceiling and floor values */
715 for (i = 0; i < vreg->corner_count; i++) {
716 if (vreg->corner[i].floor_volt
717 > vreg->corner[i].ceiling_volt) {
718 cpr3_err(vreg, "CPR floor[%d]=%d > ceiling[%d]=%d uV\n",
719 i, vreg->corner[i].floor_volt,
720 i, vreg->corner[i].ceiling_volt);
721 rc = -EINVAL;
722 goto free_temp;
723 }
724 }
725
726 /* Load optional system-supply voltages */
727 if (of_find_property(vreg->of_node, "qcom,system-voltage", NULL)) {
728 rc = cpr3_parse_corner_array_property(vreg,
729 "qcom,system-voltage", 1, temp);
730 if (rc)
731 goto free_temp;
732 for (i = 0; i < vreg->corner_count; i++)
733 vreg->corner[i].system_volt = temp[i];
734 }
735
736 rc = cpr3_parse_corner_array_property(vreg, "qcom,corner-frequencies",
737 1, temp);
738 if (rc)
739 goto free_temp;
740 for (i = 0; i < vreg->corner_count; i++)
741 vreg->corner[i].proc_freq = temp[i];
742
743 /* Validate frequencies */
744 for (i = 1; i < vreg->corner_count; i++) {
745 if (vreg->corner[i].proc_freq
746 < vreg->corner[i - 1].proc_freq) {
747 cpr3_err(vreg, "invalid frequency: freq[%d]=%u < freq[%d]=%u\n",
748 i, vreg->corner[i].proc_freq, i - 1,
749 vreg->corner[i - 1].proc_freq);
750 rc = -EINVAL;
751 goto free_temp;
752 }
753 }
754
755 vreg->fuse_corner_map = devm_kcalloc(ctrl->dev, vreg->fuse_corner_count,
756 sizeof(*vreg->fuse_corner_map), GFP_KERNEL);
757 if (!vreg->fuse_corner_map) {
758 rc = -ENOMEM;
759 goto free_temp;
760 }
761
762 rc = cpr3_parse_array_property(vreg, "qcom,cpr-corner-fmax-map",
763 vreg->fuse_corner_count, temp);
764 if (rc)
765 goto free_temp;
766 for (i = 0; i < vreg->fuse_corner_count; i++) {
767 vreg->fuse_corner_map[i] = temp[i] - CPR3_CORNER_OFFSET;
768 if (temp[i] < CPR3_CORNER_OFFSET
769 || temp[i] > vreg->corner_count + CPR3_CORNER_OFFSET) {
770 cpr3_err(vreg, "invalid corner value specified in qcom,cpr-corner-fmax-map: %u\n",
771 temp[i]);
772 rc = -EINVAL;
773 goto free_temp;
774 } else if (i > 0 && temp[i - 1] >= temp[i]) {
775 cpr3_err(vreg, "invalid corner %u less than or equal to previous corner %u\n",
776 temp[i], temp[i - 1]);
777 rc = -EINVAL;
778 goto free_temp;
779 }
780 }
781 if (temp[vreg->fuse_corner_count - 1] != vreg->corner_count)
782 cpr3_debug(vreg, "Note: highest Fmax corner %u in qcom,cpr-corner-fmax-map does not match highest supported corner %d\n",
783 temp[vreg->fuse_corner_count - 1],
784 vreg->corner_count);
785
786 for (i = 0; i < vreg->corner_count; i++) {
787 for (j = 0; j < vreg->fuse_corner_count; j++) {
788 if (i + CPR3_CORNER_OFFSET <= temp[j]) {
789 vreg->corner[i].cpr_fuse_corner = j;
790 break;
791 }
792 }
793 if (j == vreg->fuse_corner_count) {
794 /*
795 * Handle the case where the highest fuse corner maps
796 * to a corner below the highest corner.
797 */
798 vreg->corner[i].cpr_fuse_corner
799 = vreg->fuse_corner_count - 1;
800 }
801 }
802
803 if (of_find_property(vreg->of_node,
804 "qcom,allow-aging-voltage-adjustment", NULL)) {
805 rc = cpr3_parse_array_property(vreg,
806 "qcom,allow-aging-voltage-adjustment",
807 1, &aging_allowed);
808 if (rc)
809 goto free_temp;
810
811 vreg->aging_allowed = aging_allowed;
812 }
813
814 if (of_find_property(vreg->of_node,
815 "qcom,allow-aging-open-loop-voltage-adjustment", NULL)) {
816 rc = cpr3_parse_array_property(vreg,
817 "qcom,allow-aging-open-loop-voltage-adjustment",
818 1, &aging_allowed);
819 if (rc)
820 goto free_temp;
821
822 vreg->aging_allow_open_loop_adj = aging_allowed;
823 }
824
825 if (vreg->aging_allowed) {
826 if (ctrl->aging_ref_volt <= 0) {
827 cpr3_err(ctrl, "qcom,cpr-aging-ref-voltage must be specified\n");
828 rc = -EINVAL;
829 goto free_temp;
830 }
831
832 rc = cpr3_parse_array_property(vreg,
833 "qcom,cpr-aging-max-voltage-adjustment",
834 1, &vreg->aging_max_adjust_volt);
835 if (rc)
836 goto free_temp;
837
838 rc = cpr3_parse_array_property(vreg,
839 "qcom,cpr-aging-ref-corner", 1, &vreg->aging_corner);
840 if (rc) {
841 goto free_temp;
842 } else if (vreg->aging_corner < CPR3_CORNER_OFFSET
843 || vreg->aging_corner > vreg->corner_count - 1
844 + CPR3_CORNER_OFFSET) {
845 cpr3_err(vreg, "aging reference corner=%d not in range [%d, %d]\n",
846 vreg->aging_corner, CPR3_CORNER_OFFSET,
847 vreg->corner_count - 1 + CPR3_CORNER_OFFSET);
848 rc = -EINVAL;
849 goto free_temp;
850 }
851 vreg->aging_corner -= CPR3_CORNER_OFFSET;
852
853 if (of_find_property(vreg->of_node, "qcom,cpr-aging-derate",
854 NULL)) {
855 rc = cpr3_parse_corner_array_property(vreg,
856 "qcom,cpr-aging-derate", 1, temp);
857 if (rc)
858 goto free_temp;
859
860 for (i = 0; i < vreg->corner_count; i++)
861 vreg->corner[i].aging_derate = temp[i];
862 } else {
863 for (i = 0; i < vreg->corner_count; i++)
864 vreg->corner[i].aging_derate
865 = CPR3_AGING_DERATE_UNITY;
866 }
867 }
868
869free_temp:
870 kfree(temp);
871 return rc;
872}
873
874/**
875 * cpr3_parse_thread_u32() - parse the specified property from the CPR3 thread's
876 * device tree node and verify that it is within the allowed limits
877 * @thread: Pointer to the CPR3 thread
878 * @propname: The name of the device tree property to read
879 * @out_value: The output pointer to fill with the value read
880 * @value_min: The minimum allowed property value
881 * @value_max: The maximum allowed property value
882 *
883 * This function prints a verbose error message if the property is missing or
884 * has a value which is not within the specified range.
885 *
886 * Return: 0 on success, errno on failure
887 */
888int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname,
889 u32 *out_value, u32 value_min, u32 value_max)
890{
891 int rc;
892
893 rc = of_property_read_u32(thread->of_node, propname, out_value);
894 if (rc) {
895 cpr3_err(thread->ctrl, "thread %u error reading property %s, rc=%d\n",
896 thread->thread_id, propname, rc);
897 return rc;
898 }
899
900 if (*out_value < value_min || *out_value > value_max) {
901 cpr3_err(thread->ctrl, "thread %u %s=%u is invalid; allowed range: [%u, %u]\n",
902 thread->thread_id, propname, *out_value, value_min,
903 value_max);
904 return -EINVAL;
905 }
906
907 return 0;
908}
909
910/**
911 * cpr3_parse_ctrl_u32() - parse the specified property from the CPR3
912 * controller's device tree node and verify that it is within the
913 * allowed limits
914 * @ctrl: Pointer to the CPR3 controller
915 * @propname: The name of the device tree property to read
916 * @out_value: The output pointer to fill with the value read
917 * @value_min: The minimum allowed property value
918 * @value_max: The maximum allowed property value
919 *
920 * This function prints a verbose error message if the property is missing or
921 * has a value which is not within the specified range.
922 *
923 * Return: 0 on success, errno on failure
924 */
925int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname,
926 u32 *out_value, u32 value_min, u32 value_max)
927{
928 int rc;
929
930 rc = of_property_read_u32(ctrl->dev->of_node, propname, out_value);
931 if (rc) {
932 cpr3_err(ctrl, "error reading property %s, rc=%d\n",
933 propname, rc);
934 return rc;
935 }
936
937 if (*out_value < value_min || *out_value > value_max) {
938 cpr3_err(ctrl, "%s=%u is invalid; allowed range: [%u, %u]\n",
939 propname, *out_value, value_min, value_max);
940 return -EINVAL;
941 }
942
943 return 0;
944}
945
946/**
947 * cpr3_parse_common_thread_data() - parse common CPR3 thread properties from
948 * device tree
949 * @thread: Pointer to the CPR3 thread
950 *
951 * Return: 0 on success, errno on failure
952 */
953int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
954{
955 int rc;
956
957 rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-up",
958 &thread->consecutive_up, CPR3_CONSECUTIVE_UP_DOWN_MIN,
959 CPR3_CONSECUTIVE_UP_DOWN_MAX);
960 if (rc)
961 return rc;
962
963 rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-down",
964 &thread->consecutive_down, CPR3_CONSECUTIVE_UP_DOWN_MIN,
965 CPR3_CONSECUTIVE_UP_DOWN_MAX);
966 if (rc)
967 return rc;
968
969 rc = cpr3_parse_thread_u32(thread, "qcom,cpr-up-threshold",
970 &thread->up_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
971 CPR3_UP_DOWN_THRESHOLD_MAX);
972 if (rc)
973 return rc;
974
975 rc = cpr3_parse_thread_u32(thread, "qcom,cpr-down-threshold",
976 &thread->down_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
977 CPR3_UP_DOWN_THRESHOLD_MAX);
978 if (rc)
979 return rc;
980
981 return rc;
982}
983
984/**
985 * cpr3_parse_irq_affinity() - parse CPR IRQ affinity information
986 * @ctrl: Pointer to the CPR3 controller
987 *
988 * Return: 0 on success, errno on failure
989 */
990static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl)
991{
992 struct device_node *cpu_node;
993 int i, cpu;
994 int len = 0;
995
996 if (!of_find_property(ctrl->dev->of_node, "qcom,cpr-interrupt-affinity",
997 &len)) {
998 /* No IRQ affinity required */
999 return 0;
1000 }
1001
1002 len /= sizeof(u32);
1003
1004 for (i = 0; i < len; i++) {
1005 cpu_node = of_parse_phandle(ctrl->dev->of_node,
1006 "qcom,cpr-interrupt-affinity", i);
1007 if (!cpu_node) {
1008 cpr3_err(ctrl, "could not find CPU node %d\n", i);
1009 return -EINVAL;
1010 }
1011
1012 for_each_possible_cpu(cpu) {
1013 if (of_get_cpu_node(cpu, NULL) == cpu_node) {
1014 cpumask_set_cpu(cpu, &ctrl->irq_affinity_mask);
1015 break;
1016 }
1017 }
1018 of_node_put(cpu_node);
1019 }
1020
1021 return 0;
1022}
1023
1024static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl)
1025{
1026 struct device_node *node = ctrl->dev->of_node;
1027 struct cpr3_panic_regs_info *panic_regs_info;
1028 struct cpr3_reg_info *regs;
1029 int i, reg_count, len, rc = 0;
1030
1031 if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) {
1032 /* panic register address list not specified */
1033 return rc;
1034 }
1035
1036 reg_count = len / sizeof(u32);
1037 if (!reg_count) {
1038 cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n",
1039 len);
1040 return -EINVAL;
1041 }
1042
1043 if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) {
1044 cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n");
1045 return -EINVAL;
1046 }
1047
1048 len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list");
1049 if (reg_count != len) {
1050 cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n",
1051 reg_count);
1052 return -EINVAL;
1053 }
1054
1055 panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info),
1056 GFP_KERNEL);
1057 if (!panic_regs_info)
1058 return -ENOMEM;
1059
1060 regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL);
1061 if (!regs)
1062 return -ENOMEM;
1063
1064 for (i = 0; i < reg_count; i++) {
1065 rc = of_property_read_string_index(node,
1066 "qcom,cpr-panic-reg-name-list", i,
1067 &(regs[i].name));
1068 if (rc) {
1069 cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n",
1070 rc);
1071 return rc;
1072 }
1073
1074 rc = of_property_read_u32_index(node,
1075 "qcom,cpr-panic-reg-addr-list", i,
1076 &(regs[i].addr));
1077 if (rc) {
1078 cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n",
1079 rc);
1080 return rc;
1081 }
1082 regs[i].virt_addr = devm_ioremap(ctrl->dev, regs[i].addr, 0x4);
1083 if (!regs[i].virt_addr) {
1084 pr_err("Unable to map panic register addr 0x%08x\n",
1085 regs[i].addr);
1086 return -EINVAL;
1087 }
1088 regs[i].value = 0xFFFFFFFF;
1089 }
1090
1091 panic_regs_info->reg_count = reg_count;
1092 panic_regs_info->regs = regs;
1093 ctrl->panic_regs_info = panic_regs_info;
1094
1095 return rc;
1096}
1097
1098/**
1099 * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from
1100 * device tree
1101 * @ctrl: Pointer to the CPR3 controller
1102 *
1103 * Return: 0 on success, errno on failure
1104 */
1105int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
1106{
1107 int rc;
1108
1109 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-sensor-time",
1110 &ctrl->sensor_time, 0, UINT_MAX);
1111 if (rc)
1112 return rc;
1113
1114 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-loop-time",
1115 &ctrl->loop_time, 0, UINT_MAX);
1116 if (rc)
1117 return rc;
1118
1119 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-idle-cycles",
1120 &ctrl->idle_clocks, CPR3_IDLE_CLOCKS_MIN,
1121 CPR3_IDLE_CLOCKS_MAX);
1122 if (rc)
1123 return rc;
1124
1125 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-min",
1126 &ctrl->step_quot_init_min, CPR3_STEP_QUOT_MIN,
1127 CPR3_STEP_QUOT_MAX);
1128 if (rc)
1129 return rc;
1130
1131 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-max",
1132 &ctrl->step_quot_init_max, CPR3_STEP_QUOT_MIN,
1133 CPR3_STEP_QUOT_MAX);
1134 if (rc)
1135 return rc;
1136
1137 rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step",
1138 &ctrl->step_volt);
1139 if (rc) {
1140 cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n",
1141 rc);
1142 return rc;
1143 }
1144 if (ctrl->step_volt <= 0) {
1145 cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n",
1146 ctrl->step_volt);
1147 return -EINVAL;
1148 }
1149
1150 rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-count-mode",
1151 &ctrl->count_mode, CPR3_COUNT_MODE_ALL_AT_ONCE_MIN,
1152 CPR3_COUNT_MODE_STAGGERED);
1153 if (rc)
1154 return rc;
1155
1156 /* Count repeat is optional */
1157 ctrl->count_repeat = 0;
1158 of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-count-repeat",
1159 &ctrl->count_repeat);
1160
1161 ctrl->cpr_allowed_sw = of_property_read_bool(ctrl->dev->of_node,
1162 "qcom,cpr-enable");
1163
1164 rc = cpr3_parse_irq_affinity(ctrl);
1165 if (rc)
1166 return rc;
1167
David Collins044e9e72017-03-06 16:47:09 -08001168 ctrl->ignore_invalid_fuses = of_property_read_bool(ctrl->dev->of_node,
1169 "qcom,cpr-ignore-invalid-fuses");
1170
David Collins7370f1a2017-01-18 16:21:53 -08001171 /* Aging reference voltage is optional */
1172 ctrl->aging_ref_volt = 0;
1173 of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage",
1174 &ctrl->aging_ref_volt);
1175
1176 /* Aging possible bitmask is optional */
1177 ctrl->aging_possible_mask = 0;
1178 of_property_read_u32(ctrl->dev->of_node,
1179 "qcom,cpr-aging-allowed-reg-mask",
1180 &ctrl->aging_possible_mask);
1181
1182 if (ctrl->aging_possible_mask) {
1183 /*
1184 * Aging possible register value required if bitmask is
1185 * specified
1186 */
1187 rc = cpr3_parse_ctrl_u32(ctrl,
1188 "qcom,cpr-aging-allowed-reg-value",
1189 &ctrl->aging_possible_val, 0, UINT_MAX);
1190 if (rc)
1191 return rc;
1192 }
1193
1194 if (of_find_property(ctrl->dev->of_node, "clock-names", NULL)) {
1195 ctrl->core_clk = devm_clk_get(ctrl->dev, "core_clk");
1196 if (IS_ERR(ctrl->core_clk)) {
1197 rc = PTR_ERR(ctrl->core_clk);
1198 if (rc != -EPROBE_DEFER)
1199 cpr3_err(ctrl, "unable request core clock, rc=%d\n",
1200 rc);
1201 return rc;
1202 }
1203 }
1204
1205 rc = cpr3_panic_notifier_init(ctrl);
1206 if (rc)
1207 return rc;
1208
1209 if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) {
1210 ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd");
1211 if (IS_ERR(ctrl->vdd_regulator)) {
1212 rc = PTR_ERR(ctrl->vdd_regulator);
1213 if (rc != -EPROBE_DEFER)
1214 cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n",
1215 rc);
1216 return rc;
1217 }
1218 } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
1219 /* vdd-supply is optional for CPRh controllers. */
1220 ctrl->vdd_regulator = NULL;
1221 } else {
1222 cpr3_err(ctrl, "vdd supply is not defined\n");
1223 return -ENODEV;
1224 }
1225
1226 /*
1227 * Regulator device handles are not necessary for CPRh controllers
1228 * since communication with the regulators is completely managed
1229 * in hardware.
1230 */
1231 if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH)
1232 return rc;
1233
1234 ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev,
1235 "system");
1236 if (IS_ERR(ctrl->system_regulator)) {
1237 rc = PTR_ERR(ctrl->system_regulator);
1238 if (rc != -EPROBE_DEFER) {
1239 rc = 0;
1240 ctrl->system_regulator = NULL;
1241 } else {
1242 return rc;
1243 }
1244 }
1245
1246 ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev,
1247 "mem-acc");
1248 if (IS_ERR(ctrl->mem_acc_regulator)) {
1249 rc = PTR_ERR(ctrl->mem_acc_regulator);
1250 if (rc != -EPROBE_DEFER) {
1251 rc = 0;
1252 ctrl->mem_acc_regulator = NULL;
1253 } else {
1254 return rc;
1255 }
1256 }
1257
1258 return rc;
1259}
1260
1261/**
1262 * cpr3_limit_open_loop_voltages() - modify the open-loop voltage of each corner
1263 * so that it fits within the floor to ceiling
1264 * voltage range of the corner
1265 * @vreg: Pointer to the CPR3 regulator
1266 *
1267 * This function clips the open-loop voltage for each corner so that it is
1268 * limited to the floor to ceiling range. It also rounds each open-loop voltage
1269 * so that it corresponds to a set point available to the underlying regulator.
1270 *
1271 * Return: 0 on success, errno on failure
1272 */
1273int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg)
1274{
1275 int i, volt;
1276
1277 cpr3_debug(vreg, "open-loop voltages after trimming and rounding:\n");
1278 for (i = 0; i < vreg->corner_count; i++) {
1279 volt = CPR3_ROUND(vreg->corner[i].open_loop_volt,
1280 vreg->thread->ctrl->step_volt);
1281 if (volt < vreg->corner[i].floor_volt)
1282 volt = vreg->corner[i].floor_volt;
1283 else if (volt > vreg->corner[i].ceiling_volt)
1284 volt = vreg->corner[i].ceiling_volt;
1285 vreg->corner[i].open_loop_volt = volt;
1286 cpr3_debug(vreg, "corner[%2d]: open-loop=%d uV\n", i, volt);
1287 }
1288
1289 return 0;
1290}
1291
1292/**
1293 * cpr3_open_loop_voltage_as_ceiling() - configures the ceiling voltage for each
1294 * corner to equal the open-loop voltage if the relevant device
1295 * tree property is found for the CPR3 regulator
1296 * @vreg: Pointer to the CPR3 regulator
1297 *
1298 * This function assumes that the the open-loop voltage for each corner has
1299 * already been rounded to the nearest allowed set point and that it falls
1300 * within the floor to ceiling range.
1301 *
1302 * Return: none
1303 */
1304void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg)
1305{
1306 int i;
1307
1308 if (!of_property_read_bool(vreg->of_node,
1309 "qcom,cpr-scaled-open-loop-voltage-as-ceiling"))
1310 return;
1311
1312 for (i = 0; i < vreg->corner_count; i++)
1313 vreg->corner[i].ceiling_volt
1314 = vreg->corner[i].open_loop_volt;
1315}
1316
1317/**
1318 * cpr3_limit_floor_voltages() - raise the floor voltage of each corner so that
1319 * the optional maximum floor to ceiling voltage range specified in
1320 * device tree is satisfied
1321 * @vreg: Pointer to the CPR3 regulator
1322 *
1323 * This function also ensures that the open-loop voltage for each corner falls
1324 * within the final floor to ceiling voltage range and that floor voltages
1325 * increase monotonically.
1326 *
1327 * Return: 0 on success, errno on failure
1328 */
1329int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg)
1330{
1331 char *prop = "qcom,cpr-floor-to-ceiling-max-range";
1332 int i, floor_new;
1333 u32 *floor_range;
1334 int rc = 0;
1335
1336 if (!of_find_property(vreg->of_node, prop, NULL))
1337 goto enforce_monotonicity;
1338
1339 floor_range = kcalloc(vreg->corner_count, sizeof(*floor_range),
1340 GFP_KERNEL);
1341 if (!floor_range)
1342 return -ENOMEM;
1343
1344 rc = cpr3_parse_corner_array_property(vreg, prop, 1, floor_range);
1345 if (rc)
1346 goto free_floor_adjust;
1347
1348 for (i = 0; i < vreg->corner_count; i++) {
1349 if ((s32)floor_range[i] >= 0) {
1350 floor_new = CPR3_ROUND(vreg->corner[i].ceiling_volt
1351 - floor_range[i],
1352 vreg->thread->ctrl->step_volt);
1353
1354 vreg->corner[i].floor_volt = max(floor_new,
1355 vreg->corner[i].floor_volt);
1356 if (vreg->corner[i].open_loop_volt
1357 < vreg->corner[i].floor_volt)
1358 vreg->corner[i].open_loop_volt
1359 = vreg->corner[i].floor_volt;
1360 }
1361 }
1362
1363free_floor_adjust:
1364 kfree(floor_range);
1365
1366enforce_monotonicity:
1367 /* Ensure that floor voltages increase monotonically. */
1368 for (i = 1; i < vreg->corner_count; i++) {
1369 if (vreg->corner[i].floor_volt
1370 < vreg->corner[i - 1].floor_volt) {
1371 cpr3_debug(vreg, "corner %d floor voltage=%d uV < corner %d voltage=%d uV; overriding: corner %d voltage=%d\n",
1372 i, vreg->corner[i].floor_volt,
1373 i - 1, vreg->corner[i - 1].floor_volt,
1374 i, vreg->corner[i - 1].floor_volt);
1375 vreg->corner[i].floor_volt
1376 = vreg->corner[i - 1].floor_volt;
1377
1378 if (vreg->corner[i].open_loop_volt
1379 < vreg->corner[i].floor_volt)
1380 vreg->corner[i].open_loop_volt
1381 = vreg->corner[i].floor_volt;
1382 if (vreg->corner[i].ceiling_volt
1383 < vreg->corner[i].floor_volt)
1384 vreg->corner[i].ceiling_volt
1385 = vreg->corner[i].floor_volt;
1386 }
1387 }
1388
1389 return rc;
1390}
1391
1392/**
1393 * cpr3_print_quots() - print CPR target quotients into the kernel log for
1394 * debugging purposes
1395 * @vreg: Pointer to the CPR3 regulator
1396 *
1397 * Return: none
1398 */
1399void cpr3_print_quots(struct cpr3_regulator *vreg)
1400{
1401 int i, j, pos;
1402 size_t buflen;
1403 char *buf;
1404
1405 buflen = sizeof(*buf) * CPR3_RO_COUNT * (MAX_CHARS_PER_INT + 2);
1406 buf = kzalloc(buflen, GFP_KERNEL);
1407 if (!buf)
1408 return;
1409
1410 for (i = 0; i < vreg->corner_count; i++) {
1411 for (j = 0, pos = 0; j < CPR3_RO_COUNT; j++)
1412 pos += scnprintf(buf + pos, buflen - pos, " %u",
1413 vreg->corner[i].target_quot[j]);
1414 cpr3_debug(vreg, "target quots[%2d]:%s\n", i, buf);
1415 }
1416
1417 kfree(buf);
1418}
1419
1420/**
1421 * cpr3_adjust_fused_open_loop_voltages() - adjust the fused open-loop voltages
1422 * for each fuse corner according to device tree values
1423 * @vreg: Pointer to the CPR3 regulator
1424 * @fuse_volt: Pointer to an array of the fused open-loop voltage
1425 * values
1426 *
1427 * Voltage values in fuse_volt are modified in place.
1428 *
1429 * Return: 0 on success, errno on failure
1430 */
1431int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
1432 int *fuse_volt)
1433{
1434 int i, rc, prev_volt;
1435 int *volt_adjust;
1436
1437 if (!of_find_property(vreg->of_node,
1438 "qcom,cpr-open-loop-voltage-fuse-adjustment", NULL)) {
1439 /* No adjustment required. */
1440 return 0;
1441 }
1442
1443 volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust),
1444 GFP_KERNEL);
1445 if (!volt_adjust)
1446 return -ENOMEM;
1447
1448 rc = cpr3_parse_array_property(vreg,
1449 "qcom,cpr-open-loop-voltage-fuse-adjustment",
1450 vreg->fuse_corner_count, volt_adjust);
1451 if (rc) {
1452 cpr3_err(vreg, "could not load open-loop fused voltage adjustments, rc=%d\n",
1453 rc);
1454 goto done;
1455 }
1456
1457 for (i = 0; i < vreg->fuse_corner_count; i++) {
1458 if (volt_adjust[i]) {
1459 prev_volt = fuse_volt[i];
1460 fuse_volt[i] += volt_adjust[i];
1461 cpr3_debug(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n",
1462 i, prev_volt, fuse_volt[i]);
1463 }
1464 }
1465
1466done:
1467 kfree(volt_adjust);
1468 return rc;
1469}
1470
1471/**
1472 * cpr3_adjust_open_loop_voltages() - adjust the open-loop voltages for each
1473 * corner according to device tree values
1474 * @vreg: Pointer to the CPR3 regulator
1475 *
1476 * Return: 0 on success, errno on failure
1477 */
1478int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
1479{
1480 int i, rc, prev_volt, min_volt;
1481 int *volt_adjust, *volt_diff;
1482
1483 if (!of_find_property(vreg->of_node,
1484 "qcom,cpr-open-loop-voltage-adjustment", NULL)) {
1485 /* No adjustment required. */
1486 return 0;
1487 }
1488
1489 volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
1490 GFP_KERNEL);
1491 volt_diff = kcalloc(vreg->corner_count, sizeof(*volt_diff), GFP_KERNEL);
1492 if (!volt_adjust || !volt_diff) {
1493 rc = -ENOMEM;
1494 goto done;
1495 }
1496
1497 rc = cpr3_parse_corner_array_property(vreg,
1498 "qcom,cpr-open-loop-voltage-adjustment", 1, volt_adjust);
1499 if (rc) {
1500 cpr3_err(vreg, "could not load open-loop voltage adjustments, rc=%d\n",
1501 rc);
1502 goto done;
1503 }
1504
1505 for (i = 0; i < vreg->corner_count; i++) {
1506 if (volt_adjust[i]) {
1507 prev_volt = vreg->corner[i].open_loop_volt;
1508 vreg->corner[i].open_loop_volt += volt_adjust[i];
1509 cpr3_debug(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n",
1510 i, prev_volt, vreg->corner[i].open_loop_volt);
1511 }
1512 }
1513
1514 if (of_find_property(vreg->of_node,
1515 "qcom,cpr-open-loop-voltage-min-diff", NULL)) {
1516 rc = cpr3_parse_corner_array_property(vreg,
1517 "qcom,cpr-open-loop-voltage-min-diff", 1, volt_diff);
1518 if (rc) {
1519 cpr3_err(vreg, "could not load minimum open-loop voltage differences, rc=%d\n",
1520 rc);
1521 goto done;
1522 }
1523 }
1524
1525 /*
1526 * Ensure that open-loop voltages increase monotonically with respect
1527 * to configurable minimum allowed differences.
1528 */
1529 for (i = 1; i < vreg->corner_count; i++) {
1530 min_volt = vreg->corner[i - 1].open_loop_volt + volt_diff[i];
1531 if (vreg->corner[i].open_loop_volt < min_volt) {
1532 cpr3_debug(vreg, "adjusted corner %d open-loop voltage=%d uV < corner %d voltage=%d uV + min diff=%d uV; overriding: corner %d voltage=%d\n",
1533 i, vreg->corner[i].open_loop_volt,
1534 i - 1, vreg->corner[i - 1].open_loop_volt,
1535 volt_diff[i], i, min_volt);
1536 vreg->corner[i].open_loop_volt = min_volt;
1537 }
1538 }
1539
1540done:
1541 kfree(volt_diff);
1542 kfree(volt_adjust);
1543 return rc;
1544}
1545
1546/**
1547 * cpr3_quot_adjustment() - returns the quotient adjustment value resulting from
1548 * the specified voltage adjustment and RO scaling factor
1549 * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
1550 * of QUOT/V
1551 * @volt_adjust: The amount to adjust the voltage by in units of
1552 * microvolts. This value may be positive or negative.
1553 */
1554int cpr3_quot_adjustment(int ro_scale, int volt_adjust)
1555{
1556 unsigned long long temp;
1557 int quot_adjust;
1558 int sign = 1;
1559
1560 if (ro_scale < 0) {
1561 sign = -sign;
1562 ro_scale = -ro_scale;
1563 }
1564
1565 if (volt_adjust < 0) {
1566 sign = -sign;
1567 volt_adjust = -volt_adjust;
1568 }
1569
1570 temp = (unsigned long long)ro_scale * (unsigned long long)volt_adjust;
1571 do_div(temp, 1000000);
1572
1573 quot_adjust = temp;
1574 quot_adjust *= sign;
1575
1576 return quot_adjust;
1577}
1578
1579/**
1580 * cpr3_voltage_adjustment() - returns the voltage adjustment value resulting
1581 * from the specified quotient adjustment and RO scaling factor
1582 * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
1583 * of QUOT/V
1584 * @quot_adjust: The amount to adjust the quotient by in units of
1585 * QUOT. This value may be positive or negative.
1586 */
1587int cpr3_voltage_adjustment(int ro_scale, int quot_adjust)
1588{
1589 unsigned long long temp;
1590 int volt_adjust;
1591 int sign = 1;
1592
1593 if (ro_scale < 0) {
1594 sign = -sign;
1595 ro_scale = -ro_scale;
1596 }
1597
1598 if (quot_adjust < 0) {
1599 sign = -sign;
1600 quot_adjust = -quot_adjust;
1601 }
1602
1603 if (ro_scale == 0)
1604 return 0;
1605
1606 temp = (unsigned long long)quot_adjust * 1000000;
1607 do_div(temp, ro_scale);
1608
1609 volt_adjust = temp;
1610 volt_adjust *= sign;
1611
1612 return volt_adjust;
1613}
1614
1615/**
1616 * cpr3_parse_closed_loop_voltage_adjustments() - load per-fuse-corner and
1617 * per-corner closed-loop adjustment values from device tree
1618 * @vreg: Pointer to the CPR3 regulator
1619 * @ro_sel: Array of ring oscillator values selected for each
1620 * fuse corner
1621 * @volt_adjust: Pointer to array which will be filled with the
1622 * per-corner closed-loop adjustment voltages
1623 * @volt_adjust_fuse: Pointer to array which will be filled with the
1624 * per-fuse-corner closed-loop adjustment voltages
1625 * @ro_scale: Pointer to array which will be filled with the
1626 * per-fuse-corner RO scaling factor values with units of
1627 * QUOT/V
1628 *
1629 * Return: 0 on success, errno on failure
1630 */
1631int cpr3_parse_closed_loop_voltage_adjustments(
1632 struct cpr3_regulator *vreg, u64 *ro_sel,
1633 int *volt_adjust, int *volt_adjust_fuse, int *ro_scale)
1634{
1635 int i, rc;
1636 u32 *ro_all_scale;
1637
1638 if (!of_find_property(vreg->of_node,
1639 "qcom,cpr-closed-loop-voltage-adjustment", NULL)
1640 && !of_find_property(vreg->of_node,
1641 "qcom,cpr-closed-loop-voltage-fuse-adjustment", NULL)
1642 && !vreg->aging_allowed) {
1643 /* No adjustment required. */
1644 return 0;
1645 } else if (!of_find_property(vreg->of_node,
1646 "qcom,cpr-ro-scaling-factor", NULL)) {
1647 cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
1648 return -EINVAL;
1649 }
1650
1651 ro_all_scale = kcalloc(vreg->fuse_corner_count * CPR3_RO_COUNT,
1652 sizeof(*ro_all_scale), GFP_KERNEL);
1653 if (!ro_all_scale)
1654 return -ENOMEM;
1655
1656 rc = cpr3_parse_array_property(vreg, "qcom,cpr-ro-scaling-factor",
1657 vreg->fuse_corner_count * CPR3_RO_COUNT, ro_all_scale);
1658 if (rc) {
1659 cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
1660 rc);
1661 goto done;
1662 }
1663
1664 for (i = 0; i < vreg->fuse_corner_count; i++)
1665 ro_scale[i] = ro_all_scale[i * CPR3_RO_COUNT + ro_sel[i]];
1666
1667 for (i = 0; i < vreg->corner_count; i++)
1668 memcpy(vreg->corner[i].ro_scale,
1669 &ro_all_scale[vreg->corner[i].cpr_fuse_corner * CPR3_RO_COUNT],
1670 sizeof(*ro_all_scale) * CPR3_RO_COUNT);
1671
1672 if (of_find_property(vreg->of_node,
1673 "qcom,cpr-closed-loop-voltage-fuse-adjustment", NULL)) {
1674 rc = cpr3_parse_array_property(vreg,
1675 "qcom,cpr-closed-loop-voltage-fuse-adjustment",
1676 vreg->fuse_corner_count, volt_adjust_fuse);
1677 if (rc) {
1678 cpr3_err(vreg, "could not load closed-loop fused voltage adjustments, rc=%d\n",
1679 rc);
1680 goto done;
1681 }
1682 }
1683
1684 if (of_find_property(vreg->of_node,
1685 "qcom,cpr-closed-loop-voltage-adjustment", NULL)) {
1686 rc = cpr3_parse_corner_array_property(vreg,
1687 "qcom,cpr-closed-loop-voltage-adjustment",
1688 1, volt_adjust);
1689 if (rc) {
1690 cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
1691 rc);
1692 goto done;
1693 }
1694 }
1695
1696done:
1697 kfree(ro_all_scale);
1698 return rc;
1699}
1700
1701/**
1702 * cpr3_apm_init() - initialize APM data for a CPR3 controller
1703 * @ctrl: Pointer to the CPR3 controller
1704 *
1705 * This function loads memory array power mux (APM) data from device tree
1706 * if it is present and requests a handle to the appropriate APM controller
1707 * device.
1708 *
1709 * Return: 0 on success, errno on failure
1710 */
1711int cpr3_apm_init(struct cpr3_controller *ctrl)
1712{
1713 struct device_node *node = ctrl->dev->of_node;
1714 int rc;
1715
1716 if (!of_find_property(node, "qcom,apm-ctrl", NULL)) {
1717 /* No APM used */
1718 return 0;
1719 }
1720
1721 ctrl->apm = msm_apm_ctrl_dev_get(ctrl->dev);
1722 if (IS_ERR(ctrl->apm)) {
1723 rc = PTR_ERR(ctrl->apm);
1724 if (rc != -EPROBE_DEFER)
1725 cpr3_err(ctrl, "APM get failed, rc=%d\n", rc);
1726 return rc;
1727 }
1728
1729 rc = of_property_read_u32(node, "qcom,apm-threshold-voltage",
1730 &ctrl->apm_threshold_volt);
1731 if (rc) {
1732 cpr3_err(ctrl, "error reading qcom,apm-threshold-voltage, rc=%d\n",
1733 rc);
1734 return rc;
1735 }
1736 ctrl->apm_threshold_volt
1737 = CPR3_ROUND(ctrl->apm_threshold_volt, ctrl->step_volt);
1738
1739 /* No error check since this is an optional property. */
1740 of_property_read_u32(node, "qcom,apm-hysteresis-voltage",
1741 &ctrl->apm_adj_volt);
1742 ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
1743
1744 ctrl->apm_high_supply = MSM_APM_SUPPLY_APCC;
1745 ctrl->apm_low_supply = MSM_APM_SUPPLY_MX;
1746
1747 return 0;
1748}
1749
1750/**
1751 * cpr3_mem_acc_init() - initialize mem-acc regulator data for
1752 * a CPR3 regulator
1753 * @ctrl: Pointer to the CPR3 controller
1754 *
1755 * Return: 0 on success, errno on failure
1756 */
1757int cpr3_mem_acc_init(struct cpr3_regulator *vreg)
1758{
1759 struct cpr3_controller *ctrl = vreg->thread->ctrl;
1760 u32 *temp;
1761 int i, rc;
1762
1763 if (!ctrl->mem_acc_regulator) {
1764 cpr3_info(ctrl, "not using memory accelerator regulator\n");
1765 return 0;
1766 }
1767
1768 temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
1769 if (!temp)
1770 return -ENOMEM;
1771
1772 rc = cpr3_parse_corner_array_property(vreg, "qcom,mem-acc-voltage",
1773 1, temp);
1774 if (rc) {
1775 cpr3_err(ctrl, "could not load mem-acc corners, rc=%d\n", rc);
1776 } else {
1777 for (i = 0; i < vreg->corner_count; i++)
1778 vreg->corner[i].mem_acc_volt = temp[i];
1779 }
1780
1781 kfree(temp);
1782 return rc;
1783}
1784
1785/**
1786 * cpr4_load_core_and_temp_adj() - parse amount of voltage adjustment for
1787 * per-online-core and per-temperature voltage adjustment for a
1788 * given corner or corner band from device tree.
1789 * @vreg: Pointer to the CPR3 regulator
1790 * @num: Corner number or corner band number
1791 * @use_corner_band: Boolean indicating if the CPR3 regulator supports
1792 * adjustments per corner band
1793 *
1794 * Return: 0 on success, errno on failure
1795 */
1796static int cpr4_load_core_and_temp_adj(struct cpr3_regulator *vreg,
1797 int num, bool use_corner_band)
1798{
1799 struct cpr3_controller *ctrl = vreg->thread->ctrl;
1800 struct cpr4_sdelta *sdelta;
1801 int sdelta_size, i, j, pos, rc = 0;
1802 char str[75];
1803 size_t buflen;
1804 char *buf;
1805
1806 sdelta = use_corner_band ? vreg->corner_band[num].sdelta :
1807 vreg->corner[num].sdelta;
1808
1809 if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj) {
1810 /* corner doesn't need sdelta table */
1811 sdelta->max_core_count = 0;
1812 sdelta->temp_band_count = 0;
1813 return rc;
1814 }
1815
1816 sdelta_size = sdelta->max_core_count * sdelta->temp_band_count;
1817 snprintf(str, sizeof(str), use_corner_band ?
1818 "corner_band=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n"
1819 : "corner=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n",
1820 num, sdelta->max_core_count,
1821 sdelta->temp_band_count, sdelta_size);
1822
1823 cpr3_debug(vreg, "%s", str);
1824
1825 sdelta->table = devm_kcalloc(ctrl->dev, sdelta_size,
1826 sizeof(*sdelta->table), GFP_KERNEL);
1827 if (!sdelta->table)
1828 return -ENOMEM;
1829
1830 snprintf(str, sizeof(str), use_corner_band ?
1831 "qcom,cpr-corner-band%d-temp-core-voltage-adjustment" :
1832 "qcom,cpr-corner%d-temp-core-voltage-adjustment",
1833 num + CPR3_CORNER_OFFSET);
1834
1835 rc = cpr3_parse_array_property(vreg, str, sdelta_size,
1836 sdelta->table);
1837 if (rc) {
1838 cpr3_err(vreg, "could not load %s, rc=%d\n", str, rc);
1839 return rc;
1840 }
1841
1842 /*
1843 * Convert sdelta margins from uV to PMIC steps and apply negation to
1844 * follow the SDELTA register semantics.
1845 */
1846 for (i = 0; i < sdelta_size; i++)
1847 sdelta->table[i] = -(sdelta->table[i] / ctrl->step_volt);
1848
1849 buflen = sizeof(*buf) * sdelta_size * (MAX_CHARS_PER_INT + 2);
1850 buf = kzalloc(buflen, GFP_KERNEL);
1851 if (!buf)
1852 return rc;
1853
1854 for (i = 0; i < sdelta->max_core_count; i++) {
1855 for (j = 0, pos = 0; j < sdelta->temp_band_count; j++)
1856 pos += scnprintf(buf + pos, buflen - pos, " %u",
1857 sdelta->table[i * sdelta->temp_band_count + j]);
1858 cpr3_debug(vreg, "sdelta[%d]:%s\n", i, buf);
1859 }
1860
1861 kfree(buf);
1862 return rc;
1863}
1864
1865/**
1866 * cpr4_parse_core_count_temp_voltage_adj() - parse configuration data for
1867 * per-online-core and per-temperature voltage adjustment for
1868 * a CPR3 regulator from device tree.
1869 * @vreg: Pointer to the CPR3 regulator
1870 * @use_corner_band: Boolean indicating if the CPR3 regulator supports
1871 * adjustments per corner band
1872 *
1873 * This function supports parsing of per-online-core and per-temperature
1874 * adjustments per corner or per corner band. CPR controllers which support
1875 * corner bands apply the same adjustments to all corners within a corner band.
1876 *
1877 * Return: 0 on success, errno on failure
1878 */
1879int cpr4_parse_core_count_temp_voltage_adj(
1880 struct cpr3_regulator *vreg, bool use_corner_band)
1881{
1882 struct cpr3_controller *ctrl = vreg->thread->ctrl;
1883 struct device_node *node = vreg->of_node;
1884 struct cpr3_corner *corner;
1885 struct cpr4_sdelta *sdelta;
1886 int i, sdelta_table_count, rc = 0;
1887 int *allow_core_count_adj = NULL, *allow_temp_adj = NULL;
1888 char prop_str[75];
1889
1890 if (of_find_property(node, use_corner_band ?
1891 "qcom,corner-band-allow-temp-adjustment"
1892 : "qcom,corner-allow-temp-adjustment", NULL)) {
1893 if (!ctrl->allow_temp_adj) {
1894 cpr3_err(ctrl, "Temperature adjustment configurations missing\n");
1895 return -EINVAL;
1896 }
1897
1898 vreg->allow_temp_adj = true;
1899 }
1900
1901 if (of_find_property(node, use_corner_band ?
1902 "qcom,corner-band-allow-core-count-adjustment"
1903 : "qcom,corner-allow-core-count-adjustment",
1904 NULL)) {
1905 rc = of_property_read_u32(node, "qcom,max-core-count",
1906 &vreg->max_core_count);
1907 if (rc) {
1908 cpr3_err(vreg, "error reading qcom,max-core-count, rc=%d\n",
1909 rc);
1910 return -EINVAL;
1911 }
1912
1913 vreg->allow_core_count_adj = true;
1914 ctrl->allow_core_count_adj = true;
1915 }
1916
1917 if (!vreg->allow_temp_adj && !vreg->allow_core_count_adj) {
1918 /*
1919 * Both per-online-core and temperature based adjustments are
1920 * disabled for this regulator.
1921 */
1922 return 0;
1923 } else if (!vreg->allow_core_count_adj) {
1924 /*
1925 * Only per-temperature voltage adjusments are allowed.
1926 * Keep max core count value as 1 to allocate SDELTA.
1927 */
1928 vreg->max_core_count = 1;
1929 }
1930
1931 if (vreg->allow_core_count_adj) {
1932 allow_core_count_adj = kcalloc(vreg->corner_count,
1933 sizeof(*allow_core_count_adj),
1934 GFP_KERNEL);
1935 if (!allow_core_count_adj)
1936 return -ENOMEM;
1937
1938 snprintf(prop_str, sizeof(prop_str), use_corner_band ?
1939 "qcom,corner-band-allow-core-count-adjustment" :
1940 "qcom,corner-allow-core-count-adjustment");
1941
1942 rc = use_corner_band ?
1943 cpr3_parse_corner_band_array_property(vreg, prop_str,
1944 1, allow_core_count_adj) :
1945 cpr3_parse_corner_array_property(vreg, prop_str,
1946 1, allow_core_count_adj);
1947 if (rc) {
1948 cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
1949 rc);
1950 goto done;
1951 }
1952 }
1953
1954 if (vreg->allow_temp_adj) {
1955 allow_temp_adj = kcalloc(vreg->corner_count,
1956 sizeof(*allow_temp_adj), GFP_KERNEL);
1957 if (!allow_temp_adj) {
1958 rc = -ENOMEM;
1959 goto done;
1960 }
1961
1962 snprintf(prop_str, sizeof(prop_str), use_corner_band ?
1963 "qcom,corner-band-allow-temp-adjustment" :
1964 "qcom,corner-allow-temp-adjustment");
1965
1966 rc = use_corner_band ?
1967 cpr3_parse_corner_band_array_property(vreg, prop_str,
1968 1, allow_temp_adj) :
1969 cpr3_parse_corner_array_property(vreg, prop_str,
1970 1, allow_temp_adj);
1971 if (rc) {
1972 cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
1973 rc);
1974 goto done;
1975 }
1976 }
1977
1978 sdelta_table_count = use_corner_band ? vreg->corner_band_count :
1979 vreg->corner_count;
1980
1981 for (i = 0; i < sdelta_table_count; i++) {
1982 sdelta = devm_kzalloc(ctrl->dev, sizeof(*corner->sdelta),
1983 GFP_KERNEL);
1984 if (!sdelta) {
1985 rc = -ENOMEM;
1986 goto done;
1987 }
1988
1989 if (allow_core_count_adj)
1990 sdelta->allow_core_count_adj = allow_core_count_adj[i];
1991 if (allow_temp_adj)
1992 sdelta->allow_temp_adj = allow_temp_adj[i];
1993 sdelta->max_core_count = vreg->max_core_count;
1994 sdelta->temp_band_count = ctrl->temp_band_count;
1995
1996 if (use_corner_band)
1997 vreg->corner_band[i].sdelta = sdelta;
1998 else
1999 vreg->corner[i].sdelta = sdelta;
2000
2001 rc = cpr4_load_core_and_temp_adj(vreg, i, use_corner_band);
2002 if (rc) {
2003 cpr3_err(vreg, "corner/band %d core and temp adjustment loading failed, rc=%d\n",
2004 i, rc);
2005 goto done;
2006 }
2007 }
2008
2009done:
2010 kfree(allow_core_count_adj);
2011 kfree(allow_temp_adj);
2012
2013 return rc;
2014}
2015
2016/**
2017 * cprh_adjust_voltages_for_apm() - adjust per-corner floor and ceiling voltages
2018 * so that they do not overlap the APM threshold voltage.
2019 * @vreg: Pointer to the CPR3 regulator
2020 *
2021 * The memory array power mux (APM) must be configured for a specific supply
2022 * based upon where the VDD voltage lies with respect to the APM threshold
2023 * voltage. When using CPR hardware closed-loop, the voltage may vary anywhere
2024 * between the floor and ceiling voltage without software notification.
2025 * Therefore, it is required that the floor to ceiling range for every corner
2026 * not intersect the APM threshold voltage. This function adjusts the floor to
2027 * ceiling range for each corner which violates this requirement.
2028 *
2029 * The following algorithm is applied:
2030 * if floor < threshold <= ceiling:
2031 * if open_loop >= threshold, then floor = threshold - adj
2032 * else ceiling = threshold - step
2033 * where:
2034 * adj = APM hysteresis voltage established to minimize the number of
2035 * corners with artificially increased floor voltages
2036 * step = voltage in microvolts of a single step of the VDD supply
2037 *
2038 * The open-loop voltage is also bounded by the new floor or ceiling value as
2039 * needed.
2040 *
2041 * Return: none
2042 */
2043void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg)
2044{
2045 struct cpr3_controller *ctrl = vreg->thread->ctrl;
2046 struct cpr3_corner *corner;
2047 int i, adj, threshold, prev_ceiling, prev_floor, prev_open_loop;
2048
2049 if (!ctrl->apm_threshold_volt) {
2050 /* APM not being used. */
2051 return;
2052 }
2053
2054 ctrl->apm_threshold_volt = CPR3_ROUND(ctrl->apm_threshold_volt,
2055 ctrl->step_volt);
2056 ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
2057
2058 threshold = ctrl->apm_threshold_volt;
2059 adj = ctrl->apm_adj_volt;
2060
2061 for (i = 0; i < vreg->corner_count; i++) {
2062 corner = &vreg->corner[i];
2063
2064 if (threshold <= corner->floor_volt
2065 || threshold > corner->ceiling_volt)
2066 continue;
2067
2068 prev_floor = corner->floor_volt;
2069 prev_ceiling = corner->ceiling_volt;
2070 prev_open_loop = corner->open_loop_volt;
2071
2072 if (corner->open_loop_volt >= threshold) {
2073 corner->floor_volt = max(corner->floor_volt,
2074 threshold - adj);
2075 if (corner->open_loop_volt < corner->floor_volt)
2076 corner->open_loop_volt = corner->floor_volt;
2077 } else {
2078 corner->ceiling_volt = threshold - ctrl->step_volt;
2079 }
2080
2081 if (corner->floor_volt != prev_floor
2082 || corner->ceiling_volt != prev_ceiling
2083 || corner->open_loop_volt != prev_open_loop)
2084 cpr3_debug(vreg, "APM threshold=%d, APM adj=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n",
2085 threshold, adj, i, prev_floor, prev_ceiling,
2086 prev_open_loop, corner->floor_volt,
2087 corner->ceiling_volt, corner->open_loop_volt);
2088 }
2089}
2090
2091/**
2092 * cprh_adjust_voltages_for_mem_acc() - adjust per-corner floor and ceiling
2093 * voltages so that they do not intersect the MEM ACC threshold
2094 * voltage
2095 * @vreg: Pointer to the CPR3 regulator
2096 *
2097 * The following algorithm is applied:
2098 * if floor < threshold <= ceiling:
2099 * if open_loop >= threshold, then floor = threshold
2100 * else ceiling = threshold - step
2101 * where:
2102 * step = voltage in microvolts of a single step of the VDD supply
2103 *
2104 * The open-loop voltage is also bounded by the new floor or ceiling value as
2105 * needed.
2106 *
2107 * Return: none
2108 */
2109void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
2110{
2111 struct cpr3_controller *ctrl = vreg->thread->ctrl;
2112 struct cpr3_corner *corner;
2113 int i, threshold, prev_ceiling, prev_floor, prev_open_loop;
2114
2115 if (!ctrl->mem_acc_threshold_volt) {
2116 /* MEM ACC not being used. */
2117 return;
2118 }
2119
2120 ctrl->mem_acc_threshold_volt = CPR3_ROUND(ctrl->mem_acc_threshold_volt,
2121 ctrl->step_volt);
2122
2123 threshold = ctrl->mem_acc_threshold_volt;
2124
2125 for (i = 0; i < vreg->corner_count; i++) {
2126 corner = &vreg->corner[i];
2127
2128 if (threshold <= corner->floor_volt
2129 || threshold > corner->ceiling_volt)
2130 continue;
2131
2132 prev_floor = corner->floor_volt;
2133 prev_ceiling = corner->ceiling_volt;
2134 prev_open_loop = corner->open_loop_volt;
2135
2136 if (corner->open_loop_volt >= threshold) {
2137 corner->floor_volt = max(corner->floor_volt, threshold);
2138 if (corner->open_loop_volt < corner->floor_volt)
2139 corner->open_loop_volt = corner->floor_volt;
2140 } else {
2141 corner->ceiling_volt = threshold - ctrl->step_volt;
2142 }
2143
2144 if (corner->floor_volt != prev_floor
2145 || corner->ceiling_volt != prev_ceiling
2146 || corner->open_loop_volt != prev_open_loop)
2147 cpr3_debug(vreg, "MEM ACC threshold=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n",
2148 threshold, i, prev_floor, prev_ceiling,
2149 prev_open_loop, corner->floor_volt,
2150 corner->ceiling_volt, corner->open_loop_volt);
2151 }
2152}
2153
2154/**
2155 * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage
2156 * adjustments by the amounts that are needed for this
2157 * fuse combo
2158 * @vreg: Pointer to the CPR3 regulator
2159 * @volt_adjust: Array of closed-loop voltage adjustment values of length
2160 * vreg->corner_count which is further adjusted based upon
2161 * offset voltage fuse values.
2162 * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
2163 * vreg->fuse_corner_count.
2164 *
2165 * Return: 0 on success, errno on failure
2166 */
2167static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg,
2168 int *volt_adjust, int *fuse_volt_adjust)
2169{
2170 u32 *corner_map;
2171 int rc = 0, i;
2172
2173 if (!of_find_property(vreg->of_node,
2174 "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
2175 /* No closed-loop offset required. */
2176 return 0;
2177 }
2178
2179 corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
2180 GFP_KERNEL);
2181 if (!corner_map)
2182 return -ENOMEM;
2183
2184 rc = cpr3_parse_corner_array_property(vreg,
2185 "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
2186 1, corner_map);
2187 if (rc)
2188 goto done;
2189
2190 for (i = 0; i < vreg->corner_count; i++) {
2191 if (corner_map[i] == 0) {
2192 continue;
2193 } else if (corner_map[i] > vreg->fuse_corner_count) {
2194 cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
2195 i, corner_map[i]);
2196 rc = -EINVAL;
2197 goto done;
2198 }
2199
2200 volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1];
2201 }
2202
2203done:
2204 kfree(corner_map);
2205 return rc;
2206}
2207
2208/**
2209 * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients
2210 * increase monotonically from lower to higher corners
2211 * @vreg: Pointer to the CPR3 regulator
2212 *
2213 * Return: 0 on success, errno on failure
2214 */
2215static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg)
2216{
2217 int i, j;
2218
2219 for (i = 1; i < vreg->corner_count; i++) {
2220 for (j = 0; j < CPR3_RO_COUNT; j++) {
2221 if (vreg->corner[i].target_quot[j]
2222 && vreg->corner[i].target_quot[j]
2223 < vreg->corner[i - 1].target_quot[j]) {
2224 cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
2225 i, j,
2226 vreg->corner[i].target_quot[j],
2227 i - 1, j,
2228 vreg->corner[i - 1].target_quot[j],
2229 i, j,
2230 vreg->corner[i - 1].target_quot[j]);
2231 vreg->corner[i].target_quot[j]
2232 = vreg->corner[i - 1].target_quot[j];
2233 }
2234 }
2235 }
2236}
2237
2238/**
2239 * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients
2240 * decrease monotonically from higher to lower corners
2241 * @vreg: Pointer to the CPR3 regulator
2242 *
2243 * Return: 0 on success, errno on failure
2244 */
2245static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg)
2246{
2247 int i, j;
2248
2249 for (i = vreg->corner_count - 2; i >= 0; i--) {
2250 for (j = 0; j < CPR3_RO_COUNT; j++) {
2251 if (vreg->corner[i + 1].target_quot[j]
2252 && vreg->corner[i].target_quot[j]
2253 > vreg->corner[i + 1].target_quot[j]) {
2254 cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
2255 i, j,
2256 vreg->corner[i].target_quot[j],
2257 i + 1, j,
2258 vreg->corner[i + 1].target_quot[j],
2259 i, j,
2260 vreg->corner[i + 1].target_quot[j]);
2261 vreg->corner[i].target_quot[j]
2262 = vreg->corner[i + 1].target_quot[j];
2263 }
2264 }
2265 }
2266}
2267
2268/**
2269 * _cpr3_adjust_target_quotients() - adjust the target quotients for each
2270 * corner of the regulator according to input adjustment and
2271 * scaling arrays
2272 * @vreg: Pointer to the CPR3 regulator
2273 * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
2274 * with units of microvolts. The array must have
2275 * vreg->corner_count number of elements.
2276 * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
2277 * The array must have an inner dimension of CPR3_RO_COUNT
2278 * and an outer dimension of vreg->corner_count
2279 * @label: Null terminated string providing a label for the type
2280 * of adjustment.
2281 *
2282 * Return: true if any corners received a positive voltage adjustment (> 0),
2283 * else false
2284 */
2285static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
2286 const int *volt_adjust, const int *ro_scale, const char *label)
2287{
2288 int i, j, quot_adjust;
2289 bool is_increasing = false;
2290 u32 prev_quot;
2291
2292 for (i = 0; i < vreg->corner_count; i++) {
2293 for (j = 0; j < CPR3_RO_COUNT; j++) {
2294 if (vreg->corner[i].target_quot[j]) {
2295 quot_adjust = cpr3_quot_adjustment(
2296 ro_scale[i * CPR3_RO_COUNT + j],
2297 volt_adjust[i]);
2298 if (quot_adjust) {
2299 prev_quot = vreg->corner[i].
2300 target_quot[j];
2301 vreg->corner[i].target_quot[j]
2302 += quot_adjust;
2303 cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
2304 i, j, label, prev_quot,
2305 vreg->corner[i].target_quot[j],
2306 volt_adjust[i]);
2307 }
2308 }
2309 }
2310 if (volt_adjust[i] > 0)
2311 is_increasing = true;
2312 }
2313
2314 return is_increasing;
2315}
2316
2317/**
2318 * cpr3_adjust_target_quotients() - adjust the target quotients for each
2319 * corner according to device tree values and fuse values
2320 * @vreg: Pointer to the CPR3 regulator
2321 * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
2322 * vreg->fuse_corner_count. This parameter could be null
2323 * pointer when no fused adjustments are needed.
2324 *
2325 * Return: 0 on success, errno on failure
2326 */
2327int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
2328 int *fuse_volt_adjust)
2329{
2330 int i, rc;
2331 int *volt_adjust, *ro_scale;
2332 bool explicit_adjustment, fused_adjustment, is_increasing;
2333
2334 explicit_adjustment = of_find_property(vreg->of_node,
2335 "qcom,cpr-closed-loop-voltage-adjustment", NULL);
2336 fused_adjustment = of_find_property(vreg->of_node,
2337 "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
2338
2339 if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
2340 /* No adjustment required. */
2341 return 0;
2342 } else if (!of_find_property(vreg->of_node,
2343 "qcom,cpr-ro-scaling-factor", NULL)) {
2344 cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
2345 return -EINVAL;
2346 }
2347
2348 volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
2349 GFP_KERNEL);
2350 ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
2351 sizeof(*ro_scale), GFP_KERNEL);
2352 if (!volt_adjust || !ro_scale) {
2353 rc = -ENOMEM;
2354 goto done;
2355 }
2356
2357 rc = cpr3_parse_corner_array_property(vreg,
2358 "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
2359 if (rc) {
2360 cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
2361 rc);
2362 goto done;
2363 }
2364
2365 for (i = 0; i < vreg->corner_count; i++)
2366 memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
2367 sizeof(*ro_scale) * CPR3_RO_COUNT);
2368
2369 if (explicit_adjustment) {
2370 rc = cpr3_parse_corner_array_property(vreg,
2371 "qcom,cpr-closed-loop-voltage-adjustment",
2372 1, volt_adjust);
2373 if (rc) {
2374 cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
2375 rc);
2376 goto done;
2377 }
2378
2379 _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale,
2380 "from DT");
2381 cpr3_enforce_inc_quotient_monotonicity(vreg);
2382 }
2383
2384 if (fused_adjustment && fuse_volt_adjust) {
2385 memset(volt_adjust, 0,
2386 sizeof(*volt_adjust) * vreg->corner_count);
2387
2388 rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust,
2389 fuse_volt_adjust);
2390 if (rc) {
2391 cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
2392 rc);
2393 goto done;
2394 }
2395
2396 is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust,
2397 ro_scale, "from fuse");
2398 if (is_increasing)
2399 cpr3_enforce_inc_quotient_monotonicity(vreg);
2400 else
2401 cpr3_enforce_dec_quotient_monotonicity(vreg);
2402 }
2403
2404done:
2405 kfree(volt_adjust);
2406 kfree(ro_scale);
2407 return rc;
2408}