ipq807x: add Qualcomm Atheros IPQ807x target
[openwrt/staging/nbd.git] / target / linux / ipq807x / patches-5.15 / 0901-regulator-add-Qualcomm-CPR-regulators.patch
1 From 303fb163bb86f04432c93325ff8b9638c9e50641 Mon Sep 17 00:00:00 2001
2 From: Robert Marko <robimarko@gmail.com>
3 Date: Mon, 11 Apr 2022 14:35:36 +0200
4 Subject: [PATCH] regulator: add Qualcomm CPR regulators
5
6 Add Qualcomm CPR driver, which allows using the CPR HW to calculate the
7 correct OPP point voltage dynamically based on the system load.
8
9 Signed-off-by: Robert Marko <robimarko@gmail.com>
10 ---
11 drivers/regulator/Kconfig | 33 +
12 drivers/regulator/Makefile | 3 +
13 drivers/regulator/cpr3-npu-regulator.c | 695 +++
14 drivers/regulator/cpr3-regulator.c | 5112 +++++++++++++++++++++++
15 drivers/regulator/cpr3-regulator.h | 1211 ++++++
16 drivers/regulator/cpr3-util.c | 2750 ++++++++++++
17 drivers/regulator/cpr4-apss-regulator.c | 1819 ++++++++
18 include/soc/qcom/socinfo.h | 463 ++
19 8 files changed, 12086 insertions(+)
20 create mode 100644 drivers/regulator/cpr3-npu-regulator.c
21 create mode 100644 drivers/regulator/cpr3-regulator.c
22 create mode 100644 drivers/regulator/cpr3-regulator.h
23 create mode 100644 drivers/regulator/cpr3-util.c
24 create mode 100644 drivers/regulator/cpr4-apss-regulator.c
25 create mode 100644 include/soc/qcom/socinfo.h
26
27 --- a/drivers/regulator/Kconfig
28 +++ b/drivers/regulator/Kconfig
29 @@ -1423,5 +1423,38 @@ config REGULATOR_QCOM_LABIBB
30 boost regulator and IBB can be used as a negative boost regulator
31 for LCD display panel.
32
33 +config REGULATOR_CPR3
34 + bool "QCOM CPR3 regulator core support"
35 + help
36 + This driver supports Core Power Reduction (CPR) version 3 controllers
37 + which are used by some Qualcomm Technologies, Inc. SoCs to
38 + manage important voltage regulators. CPR3 controllers are capable of
39 + monitoring several ring oscillator sensing loops simultaneously. The
40 + CPR3 controller informs software when the silicon conditions require
41 + the supply voltage to be increased or decreased. On certain supply
42 + rails, the CPR3 controller is able to propagate the voltage increase
43 + or decrease requests all the way to the PMIC without software
44 + involvement.
45 +
46 +config REGULATOR_CPR3_NPU
47 + bool "QCOM CPR3 regulator for NPU"
48 + depends on OF && REGULATOR_CPR3
49 + help
50 + This driver supports Qualcomm Technologies, Inc. NPU CPR3
51 + regulator Which will always operate in open loop.
52 +
53 +config REGULATOR_CPR4_APSS
54 + bool "QCOM CPR4 regulator for APSS"
55 + depends on OF && REGULATOR_CPR3
56 + help
57 + This driver supports Qualcomm Technologies, Inc. APSS application
58 + processor specific features including memory array power mux (APM)
59 + switching, one CPR4 thread which monitor the two APSS clusters that
60 + are both powered by a shared supply, hardware closed-loop auto
61 + voltage stepping, voltage adjustments based on online core count,
62 + voltage adjustments based on temperature readings, and voltage
63 + adjustments for performance boost mode. This driver reads both initial
64 + voltage and CPR target quotient values out of hardware fuses.
65 +
66 endif
67
68 --- a/drivers/regulator/Makefile
69 +++ b/drivers/regulator/Makefile
70 @@ -105,6 +105,9 @@ obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qco
71 obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
72 obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
73 obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o
74 +obj-$(CONFIG_REGULATOR_CPR3) += cpr3-regulator.o cpr3-util.o
75 +obj-$(CONFIG_REGULATOR_CPR3_NPU) += cpr3-npu-regulator.o
76 +obj-$(CONFIG_REGULATOR_CPR4_APSS) += cpr4-apss-regulator.o
77 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
78 obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
79 obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o
80 --- /dev/null
81 +++ b/drivers/regulator/cpr3-npu-regulator.c
82 @@ -0,0 +1,695 @@
83 +/*
84 + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
85 + *
86 + * Permission to use, copy, modify, and/or distribute this software for any
87 + * purpose with or without fee is hereby granted, provided that the above
88 + * copyright notice and this permission notice appear in all copies.
89 + *
90 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
91 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
92 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
93 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
94 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
95 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
96 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
97 + */
98 +
99 +#include <linux/err.h>
100 +#include <linux/platform_device.h>
101 +#include <linux/module.h>
102 +#include <linux/of.h>
103 +#include <linux/of_device.h>
104 +#include <linux/slab.h>
105 +#include <linux/thermal.h>
106 +
107 +#include "cpr3-regulator.h"
108 +
109 +#define IPQ807x_NPU_FUSE_CORNERS 2
110 +#define IPQ817x_NPU_FUSE_CORNERS 1
111 +#define IPQ807x_NPU_FUSE_STEP_VOLT 8000
112 +#define IPQ807x_NPU_VOLTAGE_FUSE_SIZE 6
113 +#define IPQ807x_NPU_CPR_CLOCK_RATE 19200000
114 +
115 +#define IPQ807x_NPU_CPR_TCSR_START 6
116 +#define IPQ807x_NPU_CPR_TCSR_END 7
117 +
118 +#define NPU_TSENS 5
119 +
120 +u32 g_valid_npu_fuse_count = IPQ807x_NPU_FUSE_CORNERS;
121 +/**
122 + * struct cpr3_ipq807x_npu_fuses - NPU specific fuse data for IPQ807x
123 + * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value
124 + * for each fuse corner (raw, not converted to a voltage)
125 + * This struct holds the values for all of the fuses read from memory.
126 + */
127 +struct cpr3_ipq807x_npu_fuses {
128 + u64 init_voltage[IPQ807x_NPU_FUSE_CORNERS];
129 +};
130 +
131 +/*
132 + * Constants which define the name of each fuse corner.
133 + */
134 +enum cpr3_ipq807x_npu_fuse_corner {
135 + CPR3_IPQ807x_NPU_FUSE_CORNER_NOM = 0,
136 + CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO = 1,
137 +};
138 +
139 +static const char * const cpr3_ipq807x_npu_fuse_corner_name[] = {
140 + [CPR3_IPQ807x_NPU_FUSE_CORNER_NOM] = "NOM",
141 + [CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO] = "TURBO",
142 +};
143 +
144 +/*
145 + * IPQ807x NPU fuse parameter locations:
146 + *
147 + * Structs are organized with the following dimensions:
148 + * Outer: 0 to 1 for fuse corners from lowest to highest corner
149 + * Inner: large enough to hold the longest set of parameter segments which
150 + * fully defines a fuse parameter, +1 (for NULL termination).
151 + * Each segment corresponds to a contiguous group of bits from a
152 + * single fuse row. These segments are concatentated together in
153 + * order to form the full fuse parameter value. The segments for
154 + * a given parameter may correspond to different fuse rows.
155 + */
156 +static struct cpr3_fuse_param
157 +ipq807x_npu_init_voltage_param[IPQ807x_NPU_FUSE_CORNERS][2] = {
158 + {{73, 22, 27}, {} },
159 + {{73, 16, 21}, {} },
160 +};
161 +
162 +/*
163 + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
164 + */
165 +static int
166 +ipq807x_npu_fuse_ref_volt [IPQ807x_NPU_FUSE_CORNERS] = {
167 + 912000,
168 + 992000,
169 +};
170 +
171 +/*
172 + * IPQ9574 (Few parameters are changed, remaining are same as IPQ807x)
173 + */
174 +#define IPQ9574_NPU_FUSE_CORNERS 2
175 +#define IPQ9574_NPU_FUSE_STEP_VOLT 10000
176 +#define IPQ9574_NPU_CPR_CLOCK_RATE 24000000
177 +
178 +/*
179 + * fues parameters for IPQ9574
180 + */
181 +static struct cpr3_fuse_param
182 +ipq9574_npu_init_voltage_param[IPQ9574_NPU_FUSE_CORNERS][2] = {
183 + {{105, 12, 17}, {} },
184 + {{105, 6, 11}, {} },
185 +};
186 +
187 +/*
188 + * Open loop voltage fuse reference voltages in microvolts for IPQ9574
189 + */
190 +static int
191 +ipq9574_npu_fuse_ref_volt [IPQ9574_NPU_FUSE_CORNERS] = {
192 + 862500,
193 + 987500,
194 +};
195 +
196 +struct cpr3_controller *g_ctrl;
197 +
198 +void cpr3_npu_temp_notify(int sensor, int temp, int low_notif)
199 +{
200 + u32 prev_sensor_state;
201 +
202 + if (sensor != NPU_TSENS)
203 + return;
204 +
205 + prev_sensor_state = g_ctrl->cur_sensor_state;
206 + if (low_notif)
207 + g_ctrl->cur_sensor_state |= BIT(sensor);
208 + else
209 + g_ctrl->cur_sensor_state &= ~BIT(sensor);
210 +
211 + if (!prev_sensor_state && g_ctrl->cur_sensor_state)
212 + cpr3_handle_temp_open_loop_adjustment(g_ctrl, true);
213 + else if (prev_sensor_state && !g_ctrl->cur_sensor_state)
214 + cpr3_handle_temp_open_loop_adjustment(g_ctrl, false);
215 +}
216 +
217 +/**
218 + * cpr3_ipq807x_npu_read_fuse_data() - load NPU specific fuse parameter values
219 + * @vreg: Pointer to the CPR3 regulator
220 + *
221 + * This function allocates a cpr3_ipq807x_npu_fuses struct, fills it with
222 + * values read out of hardware fuses, and finally copies common fuse values
223 + * into the CPR3 regulator struct.
224 + *
225 + * Return: 0 on success, errno on failure
226 + */
227 +static int cpr3_ipq807x_npu_read_fuse_data(struct cpr3_regulator *vreg)
228 +{
229 + void __iomem *base = vreg->thread->ctrl->fuse_base;
230 + struct cpr3_ipq807x_npu_fuses *fuse;
231 + int i, rc;
232 +
233 + fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL);
234 + if (!fuse)
235 + return -ENOMEM;
236 +
237 + for (i = 0; i < g_valid_npu_fuse_count; i++) {
238 + rc = cpr3_read_fuse_param(base,
239 + vreg->cpr3_regulator_data->init_voltage_param[i],
240 + &fuse->init_voltage[i]);
241 + if (rc) {
242 + cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n",
243 + i, rc);
244 + return rc;
245 + }
246 + }
247 +
248 + vreg->fuse_corner_count = g_valid_npu_fuse_count;
249 + vreg->platform_fuses = fuse;
250 +
251 + return 0;
252 +}
253 +
254 +/**
255 + * cpr3_npu_parse_corner_data() - parse NPU corner data from device tree
256 + * properties of the CPR3 regulator's device node
257 + * @vreg: Pointer to the CPR3 regulator
258 + *
259 + * Return: 0 on success, errno on failure
260 + */
261 +static int cpr3_npu_parse_corner_data(struct cpr3_regulator *vreg)
262 +{
263 + int rc;
264 +
265 + rc = cpr3_parse_common_corner_data(vreg);
266 + if (rc) {
267 + cpr3_err(vreg, "error reading corner data, rc=%d\n", rc);
268 + return rc;
269 + }
270 +
271 + return rc;
272 +}
273 +
274 +/**
275 + * cpr3_ipq807x_npu_calculate_open_loop_voltages() - calculate the open-loop
276 + * voltage for each corner of a CPR3 regulator
277 + * @vreg: Pointer to the CPR3 regulator
278 + * @temp_correction: Temperature based correction
279 + *
280 + * If open-loop voltage interpolation is allowed in device tree, then
281 + * this function calculates the open-loop voltage for a given corner using
282 + * linear interpolation. This interpolation is performed using the processor
283 + * frequencies of the lower and higher Fmax corners along with their fused
284 + * open-loop voltages.
285 + *
286 + * If open-loop voltage interpolation is not allowed, then this function uses
287 + * the Fmax fused open-loop voltage for all of the corners associated with a
288 + * given fuse corner.
289 + *
290 + * Return: 0 on success, errno on failure
291 + */
292 +static int cpr3_ipq807x_npu_calculate_open_loop_voltages(
293 + struct cpr3_regulator *vreg, bool temp_correction)
294 +{
295 + struct cpr3_ipq807x_npu_fuses *fuse = vreg->platform_fuses;
296 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
297 + int i, j, rc = 0;
298 + u64 freq_low, volt_low, freq_high, volt_high;
299 + int *fuse_volt;
300 + int *fmax_corner;
301 +
302 + fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt),
303 + GFP_KERNEL);
304 + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
305 + GFP_KERNEL);
306 + if (!fuse_volt || !fmax_corner) {
307 + rc = -ENOMEM;
308 + goto done;
309 + }
310 +
311 + for (i = 0; i < vreg->fuse_corner_count; i++) {
312 + if (ctrl->cpr_global_setting == CPR_DISABLED)
313 + fuse_volt[i] = vreg->cpr3_regulator_data->fuse_ref_volt[i];
314 + else
315 + fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(
316 + vreg->cpr3_regulator_data->fuse_ref_volt[i],
317 + vreg->cpr3_regulator_data->fuse_step_volt,
318 + fuse->init_voltage[i],
319 + IPQ807x_NPU_VOLTAGE_FUSE_SIZE);
320 +
321 + /* Log fused open-loop voltage values for debugging purposes. */
322 + cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n",
323 + cpr3_ipq807x_npu_fuse_corner_name[i],
324 + fuse_volt[i]);
325 + }
326 +
327 + rc = cpr3_determine_part_type(vreg,
328 + fuse_volt[CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO]);
329 + if (rc) {
330 + cpr3_err(vreg,
331 + "fused part type detection failed failed, rc=%d\n", rc);
332 + goto done;
333 + }
334 +
335 + rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt);
336 + if (rc) {
337 + cpr3_err(vreg,
338 + "fused open-loop voltage adjustment failed, rc=%d\n",
339 + rc);
340 + goto done;
341 + }
342 + if (temp_correction) {
343 + rc = cpr3_determine_temp_base_open_loop_correction(vreg,
344 + fuse_volt);
345 + if (rc) {
346 + cpr3_err(vreg,
347 + "temp open-loop voltage adj. failed, rc=%d\n",
348 + rc);
349 + goto done;
350 + }
351 + }
352 +
353 + for (i = 1; i < vreg->fuse_corner_count; i++) {
354 + if (fuse_volt[i] < fuse_volt[i - 1]) {
355 + cpr3_info(vreg,
356 + "fuse corner %d voltage=%d uV < fuse corner %d \
357 + voltage=%d uV; overriding: fuse corner %d \
358 + voltage=%d\n",
359 + i, fuse_volt[i], i - 1, fuse_volt[i - 1],
360 + i, fuse_volt[i - 1]);
361 + fuse_volt[i] = fuse_volt[i - 1];
362 + }
363 + }
364 +
365 + /* Determine highest corner mapped to each fuse corner */
366 + j = vreg->fuse_corner_count - 1;
367 + for (i = vreg->corner_count - 1; i >= 0; i--) {
368 + if (vreg->corner[i].cpr_fuse_corner == j) {
369 + fmax_corner[j] = i;
370 + j--;
371 + }
372 + }
373 +
374 + if (j >= 0) {
375 + cpr3_err(vreg, "invalid fuse corner mapping\n");
376 + rc = -EINVAL;
377 + goto done;
378 + }
379 +
380 + /*
381 + * Interpolation is not possible for corners mapped to the lowest fuse
382 + * corner so use the fuse corner value directly.
383 + */
384 + for (i = 0; i <= fmax_corner[0]; i++)
385 + vreg->corner[i].open_loop_volt = fuse_volt[0];
386 +
387 + /* Interpolate voltages for the higher fuse corners. */
388 + for (i = 1; i < vreg->fuse_corner_count; i++) {
389 + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
390 + volt_low = fuse_volt[i - 1];
391 + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
392 + volt_high = fuse_volt[i];
393 +
394 + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
395 + vreg->corner[j].open_loop_volt = cpr3_interpolate(
396 + freq_low, volt_low, freq_high, volt_high,
397 + vreg->corner[j].proc_freq);
398 + }
399 +
400 +done:
401 + if (rc == 0) {
402 + cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n");
403 + for (i = 0; i < vreg->corner_count; i++)
404 + cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i,
405 + vreg->corner[i].open_loop_volt);
406 +
407 + rc = cpr3_adjust_open_loop_voltages(vreg);
408 + if (rc)
409 + cpr3_err(vreg,
410 + "open-loop voltage adjustment failed, rc=%d\n",
411 + rc);
412 + }
413 +
414 + kfree(fuse_volt);
415 + kfree(fmax_corner);
416 + return rc;
417 +}
418 +
419 +/**
420 + * cpr3_npu_print_settings() - print out NPU CPR configuration settings into
421 + * the kernel log for debugging purposes
422 + * @vreg: Pointer to the CPR3 regulator
423 + */
424 +static void cpr3_npu_print_settings(struct cpr3_regulator *vreg)
425 +{
426 + struct cpr3_corner *corner;
427 + int i;
428 +
429 + cpr3_debug(vreg,
430 + "Corner: Frequency (Hz), Fuse Corner, Floor (uV), \
431 + Open-Loop (uV), Ceiling (uV)\n");
432 + for (i = 0; i < vreg->corner_count; i++) {
433 + corner = &vreg->corner[i];
434 + cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n",
435 + i, corner->proc_freq, corner->cpr_fuse_corner,
436 + corner->floor_volt, corner->open_loop_volt,
437 + corner->ceiling_volt);
438 + }
439 +
440 + if (vreg->thread->ctrl->apm)
441 + cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n",
442 + vreg->thread->ctrl->apm_threshold_volt,
443 + vreg->thread->ctrl->apm_adj_volt);
444 +}
445 +
446 +/**
447 + * cpr3_ipq807x_npu_calc_temp_based_ol_voltages() - Calculate the open loop
448 + * voltages based on temperature based correction margins
449 + * @vreg: Pointer to the CPR3 regulator
450 + */
451 +
452 +static int
453 +cpr3_ipq807x_npu_calc_temp_based_ol_voltages(struct cpr3_regulator *vreg,
454 + bool temp_correction)
455 +{
456 + int rc, i;
457 +
458 + rc = cpr3_ipq807x_npu_calculate_open_loop_voltages(vreg,
459 + temp_correction);
460 + if (rc) {
461 + cpr3_err(vreg,
462 + "unable to calculate open-loop voltages, rc=%d\n", rc);
463 + return rc;
464 + }
465 +
466 + rc = cpr3_limit_open_loop_voltages(vreg);
467 + if (rc) {
468 + cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n",
469 + rc);
470 + return rc;
471 + }
472 +
473 + cpr3_open_loop_voltage_as_ceiling(vreg);
474 +
475 + rc = cpr3_limit_floor_voltages(vreg);
476 + if (rc) {
477 + cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc);
478 + return rc;
479 + }
480 +
481 + for (i = 0; i < vreg->corner_count; i++) {
482 + if (temp_correction)
483 + vreg->corner[i].cold_temp_open_loop_volt =
484 + vreg->corner[i].open_loop_volt;
485 + else
486 + vreg->corner[i].normal_temp_open_loop_volt =
487 + vreg->corner[i].open_loop_volt;
488 + }
489 +
490 + cpr3_npu_print_settings(vreg);
491 +
492 + return rc;
493 +}
494 +
495 +/**
496 + * cpr3_npu_init_thread() - perform steps necessary to initialize the
497 + * configuration data for a CPR3 thread
498 + * @thread: Pointer to the CPR3 thread
499 + *
500 + * Return: 0 on success, errno on failure
501 + */
502 +static int cpr3_npu_init_thread(struct cpr3_thread *thread)
503 +{
504 + int rc;
505 +
506 + rc = cpr3_parse_common_thread_data(thread);
507 + if (rc) {
508 + cpr3_err(thread->ctrl,
509 + "thread %u CPR thread data from DT- failed, rc=%d\n",
510 + thread->thread_id, rc);
511 + return rc;
512 + }
513 +
514 + return 0;
515 +}
516 +
517 +/**
518 + * cpr3_npu_init_regulator() - perform all steps necessary to initialize the
519 + * configuration data for a CPR3 regulator
520 + * @vreg: Pointer to the CPR3 regulator
521 + *
522 + * Return: 0 on success, errno on failure
523 + */
524 +static int cpr3_npu_init_regulator(struct cpr3_regulator *vreg)
525 +{
526 + struct cpr3_ipq807x_npu_fuses *fuse;
527 + int rc, cold_temp = 0;
528 + bool can_adj_cold_temp = cpr3_can_adjust_cold_temp(vreg);
529 +
530 + rc = cpr3_ipq807x_npu_read_fuse_data(vreg);
531 + if (rc) {
532 + cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc);
533 + return rc;
534 + }
535 +
536 + fuse = vreg->platform_fuses;
537 +
538 + rc = cpr3_npu_parse_corner_data(vreg);
539 + if (rc) {
540 + cpr3_err(vreg,
541 + "Cannot read CPR corner data from DT, rc=%d\n", rc);
542 + return rc;
543 + }
544 +
545 + rc = cpr3_mem_acc_init(vreg);
546 + if (rc) {
547 + if (rc != -EPROBE_DEFER)
548 + cpr3_err(vreg,
549 + "Cannot initialize mem-acc regulator settings, rc=%d\n",
550 + rc);
551 + return rc;
552 + }
553 +
554 + if (can_adj_cold_temp) {
555 + rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, true);
556 + if (rc) {
557 + cpr3_err(vreg,
558 + "unable to calculate open-loop voltages, rc=%d\n", rc);
559 + return rc;
560 + }
561 + }
562 +
563 + rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, false);
564 + if (rc) {
565 + cpr3_err(vreg,
566 + "unable to calculate open-loop voltages, rc=%d\n", rc);
567 + return rc;
568 + }
569 +
570 + if (can_adj_cold_temp) {
571 + cpr3_info(vreg,
572 + "Normal and Cold condition init done. Default to normal.\n");
573 +
574 + rc = cpr3_get_cold_temp_threshold(vreg, &cold_temp);
575 + if (rc) {
576 + cpr3_err(vreg,
577 + "Get cold temperature threshold failed, rc=%d\n", rc);
578 + return rc;
579 + }
580 + register_low_temp_notif(NPU_TSENS, cold_temp,
581 + cpr3_npu_temp_notify);
582 + }
583 +
584 + return rc;
585 +}
586 +
587 +/**
588 + * cpr3_npu_init_controller() - perform NPU CPR3 controller specific
589 + * initializations
590 + * @ctrl: Pointer to the CPR3 controller
591 + *
592 + * Return: 0 on success, errno on failure
593 + */
594 +static int cpr3_npu_init_controller(struct cpr3_controller *ctrl)
595 +{
596 + int rc;
597 +
598 + rc = cpr3_parse_open_loop_common_ctrl_data(ctrl);
599 + if (rc) {
600 + if (rc != -EPROBE_DEFER)
601 + cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n",
602 + rc);
603 + return rc;
604 + }
605 +
606 + ctrl->ctrl_type = CPR_CTRL_TYPE_CPR3;
607 + ctrl->supports_hw_closed_loop = false;
608 +
609 + return 0;
610 +}
611 +
612 +static const struct cpr3_reg_data ipq807x_cpr_npu = {
613 + .cpr_valid_fuse_count = IPQ807x_NPU_FUSE_CORNERS,
614 + .init_voltage_param = ipq807x_npu_init_voltage_param,
615 + .fuse_ref_volt = ipq807x_npu_fuse_ref_volt,
616 + .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT,
617 + .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE,
618 +};
619 +
620 +static const struct cpr3_reg_data ipq817x_cpr_npu = {
621 + .cpr_valid_fuse_count = IPQ817x_NPU_FUSE_CORNERS,
622 + .init_voltage_param = ipq807x_npu_init_voltage_param,
623 + .fuse_ref_volt = ipq807x_npu_fuse_ref_volt,
624 + .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT,
625 + .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE,
626 +};
627 +
628 +static const struct cpr3_reg_data ipq9574_cpr_npu = {
629 + .cpr_valid_fuse_count = IPQ9574_NPU_FUSE_CORNERS,
630 + .init_voltage_param = ipq9574_npu_init_voltage_param,
631 + .fuse_ref_volt = ipq9574_npu_fuse_ref_volt,
632 + .fuse_step_volt = IPQ9574_NPU_FUSE_STEP_VOLT,
633 + .cpr_clk_rate = IPQ9574_NPU_CPR_CLOCK_RATE,
634 +};
635 +
636 +static struct of_device_id cpr3_regulator_match_table[] = {
637 + {
638 + .compatible = "qcom,cpr3-ipq807x-npu-regulator",
639 + .data = &ipq807x_cpr_npu
640 + },
641 + {
642 + .compatible = "qcom,cpr3-ipq817x-npu-regulator",
643 + .data = &ipq817x_cpr_npu
644 + },
645 + {
646 + .compatible = "qcom,cpr3-ipq9574-npu-regulator",
647 + .data = &ipq9574_cpr_npu
648 + },
649 + {}
650 +};
651 +
652 +static int cpr3_npu_regulator_probe(struct platform_device *pdev)
653 +{
654 + struct device *dev = &pdev->dev;
655 + struct cpr3_controller *ctrl;
656 + int i, rc;
657 + const struct of_device_id *match;
658 + struct cpr3_reg_data *cpr_data;
659 +
660 + if (!dev->of_node) {
661 + dev_err(dev, "Device tree node is missing\n");
662 + return -EINVAL;
663 + }
664 +
665 + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
666 + if (!ctrl)
667 + return -ENOMEM;
668 + g_ctrl = ctrl;
669 +
670 + match = of_match_device(cpr3_regulator_match_table, &pdev->dev);
671 + if (!match)
672 + return -ENODEV;
673 +
674 + cpr_data = (struct cpr3_reg_data *)match->data;
675 + g_valid_npu_fuse_count = cpr_data->cpr_valid_fuse_count;
676 + dev_info(dev, "NPU CPR valid fuse count: %d\n", g_valid_npu_fuse_count);
677 + ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate;
678 +
679 + ctrl->dev = dev;
680 + /* Set to false later if anything precludes CPR operation. */
681 + ctrl->cpr_allowed_hw = true;
682 +
683 + rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name",
684 + &ctrl->name);
685 + if (rc) {
686 + cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n",
687 + rc);
688 + return rc;
689 + }
690 +
691 + rc = cpr3_map_fuse_base(ctrl, pdev);
692 + if (rc) {
693 + cpr3_err(ctrl, "could not map fuse base address\n");
694 + return rc;
695 + }
696 +
697 + rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_NPU_CPR_TCSR_START,
698 + IPQ807x_NPU_CPR_TCSR_END);
699 + if (rc) {
700 + cpr3_err(ctrl, "could not read CPR tcsr rsetting\n");
701 + return rc;
702 + }
703 +
704 + rc = cpr3_allocate_threads(ctrl, 0, 0);
705 + if (rc) {
706 + cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n",
707 + rc);
708 + return rc;
709 + }
710 +
711 + if (ctrl->thread_count != 1) {
712 + cpr3_err(ctrl, "expected 1 thread but found %d\n",
713 + ctrl->thread_count);
714 + return -EINVAL;
715 + }
716 +
717 + rc = cpr3_npu_init_controller(ctrl);
718 + if (rc) {
719 + if (rc != -EPROBE_DEFER)
720 + cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n",
721 + rc);
722 + return rc;
723 + }
724 +
725 + rc = cpr3_npu_init_thread(&ctrl->thread[0]);
726 + if (rc) {
727 + cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc);
728 + return rc;
729 + }
730 +
731 + for (i = 0; i < ctrl->thread[0].vreg_count; i++) {
732 + ctrl->thread[0].vreg[i].cpr3_regulator_data = cpr_data;
733 + rc = cpr3_npu_init_regulator(&ctrl->thread[0].vreg[i]);
734 + if (rc) {
735 + cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n",
736 + rc);
737 + return rc;
738 + }
739 + }
740 +
741 + platform_set_drvdata(pdev, ctrl);
742 +
743 + return cpr3_open_loop_regulator_register(pdev, ctrl);
744 +}
745 +
746 +static int cpr3_npu_regulator_remove(struct platform_device *pdev)
747 +{
748 + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
749 +
750 + return cpr3_open_loop_regulator_unregister(ctrl);
751 +}
752 +
753 +static struct platform_driver cpr3_npu_regulator_driver = {
754 + .driver = {
755 + .name = "qcom,cpr3-npu-regulator",
756 + .of_match_table = cpr3_regulator_match_table,
757 + .owner = THIS_MODULE,
758 + },
759 + .probe = cpr3_npu_regulator_probe,
760 + .remove = cpr3_npu_regulator_remove,
761 +};
762 +
763 +static int cpr3_regulator_init(void)
764 +{
765 + return platform_driver_register(&cpr3_npu_regulator_driver);
766 +}
767 +arch_initcall(cpr3_regulator_init);
768 +
769 +static void cpr3_regulator_exit(void)
770 +{
771 + platform_driver_unregister(&cpr3_npu_regulator_driver);
772 +}
773 +module_exit(cpr3_regulator_exit);
774 +
775 +MODULE_DESCRIPTION("QCOM CPR3 NPU regulator driver");
776 +MODULE_LICENSE("Dual BSD/GPLv2");
777 +MODULE_ALIAS("platform:npu-ipq807x");
778 --- /dev/null
779 +++ b/drivers/regulator/cpr3-regulator.c
780 @@ -0,0 +1,5112 @@
781 +/*
782 + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
783 + *
784 + * This program is free software; you can redistribute it and/or modify
785 + * it under the terms of the GNU General Public License version 2 and
786 + * only version 2 as published by the Free Software Foundation.
787 + *
788 + * This program is distributed in the hope that it will be useful,
789 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
790 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
791 + * GNU General Public License for more details.
792 + */
793 +
794 +#define pr_fmt(fmt) "%s: " fmt, __func__
795 +
796 +#include <linux/bitops.h>
797 +#include <linux/debugfs.h>
798 +#include <linux/delay.h>
799 +#include <linux/err.h>
800 +#include <linux/init.h>
801 +#include <linux/interrupt.h>
802 +#include <linux/io.h>
803 +#include <linux/kernel.h>
804 +#include <linux/ktime.h>
805 +#include <linux/list.h>
806 +#include <linux/module.h>
807 +#include <linux/of.h>
808 +#include <linux/of_device.h>
809 +#include <linux/platform_device.h>
810 +#include <linux/pm_opp.h>
811 +#include <linux/slab.h>
812 +#include <linux/sort.h>
813 +#include <linux/string.h>
814 +#include <linux/uaccess.h>
815 +#include <linux/regulator/driver.h>
816 +#include <linux/regulator/machine.h>
817 +#include <linux/regulator/of_regulator.h>
818 +#include <linux/panic_notifier.h>
819 +
820 +#include "cpr3-regulator.h"
821 +
822 +#define CPR3_REGULATOR_CORNER_INVALID (-1)
823 +#define CPR3_RO_MASK GENMASK(CPR3_RO_COUNT - 1, 0)
824 +
825 +/* CPR3 registers */
826 +#define CPR3_REG_CPR_CTL 0x4
827 +#define CPR3_CPR_CTL_LOOP_EN_MASK BIT(0)
828 +#define CPR3_CPR_CTL_LOOP_ENABLE BIT(0)
829 +#define CPR3_CPR_CTL_LOOP_DISABLE 0
830 +#define CPR3_CPR_CTL_IDLE_CLOCKS_MASK GENMASK(5, 1)
831 +#define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT 1
832 +#define CPR3_CPR_CTL_COUNT_MODE_MASK GENMASK(7, 6)
833 +#define CPR3_CPR_CTL_COUNT_MODE_SHIFT 6
834 +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN 0
835 +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX 1
836 +#define CPR3_CPR_CTL_COUNT_MODE_STAGGERED 2
837 +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE 3
838 +#define CPR3_CPR_CTL_COUNT_REPEAT_MASK GENMASK(31, 9)
839 +#define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT 9
840 +
841 +#define CPR3_REG_CPR_STATUS 0x8
842 +#define CPR3_CPR_STATUS_BUSY_MASK BIT(0)
843 +#define CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK BIT(1)
844 +
845 +/*
846 + * This register is not present on controllers that support HW closed-loop
847 + * except CPR4 APSS controller.
848 + */
849 +#define CPR3_REG_CPR_TIMER_AUTO_CONT 0xC
850 +
851 +#define CPR3_REG_CPR_STEP_QUOT 0x14
852 +#define CPR3_CPR_STEP_QUOT_MIN_MASK GENMASK(5, 0)
853 +#define CPR3_CPR_STEP_QUOT_MIN_SHIFT 0
854 +#define CPR3_CPR_STEP_QUOT_MAX_MASK GENMASK(11, 6)
855 +#define CPR3_CPR_STEP_QUOT_MAX_SHIFT 6
856 +
857 +#define CPR3_REG_GCNT(ro) (0xA0 + 0x4 * (ro))
858 +
859 +#define CPR3_REG_SENSOR_BYPASS_WRITE(sensor) (0xE0 + 0x4 * ((sensor) / 32))
860 +#define CPR3_REG_SENSOR_BYPASS_WRITE_BANK(bank) (0xE0 + 0x4 * (bank))
861 +
862 +#define CPR3_REG_SENSOR_MASK_WRITE(sensor) (0x120 + 0x4 * ((sensor) / 32))
863 +#define CPR3_REG_SENSOR_MASK_WRITE_BANK(bank) (0x120 + 0x4 * (bank))
864 +#define CPR3_REG_SENSOR_MASK_READ(sensor) (0x140 + 0x4 * ((sensor) / 32))
865 +
866 +#define CPR3_REG_SENSOR_OWNER(sensor) (0x200 + 0x4 * (sensor))
867 +
868 +#define CPR3_REG_CONT_CMD 0x800
869 +#define CPR3_CONT_CMD_ACK 0x1
870 +#define CPR3_CONT_CMD_NACK 0x0
871 +
872 +#define CPR3_REG_THRESH(thread) (0x808 + 0x440 * (thread))
873 +#define CPR3_THRESH_CONS_DOWN_MASK GENMASK(3, 0)
874 +#define CPR3_THRESH_CONS_DOWN_SHIFT 0
875 +#define CPR3_THRESH_CONS_UP_MASK GENMASK(7, 4)
876 +#define CPR3_THRESH_CONS_UP_SHIFT 4
877 +#define CPR3_THRESH_DOWN_THRESH_MASK GENMASK(12, 8)
878 +#define CPR3_THRESH_DOWN_THRESH_SHIFT 8
879 +#define CPR3_THRESH_UP_THRESH_MASK GENMASK(17, 13)
880 +#define CPR3_THRESH_UP_THRESH_SHIFT 13
881 +
882 +#define CPR3_REG_RO_MASK(thread) (0x80C + 0x440 * (thread))
883 +
884 +#define CPR3_REG_RESULT0(thread) (0x810 + 0x440 * (thread))
885 +#define CPR3_RESULT0_BUSY_MASK BIT(0)
886 +#define CPR3_RESULT0_STEP_DN_MASK BIT(1)
887 +#define CPR3_RESULT0_STEP_UP_MASK BIT(2)
888 +#define CPR3_RESULT0_ERROR_STEPS_MASK GENMASK(7, 3)
889 +#define CPR3_RESULT0_ERROR_STEPS_SHIFT 3
890 +#define CPR3_RESULT0_ERROR_MASK GENMASK(19, 8)
891 +#define CPR3_RESULT0_ERROR_SHIFT 8
892 +#define CPR3_RESULT0_NEGATIVE_MASK BIT(20)
893 +
894 +#define CPR3_REG_RESULT1(thread) (0x814 + 0x440 * (thread))
895 +#define CPR3_RESULT1_QUOT_MIN_MASK GENMASK(11, 0)
896 +#define CPR3_RESULT1_QUOT_MIN_SHIFT 0
897 +#define CPR3_RESULT1_QUOT_MAX_MASK GENMASK(23, 12)
898 +#define CPR3_RESULT1_QUOT_MAX_SHIFT 12
899 +#define CPR3_RESULT1_RO_MIN_MASK GENMASK(27, 24)
900 +#define CPR3_RESULT1_RO_MIN_SHIFT 24
901 +#define CPR3_RESULT1_RO_MAX_MASK GENMASK(31, 28)
902 +#define CPR3_RESULT1_RO_MAX_SHIFT 28
903 +
904 +#define CPR3_REG_RESULT2(thread) (0x818 + 0x440 * (thread))
905 +#define CPR3_RESULT2_STEP_QUOT_MIN_MASK GENMASK(5, 0)
906 +#define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT 0
907 +#define CPR3_RESULT2_STEP_QUOT_MAX_MASK GENMASK(11, 6)
908 +#define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT 6
909 +#define CPR3_RESULT2_SENSOR_MIN_MASK GENMASK(23, 16)
910 +#define CPR3_RESULT2_SENSOR_MIN_SHIFT 16
911 +#define CPR3_RESULT2_SENSOR_MAX_MASK GENMASK(31, 24)
912 +#define CPR3_RESULT2_SENSOR_MAX_SHIFT 24
913 +
914 +#define CPR3_REG_IRQ_EN 0x81C
915 +#define CPR3_REG_IRQ_CLEAR 0x820
916 +#define CPR3_REG_IRQ_STATUS 0x824
917 +#define CPR3_IRQ_UP BIT(3)
918 +#define CPR3_IRQ_MID BIT(2)
919 +#define CPR3_IRQ_DOWN BIT(1)
920 +
921 +#define CPR3_REG_TARGET_QUOT(thread, ro) \
922 + (0x840 + 0x440 * (thread) + 0x4 * (ro))
923 +
924 +/* Registers found only on controllers that support HW closed-loop. */
925 +#define CPR3_REG_PD_THROTTLE 0xE8
926 +#define CPR3_PD_THROTTLE_DISABLE 0x0
927 +
928 +#define CPR3_REG_HW_CLOSED_LOOP 0x3000
929 +#define CPR3_HW_CLOSED_LOOP_ENABLE 0x0
930 +#define CPR3_HW_CLOSED_LOOP_DISABLE 0x1
931 +
932 +#define CPR3_REG_CPR_TIMER_MID_CONT 0x3004
933 +#define CPR3_REG_CPR_TIMER_UP_DN_CONT 0x3008
934 +
935 +#define CPR3_REG_LAST_MEASUREMENT 0x7F8
936 +#define CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT 0
937 +#define CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT 4
938 +#define CPR3_LAST_MEASUREMENT_THREAD_DN(thread) \
939 + (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT)
940 +#define CPR3_LAST_MEASUREMENT_THREAD_UP(thread) \
941 + (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT)
942 +#define CPR3_LAST_MEASUREMENT_AGGR_DN BIT(8)
943 +#define CPR3_LAST_MEASUREMENT_AGGR_MID BIT(9)
944 +#define CPR3_LAST_MEASUREMENT_AGGR_UP BIT(10)
945 +#define CPR3_LAST_MEASUREMENT_VALID BIT(11)
946 +#define CPR3_LAST_MEASUREMENT_SAW_ERROR BIT(12)
947 +#define CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK GENMASK(23, 16)
948 +#define CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT 16
949 +
950 +/* CPR4 controller specific registers and bit definitions */
951 +#define CPR4_REG_CPR_TIMER_CLAMP 0x10
952 +#define CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN BIT(27)
953 +
954 +#define CPR4_REG_MISC 0x700
955 +#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK GENMASK(23, 20)
956 +#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT 20
957 +#define CPR4_MISC_TEMP_SENSOR_ID_START_MASK GENMASK(27, 24)
958 +#define CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT 24
959 +#define CPR4_MISC_TEMP_SENSOR_ID_END_MASK GENMASK(31, 28)
960 +#define CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT 28
961 +
962 +#define CPR4_REG_SAW_ERROR_STEP_LIMIT 0x7A4
963 +#define CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK GENMASK(4, 0)
964 +#define CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT 0
965 +#define CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK GENMASK(9, 5)
966 +#define CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT 5
967 +
968 +#define CPR4_REG_MARGIN_TEMP_CORE_TIMERS 0x7A8
969 +#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK GENMASK(28, 18)
970 +#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT 18
971 +
972 +#define CPR4_REG_MARGIN_TEMP_CORE(core) (0x7AC + 0x4 * (core))
973 +#define CPR4_MARGIN_TEMP_CORE_ADJ_MASK GENMASK(7, 0)
974 +#define CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT 8
975 +
976 +#define CPR4_REG_MARGIN_TEMP_POINT0N1 0x7F0
977 +#define CPR4_MARGIN_TEMP_POINT0_MASK GENMASK(11, 0)
978 +#define CPR4_MARGIN_TEMP_POINT0_SHIFT 0
979 +#define CPR4_MARGIN_TEMP_POINT1_MASK GENMASK(23, 12)
980 +#define CPR4_MARGIN_TEMP_POINT1_SHIFT 12
981 +#define CPR4_REG_MARGIN_TEMP_POINT2 0x7F4
982 +#define CPR4_MARGIN_TEMP_POINT2_MASK GENMASK(11, 0)
983 +#define CPR4_MARGIN_TEMP_POINT2_SHIFT 0
984 +
985 +#define CPR4_REG_MARGIN_ADJ_CTL 0x7F8
986 +#define CPR4_MARGIN_ADJ_CTL_BOOST_EN BIT(0)
987 +#define CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN BIT(1)
988 +#define CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN BIT(2)
989 +#define CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN BIT(3)
990 +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK BIT(4)
991 +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE BIT(4)
992 +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE 0
993 +#define CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN BIT(7)
994 +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN BIT(8)
995 +#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK GENMASK(16, 12)
996 +#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT 12
997 +#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK GENMASK(21, 19)
998 +#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT 19
999 +#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK GENMASK(25, 22)
1000 +#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT 22
1001 +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK GENMASK(31, 26)
1002 +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT 26
1003 +
1004 +#define CPR4_REG_CPR_MASK_THREAD(thread) (0x80C + 0x440 * (thread))
1005 +#define CPR4_CPR_MASK_THREAD_DISABLE_THREAD BIT(31)
1006 +#define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK GENMASK(15, 0)
1007 +
1008 +/*
1009 + * The amount of time to wait for the CPR controller to become idle when
1010 + * performing an aging measurement.
1011 + */
1012 +#define CPR3_AGING_MEASUREMENT_TIMEOUT_NS 5000000
1013 +
1014 +/*
1015 + * The number of individual aging measurements to perform which are then
1016 + * averaged together in order to determine the final aging adjustment value.
1017 + */
1018 +#define CPR3_AGING_MEASUREMENT_ITERATIONS 16
1019 +
1020 +/*
1021 + * Aging measurements for the aged and unaged ring oscillators take place a few
1022 + * microseconds apart. If the vdd-supply voltage fluctuates between the two
1023 + * measurements, then the difference between them will be incorrect. The
1024 + * difference could end up too high or too low. This constant defines the
1025 + * number of lowest and highest measurements to ignore when averaging.
1026 + */
1027 +#define CPR3_AGING_MEASUREMENT_FILTER 3
1028 +
1029 +/*
1030 + * The number of times to attempt the full aging measurement sequence before
1031 + * declaring a measurement failure.
1032 + */
1033 +#define CPR3_AGING_RETRY_COUNT 5
1034 +
1035 +/*
1036 + * The maximum time to wait in microseconds for a CPR register write to
1037 + * complete.
1038 + */
1039 +#define CPR3_REGISTER_WRITE_DELAY_US 200
1040 +
1041 +static DEFINE_MUTEX(cpr3_controller_list_mutex);
1042 +static LIST_HEAD(cpr3_controller_list);
1043 +static struct dentry *cpr3_debugfs_base;
1044 +
1045 +/**
1046 + * cpr3_read() - read four bytes from the memory address specified
1047 + * @ctrl: Pointer to the CPR3 controller
1048 + * @offset: Offset in bytes from the CPR3 controller's base address
1049 + *
1050 + * Return: memory address value
1051 + */
1052 +static inline u32 cpr3_read(struct cpr3_controller *ctrl, u32 offset)
1053 +{
1054 + if (!ctrl->cpr_enabled) {
1055 + cpr3_err(ctrl, "CPR register reads are not possible when CPR clocks are disabled\n");
1056 + return 0;
1057 + }
1058 +
1059 + return readl_relaxed(ctrl->cpr_ctrl_base + offset);
1060 +}
1061 +
1062 +/**
1063 + * cpr3_write() - write four bytes to the memory address specified
1064 + * @ctrl: Pointer to the CPR3 controller
1065 + * @offset: Offset in bytes from the CPR3 controller's base address
1066 + * @value: Value to write to the memory address
1067 + *
1068 + * Return: none
1069 + */
1070 +static inline void cpr3_write(struct cpr3_controller *ctrl, u32 offset,
1071 + u32 value)
1072 +{
1073 + if (!ctrl->cpr_enabled) {
1074 + cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
1075 + return;
1076 + }
1077 +
1078 + writel_relaxed(value, ctrl->cpr_ctrl_base + offset);
1079 +}
1080 +
1081 +/**
1082 + * cpr3_masked_write() - perform a read-modify-write sequence so that only
1083 + * masked bits are modified
1084 + * @ctrl: Pointer to the CPR3 controller
1085 + * @offset: Offset in bytes from the CPR3 controller's base address
1086 + * @mask: Mask identifying the bits that should be modified
1087 + * @value: Value to write to the memory address
1088 + *
1089 + * Return: none
1090 + */
1091 +static inline void cpr3_masked_write(struct cpr3_controller *ctrl, u32 offset,
1092 + u32 mask, u32 value)
1093 +{
1094 + u32 reg_val, orig_val;
1095 +
1096 + if (!ctrl->cpr_enabled) {
1097 + cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
1098 + return;
1099 + }
1100 +
1101 + reg_val = orig_val = readl_relaxed(ctrl->cpr_ctrl_base + offset);
1102 + reg_val &= ~mask;
1103 + reg_val |= value & mask;
1104 +
1105 + if (reg_val != orig_val)
1106 + writel_relaxed(reg_val, ctrl->cpr_ctrl_base + offset);
1107 +}
1108 +
1109 +/**
1110 + * cpr3_ctrl_loop_enable() - enable the CPR sensing loop for a given controller
1111 + * @ctrl: Pointer to the CPR3 controller
1112 + *
1113 + * Return: none
1114 + */
1115 +static inline void cpr3_ctrl_loop_enable(struct cpr3_controller *ctrl)
1116 +{
1117 + if (ctrl->cpr_enabled && !(ctrl->aggr_corner.sdelta
1118 + && ctrl->aggr_corner.sdelta->allow_boost))
1119 + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
1120 + CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_ENABLE);
1121 +}
1122 +
1123 +/**
1124 + * cpr3_ctrl_loop_disable() - disable the CPR sensing loop for a given
1125 + * controller
1126 + * @ctrl: Pointer to the CPR3 controller
1127 + *
1128 + * Return: none
1129 + */
1130 +static inline void cpr3_ctrl_loop_disable(struct cpr3_controller *ctrl)
1131 +{
1132 + if (ctrl->cpr_enabled)
1133 + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
1134 + CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_DISABLE);
1135 +}
1136 +
1137 +/**
1138 + * cpr3_clock_enable() - prepare and enable all clocks used by this CPR3
1139 + * controller
1140 + * @ctrl: Pointer to the CPR3 controller
1141 + *
1142 + * Return: 0 on success, errno on failure
1143 + */
1144 +static int cpr3_clock_enable(struct cpr3_controller *ctrl)
1145 +{
1146 + int rc;
1147 +
1148 + rc = clk_prepare_enable(ctrl->bus_clk);
1149 + if (rc) {
1150 + cpr3_err(ctrl, "failed to enable bus clock, rc=%d\n", rc);
1151 + return rc;
1152 + }
1153 +
1154 + rc = clk_prepare_enable(ctrl->iface_clk);
1155 + if (rc) {
1156 + cpr3_err(ctrl, "failed to enable interface clock, rc=%d\n", rc);
1157 + clk_disable_unprepare(ctrl->bus_clk);
1158 + return rc;
1159 + }
1160 +
1161 + rc = clk_prepare_enable(ctrl->core_clk);
1162 + if (rc) {
1163 + cpr3_err(ctrl, "failed to enable core clock, rc=%d\n", rc);
1164 + clk_disable_unprepare(ctrl->iface_clk);
1165 + clk_disable_unprepare(ctrl->bus_clk);
1166 + return rc;
1167 + }
1168 +
1169 + return 0;
1170 +}
1171 +
1172 +/**
1173 + * cpr3_clock_disable() - disable and unprepare all clocks used by this CPR3
1174 + * controller
1175 + * @ctrl: Pointer to the CPR3 controller
1176 + *
1177 + * Return: none
1178 + */
1179 +static void cpr3_clock_disable(struct cpr3_controller *ctrl)
1180 +{
1181 + clk_disable_unprepare(ctrl->core_clk);
1182 + clk_disable_unprepare(ctrl->iface_clk);
1183 + clk_disable_unprepare(ctrl->bus_clk);
1184 +}
1185 +
1186 +/**
1187 + * cpr3_ctrl_clear_cpr4_config() - clear the CPR4 register configuration
1188 + * programmed for current aggregated corner of a given controller
1189 + * @ctrl: Pointer to the CPR3 controller
1190 + *
1191 + * Return: 0 on success, errno on failure
1192 + */
1193 +static inline int cpr3_ctrl_clear_cpr4_config(struct cpr3_controller *ctrl)
1194 +{
1195 + struct cpr4_sdelta *aggr_sdelta = ctrl->aggr_corner.sdelta;
1196 + bool cpr_enabled = ctrl->cpr_enabled;
1197 + int i, rc = 0;
1198 +
1199 + if (!aggr_sdelta || !(aggr_sdelta->allow_core_count_adj
1200 + || aggr_sdelta->allow_temp_adj || aggr_sdelta->allow_boost))
1201 + /* cpr4 features are not enabled */
1202 + return 0;
1203 +
1204 + /* Ensure that CPR clocks are enabled before writing to registers. */
1205 + if (!cpr_enabled) {
1206 + rc = cpr3_clock_enable(ctrl);
1207 + if (rc) {
1208 + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
1209 + return rc;
1210 + }
1211 + ctrl->cpr_enabled = true;
1212 + }
1213 +
1214 + /*
1215 + * Clear feature enable configuration made for current
1216 + * aggregated corner.
1217 + */
1218 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1219 + CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
1220 + | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
1221 + | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
1222 + | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
1223 + | CPR4_MARGIN_ADJ_CTL_BOOST_EN
1224 + | CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, 0);
1225 +
1226 + cpr3_masked_write(ctrl, CPR4_REG_MISC,
1227 + CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
1228 + 0 << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
1229 +
1230 + for (i = 0; i <= aggr_sdelta->max_core_count; i++) {
1231 + /* Clear voltage margin adjustments programmed in TEMP_COREi */
1232 + cpr3_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE(i), 0);
1233 + }
1234 +
1235 + /* Turn off CPR clocks if they were off before this function call. */
1236 + if (!cpr_enabled) {
1237 + cpr3_clock_disable(ctrl);
1238 + ctrl->cpr_enabled = false;
1239 + }
1240 +
1241 + return 0;
1242 +}
1243 +
1244 +/**
1245 + * cpr3_closed_loop_enable() - enable logical CPR closed-loop operation
1246 + * @ctrl: Pointer to the CPR3 controller
1247 + *
1248 + * Return: 0 on success, errno on failure
1249 + */
1250 +static int cpr3_closed_loop_enable(struct cpr3_controller *ctrl)
1251 +{
1252 + int rc;
1253 +
1254 + if (!ctrl->cpr_allowed_hw || !ctrl->cpr_allowed_sw) {
1255 + cpr3_err(ctrl, "cannot enable closed-loop CPR operation because it is disallowed\n");
1256 + return -EPERM;
1257 + } else if (ctrl->cpr_enabled) {
1258 + /* Already enabled */
1259 + return 0;
1260 + } else if (ctrl->cpr_suspended) {
1261 + /*
1262 + * CPR must remain disabled as the system is entering suspend.
1263 + */
1264 + return 0;
1265 + }
1266 +
1267 + rc = cpr3_clock_enable(ctrl);
1268 + if (rc) {
1269 + cpr3_err(ctrl, "unable to enable CPR clocks, rc=%d\n", rc);
1270 + return rc;
1271 + }
1272 +
1273 + ctrl->cpr_enabled = true;
1274 + cpr3_debug(ctrl, "CPR closed-loop operation enabled\n");
1275 +
1276 + return 0;
1277 +}
1278 +
1279 +/**
1280 + * cpr3_closed_loop_disable() - disable logical CPR closed-loop operation
1281 + * @ctrl: Pointer to the CPR3 controller
1282 + *
1283 + * Return: 0 on success, errno on failure
1284 + */
1285 +static inline int cpr3_closed_loop_disable(struct cpr3_controller *ctrl)
1286 +{
1287 + if (!ctrl->cpr_enabled) {
1288 + /* Already disabled */
1289 + return 0;
1290 + }
1291 +
1292 + cpr3_clock_disable(ctrl);
1293 + ctrl->cpr_enabled = false;
1294 + cpr3_debug(ctrl, "CPR closed-loop operation disabled\n");
1295 +
1296 + return 0;
1297 +}
1298 +
1299 +/**
1300 + * cpr3_regulator_get_gcnt() - returns the GCNT register value corresponding
1301 + * to the clock rate and sensor time of the CPR3 controller
1302 + * @ctrl: Pointer to the CPR3 controller
1303 + *
1304 + * Return: GCNT value
1305 + */
1306 +static u32 cpr3_regulator_get_gcnt(struct cpr3_controller *ctrl)
1307 +{
1308 + u64 temp;
1309 + unsigned int remainder;
1310 + u32 gcnt;
1311 +
1312 + temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->sensor_time;
1313 + remainder = do_div(temp, 1000000000);
1314 + if (remainder)
1315 + temp++;
1316 + /*
1317 + * GCNT == 0 corresponds to a single ref clock measurement interval so
1318 + * offset GCNT values by 1.
1319 + */
1320 + gcnt = temp - 1;
1321 +
1322 + return gcnt;
1323 +}
1324 +
1325 +/**
1326 + * cpr3_regulator_init_thread() - performs hardware initialization of CPR
1327 + * thread registers
1328 + * @thread: Pointer to the CPR3 thread
1329 + *
1330 + * CPR interface/bus clocks must be enabled before calling this function.
1331 + *
1332 + * Return: 0 on success, errno on failure
1333 + */
1334 +static int cpr3_regulator_init_thread(struct cpr3_thread *thread)
1335 +{
1336 + u32 reg;
1337 +
1338 + reg = (thread->consecutive_up << CPR3_THRESH_CONS_UP_SHIFT)
1339 + & CPR3_THRESH_CONS_UP_MASK;
1340 + reg |= (thread->consecutive_down << CPR3_THRESH_CONS_DOWN_SHIFT)
1341 + & CPR3_THRESH_CONS_DOWN_MASK;
1342 + reg |= (thread->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT)
1343 + & CPR3_THRESH_UP_THRESH_MASK;
1344 + reg |= (thread->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT)
1345 + & CPR3_THRESH_DOWN_THRESH_MASK;
1346 +
1347 + cpr3_write(thread->ctrl, CPR3_REG_THRESH(thread->thread_id), reg);
1348 +
1349 + /*
1350 + * Mask all RO's initially so that unused thread doesn't contribute
1351 + * to closed-loop voltage.
1352 + */
1353 + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
1354 + CPR3_RO_MASK);
1355 +
1356 + return 0;
1357 +}
1358 +
1359 +/**
1360 + * cpr4_regulator_init_temp_points() - performs hardware initialization of CPR4
1361 + * registers to track tsen temperature data and also specify the
1362 + * temperature band range values to apply different voltage margins
1363 + * @ctrl: Pointer to the CPR3 controller
1364 + *
1365 + * CPR interface/bus clocks must be enabled before calling this function.
1366 + *
1367 + * Return: 0 on success, errno on failure
1368 + */
1369 +static int cpr4_regulator_init_temp_points(struct cpr3_controller *ctrl)
1370 +{
1371 + if (!ctrl->allow_temp_adj)
1372 + return 0;
1373 +
1374 + cpr3_masked_write(ctrl, CPR4_REG_MISC,
1375 + CPR4_MISC_TEMP_SENSOR_ID_START_MASK,
1376 + ctrl->temp_sensor_id_start
1377 + << CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT);
1378 +
1379 + cpr3_masked_write(ctrl, CPR4_REG_MISC,
1380 + CPR4_MISC_TEMP_SENSOR_ID_END_MASK,
1381 + ctrl->temp_sensor_id_end
1382 + << CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT);
1383 +
1384 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT2,
1385 + CPR4_MARGIN_TEMP_POINT2_MASK,
1386 + (ctrl->temp_band_count == 4 ? ctrl->temp_points[2] : 0x7FF)
1387 + << CPR4_MARGIN_TEMP_POINT2_SHIFT);
1388 +
1389 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
1390 + CPR4_MARGIN_TEMP_POINT1_MASK,
1391 + (ctrl->temp_band_count >= 3 ? ctrl->temp_points[1] : 0x7FF)
1392 + << CPR4_MARGIN_TEMP_POINT1_SHIFT);
1393 +
1394 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
1395 + CPR4_MARGIN_TEMP_POINT0_MASK,
1396 + (ctrl->temp_band_count >= 2 ? ctrl->temp_points[0] : 0x7FF)
1397 + << CPR4_MARGIN_TEMP_POINT0_SHIFT);
1398 + return 0;
1399 +}
1400 +
1401 +/**
1402 + * cpr3_regulator_init_cpr4() - performs hardware initialization at the
1403 + * controller and thread level required for CPR4 operation.
1404 + * @ctrl: Pointer to the CPR3 controller
1405 + *
1406 + * CPR interface/bus clocks must be enabled before calling this function.
1407 + * This function allocates sdelta structures and sdelta tables for aggregated
1408 + * corners of the controller and its threads.
1409 + *
1410 + * Return: 0 on success, errno on failure
1411 + */
1412 +static int cpr3_regulator_init_cpr4(struct cpr3_controller *ctrl)
1413 +{
1414 + struct cpr3_thread *thread;
1415 + struct cpr3_regulator *vreg;
1416 + struct cpr4_sdelta *sdelta;
1417 + int i, j, ctrl_max_core_count, thread_max_core_count, rc = 0;
1418 + bool ctrl_valid_sdelta, thread_valid_sdelta;
1419 + u32 pmic_step_size = 1;
1420 + int thread_id = 0;
1421 + u64 temp;
1422 +
1423 + if (ctrl->supports_hw_closed_loop) {
1424 + if (ctrl->saw_use_unit_mV)
1425 + pmic_step_size = ctrl->step_volt / 1000;
1426 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1427 + CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK,
1428 + (pmic_step_size
1429 + << CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT));
1430 +
1431 + cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
1432 + CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK,
1433 + (ctrl->down_error_step_limit
1434 + << CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT));
1435 +
1436 + cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
1437 + CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK,
1438 + (ctrl->up_error_step_limit
1439 + << CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT));
1440 +
1441 + /*
1442 + * Enable thread aggregation regardless of which threads are
1443 + * enabled or disabled.
1444 + */
1445 + cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP,
1446 + CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
1447 + CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
1448 +
1449 + switch (ctrl->thread_count) {
1450 + case 0:
1451 + /* Disable both threads */
1452 + cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(0),
1453 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1454 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
1455 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1456 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
1457 +
1458 + cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(1),
1459 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1460 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
1461 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1462 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
1463 + break;
1464 + case 1:
1465 + /* Disable unused thread */
1466 + thread_id = ctrl->thread[0].thread_id ? 0 : 1;
1467 + cpr3_masked_write(ctrl,
1468 + CPR4_REG_CPR_MASK_THREAD(thread_id),
1469 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1470 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
1471 + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
1472 + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
1473 + break;
1474 + }
1475 + }
1476 +
1477 + if (!ctrl->allow_core_count_adj && !ctrl->allow_temp_adj
1478 + && !ctrl->allow_boost) {
1479 + /*
1480 + * Skip below configuration as none of the features
1481 + * are enabled.
1482 + */
1483 + return rc;
1484 + }
1485 +
1486 + if (ctrl->supports_hw_closed_loop)
1487 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1488 + CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN,
1489 + CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN);
1490 +
1491 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1492 + CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK,
1493 + ctrl->step_quot_fixed
1494 + << CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT);
1495 +
1496 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1497 + CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN,
1498 + (ctrl->use_dynamic_step_quot
1499 + ? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0));
1500 +
1501 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1502 + CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK,
1503 + ctrl->initial_temp_band
1504 + << CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT);
1505 +
1506 + rc = cpr4_regulator_init_temp_points(ctrl);
1507 + if (rc) {
1508 + cpr3_err(ctrl, "initialize temp points failed, rc=%d\n", rc);
1509 + return rc;
1510 + }
1511 +
1512 + if (ctrl->voltage_settling_time) {
1513 + /*
1514 + * Configure the settling timer used to account for
1515 + * one VDD supply step.
1516 + */
1517 + temp = (u64)ctrl->cpr_clock_rate
1518 + * (u64)ctrl->voltage_settling_time;
1519 + do_div(temp, 1000000000);
1520 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE_TIMERS,
1521 + CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK,
1522 + temp
1523 + << CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT);
1524 + }
1525 +
1526 + /*
1527 + * Allocate memory for cpr4_sdelta structure and sdelta table for
1528 + * controller aggregated corner by finding the maximum core count
1529 + * used by any cpr3 regulators.
1530 + */
1531 + ctrl_max_core_count = 1;
1532 + ctrl_valid_sdelta = false;
1533 + for (i = 0; i < ctrl->thread_count; i++) {
1534 + thread = &ctrl->thread[i];
1535 +
1536 + /*
1537 + * Allocate memory for cpr4_sdelta structure and sdelta table
1538 + * for thread aggregated corner by finding the maximum core
1539 + * count used by any cpr3 regulators of the thread.
1540 + */
1541 + thread_max_core_count = 1;
1542 + thread_valid_sdelta = false;
1543 + for (j = 0; j < thread->vreg_count; j++) {
1544 + vreg = &thread->vreg[j];
1545 + thread_max_core_count = max(thread_max_core_count,
1546 + vreg->max_core_count);
1547 + thread_valid_sdelta |= (vreg->allow_core_count_adj
1548 + | vreg->allow_temp_adj
1549 + | vreg->allow_boost);
1550 + }
1551 + if (thread_valid_sdelta) {
1552 + sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta),
1553 + GFP_KERNEL);
1554 + if (!sdelta)
1555 + return -ENOMEM;
1556 +
1557 + sdelta->table = devm_kcalloc(ctrl->dev,
1558 + thread_max_core_count
1559 + * ctrl->temp_band_count,
1560 + sizeof(*sdelta->table),
1561 + GFP_KERNEL);
1562 + if (!sdelta->table)
1563 + return -ENOMEM;
1564 +
1565 + sdelta->boost_table = devm_kcalloc(ctrl->dev,
1566 + ctrl->temp_band_count,
1567 + sizeof(*sdelta->boost_table),
1568 + GFP_KERNEL);
1569 + if (!sdelta->boost_table)
1570 + return -ENOMEM;
1571 +
1572 + thread->aggr_corner.sdelta = sdelta;
1573 + }
1574 +
1575 + ctrl_valid_sdelta |= thread_valid_sdelta;
1576 + ctrl_max_core_count = max(ctrl_max_core_count,
1577 + thread_max_core_count);
1578 + }
1579 +
1580 + if (ctrl_valid_sdelta) {
1581 + sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta), GFP_KERNEL);
1582 + if (!sdelta)
1583 + return -ENOMEM;
1584 +
1585 + sdelta->table = devm_kcalloc(ctrl->dev, ctrl_max_core_count
1586 + * ctrl->temp_band_count,
1587 + sizeof(*sdelta->table), GFP_KERNEL);
1588 + if (!sdelta->table)
1589 + return -ENOMEM;
1590 +
1591 + sdelta->boost_table = devm_kcalloc(ctrl->dev,
1592 + ctrl->temp_band_count,
1593 + sizeof(*sdelta->boost_table),
1594 + GFP_KERNEL);
1595 + if (!sdelta->boost_table)
1596 + return -ENOMEM;
1597 +
1598 + ctrl->aggr_corner.sdelta = sdelta;
1599 + }
1600 +
1601 + return 0;
1602 +}
1603 +
1604 +/**
1605 + * cpr3_write_temp_core_margin() - programs hardware SDELTA registers with
1606 + * the voltage margin adjustments that need to be applied for
1607 + * different online core-count and temperature bands.
1608 + * @ctrl: Pointer to the CPR3 controller
1609 + * @addr: SDELTA register address
1610 + * @temp_core_adj: Array of voltage margin values for different temperature
1611 + * bands.
1612 + *
1613 + * CPR interface/bus clocks must be enabled before calling this function.
1614 + *
1615 + * Return: none
1616 + */
1617 +static void cpr3_write_temp_core_margin(struct cpr3_controller *ctrl,
1618 + int addr, int *temp_core_adj)
1619 +{
1620 + int i, margin_steps;
1621 + u32 reg = 0;
1622 +
1623 + for (i = 0; i < ctrl->temp_band_count; i++) {
1624 + margin_steps = max(min(temp_core_adj[i], 127), -128);
1625 + reg |= (margin_steps & CPR4_MARGIN_TEMP_CORE_ADJ_MASK) <<
1626 + (i * CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT);
1627 + }
1628 +
1629 + cpr3_write(ctrl, addr, reg);
1630 + cpr3_debug(ctrl, "sdelta offset=0x%08x, val=0x%08x\n", addr, reg);
1631 +}
1632 +
1633 +/**
1634 + * cpr3_controller_program_sdelta() - programs hardware SDELTA registers with
1635 + * the voltage margin adjustments that need to be applied at
1636 + * different online core-count and temperature bands. Also,
1637 + * programs hardware register configuration for per-online-core
1638 + * and per-temperature based adjustments.
1639 + * @ctrl: Pointer to the CPR3 controller
1640 + *
1641 + * CPR interface/bus clocks must be enabled before calling this function.
1642 + *
1643 + * Return: 0 on success, errno on failure
1644 + */
1645 +static int cpr3_controller_program_sdelta(struct cpr3_controller *ctrl)
1646 +{
1647 + struct cpr3_corner *corner = &ctrl->aggr_corner;
1648 + struct cpr4_sdelta *sdelta = corner->sdelta;
1649 + int i, index, max_core_count, rc = 0;
1650 + bool cpr_enabled = ctrl->cpr_enabled;
1651 +
1652 + if (!sdelta)
1653 + /* cpr4_sdelta not defined for current aggregated corner */
1654 + return 0;
1655 +
1656 + if (ctrl->supports_hw_closed_loop && ctrl->cpr_enabled) {
1657 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1658 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
1659 + (ctrl->use_hw_closed_loop && !sdelta->allow_boost)
1660 + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE : 0);
1661 + }
1662 +
1663 + if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj
1664 + && !sdelta->allow_boost) {
1665 + /*
1666 + * Per-online-core, per-temperature and voltage boost
1667 + * adjustments are disabled for this aggregation corner.
1668 + */
1669 + return 0;
1670 + }
1671 +
1672 + /* Ensure that CPR clocks are enabled before writing to registers. */
1673 + if (!cpr_enabled) {
1674 + rc = cpr3_clock_enable(ctrl);
1675 + if (rc) {
1676 + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
1677 + return rc;
1678 + }
1679 + ctrl->cpr_enabled = true;
1680 + }
1681 +
1682 + max_core_count = sdelta->max_core_count;
1683 +
1684 + if (sdelta->allow_core_count_adj || sdelta->allow_temp_adj) {
1685 + if (sdelta->allow_core_count_adj) {
1686 + /* Program TEMP_CORE0 to same margins as TEMP_CORE1 */
1687 + cpr3_write_temp_core_margin(ctrl,
1688 + CPR4_REG_MARGIN_TEMP_CORE(0),
1689 + &sdelta->table[0]);
1690 + }
1691 +
1692 + for (i = 0; i < max_core_count; i++) {
1693 + index = i * sdelta->temp_band_count;
1694 + /*
1695 + * Program TEMP_COREi with voltage margin adjustments
1696 + * that need to be applied when the number of cores
1697 + * becomes i.
1698 + */
1699 + cpr3_write_temp_core_margin(ctrl,
1700 + CPR4_REG_MARGIN_TEMP_CORE(
1701 + sdelta->allow_core_count_adj
1702 + ? i + 1 : max_core_count),
1703 + &sdelta->table[index]);
1704 + }
1705 + }
1706 +
1707 + if (sdelta->allow_boost) {
1708 + /* Program only boost_num_cores row of SDELTA */
1709 + cpr3_write_temp_core_margin(ctrl,
1710 + CPR4_REG_MARGIN_TEMP_CORE(sdelta->boost_num_cores),
1711 + &sdelta->boost_table[0]);
1712 + }
1713 +
1714 + if (!sdelta->allow_core_count_adj && !sdelta->allow_boost) {
1715 + cpr3_masked_write(ctrl, CPR4_REG_MISC,
1716 + CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
1717 + max_core_count
1718 + << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
1719 + }
1720 +
1721 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1722 + CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
1723 + | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
1724 + | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
1725 + | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
1726 + | CPR4_MARGIN_ADJ_CTL_BOOST_EN,
1727 + max_core_count << CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT
1728 + | ((sdelta->allow_core_count_adj || sdelta->allow_boost)
1729 + ? CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN : 0)
1730 + | ((sdelta->allow_temp_adj && ctrl->supports_hw_closed_loop)
1731 + ? CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN : 0)
1732 + | (((ctrl->use_hw_closed_loop && !sdelta->allow_boost)
1733 + || !ctrl->supports_hw_closed_loop)
1734 + ? CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN : 0)
1735 + | (sdelta->allow_boost
1736 + ? CPR4_MARGIN_ADJ_CTL_BOOST_EN : 0));
1737 +
1738 + /*
1739 + * Ensure that all previous CPR register writes have completed before
1740 + * continuing.
1741 + */
1742 + mb();
1743 +
1744 + /* Turn off CPR clocks if they were off before this function call. */
1745 + if (!cpr_enabled) {
1746 + cpr3_clock_disable(ctrl);
1747 + ctrl->cpr_enabled = false;
1748 + }
1749 +
1750 + return 0;
1751 +}
1752 +
1753 +/**
1754 + * cpr3_regulator_init_ctrl() - performs hardware initialization of CPR
1755 + * controller registers
1756 + * @ctrl: Pointer to the CPR3 controller
1757 + *
1758 + * Return: 0 on success, errno on failure
1759 + */
1760 +static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl)
1761 +{
1762 + int i, j, k, m, rc;
1763 + u32 ro_used = 0;
1764 + u32 gcnt, cont_dly, up_down_dly, val;
1765 + u64 temp;
1766 + char *mode;
1767 +
1768 + if (ctrl->core_clk) {
1769 + rc = clk_set_rate(ctrl->core_clk, ctrl->cpr_clock_rate);
1770 + if (rc) {
1771 + cpr3_err(ctrl, "clk_set_rate(core_clk, %u) failed, rc=%d\n",
1772 + ctrl->cpr_clock_rate, rc);
1773 + return rc;
1774 + }
1775 + }
1776 +
1777 + rc = cpr3_clock_enable(ctrl);
1778 + if (rc) {
1779 + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
1780 + return rc;
1781 + }
1782 + ctrl->cpr_enabled = true;
1783 +
1784 + /* Find all RO's used by any corner of any regulator. */
1785 + for (i = 0; i < ctrl->thread_count; i++)
1786 + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
1787 + for (k = 0; k < ctrl->thread[i].vreg[j].corner_count;
1788 + k++)
1789 + for (m = 0; m < CPR3_RO_COUNT; m++)
1790 + if (ctrl->thread[i].vreg[j].corner[k].
1791 + target_quot[m])
1792 + ro_used |= BIT(m);
1793 +
1794 + /* Configure the GCNT of the RO's that will be used */
1795 + gcnt = cpr3_regulator_get_gcnt(ctrl);
1796 + for (i = 0; i < CPR3_RO_COUNT; i++)
1797 + if (ro_used & BIT(i))
1798 + cpr3_write(ctrl, CPR3_REG_GCNT(i), gcnt);
1799 +
1800 + /* Configure the loop delay time */
1801 + temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->loop_time;
1802 + do_div(temp, 1000000000);
1803 + cont_dly = temp;
1804 + if (ctrl->supports_hw_closed_loop
1805 + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
1806 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly);
1807 + else
1808 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, cont_dly);
1809 +
1810 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
1811 + temp = (u64)ctrl->cpr_clock_rate *
1812 + (u64)ctrl->up_down_delay_time;
1813 + do_div(temp, 1000000000);
1814 + up_down_dly = temp;
1815 + if (ctrl->supports_hw_closed_loop)
1816 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
1817 + up_down_dly);
1818 + cpr3_debug(ctrl, "up_down_dly=%u, up_down_delay_time=%u ns\n",
1819 + up_down_dly, ctrl->up_down_delay_time);
1820 + }
1821 +
1822 + cpr3_debug(ctrl, "cpr_clock_rate=%u HZ, sensor_time=%u ns, loop_time=%u ns, gcnt=%u, cont_dly=%u\n",
1823 + ctrl->cpr_clock_rate, ctrl->sensor_time, ctrl->loop_time,
1824 + gcnt, cont_dly);
1825 +
1826 + /* Configure CPR sensor operation */
1827 + val = (ctrl->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT)
1828 + & CPR3_CPR_CTL_IDLE_CLOCKS_MASK;
1829 + val |= (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
1830 + & CPR3_CPR_CTL_COUNT_MODE_MASK;
1831 + val |= (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT)
1832 + & CPR3_CPR_CTL_COUNT_REPEAT_MASK;
1833 + cpr3_write(ctrl, CPR3_REG_CPR_CTL, val);
1834 +
1835 + cpr3_debug(ctrl, "idle_clocks=%u, count_mode=%u, count_repeat=%u; CPR_CTL=0x%08X\n",
1836 + ctrl->idle_clocks, ctrl->count_mode, ctrl->count_repeat, val);
1837 +
1838 + /* Configure CPR default step quotients */
1839 + val = (ctrl->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT)
1840 + & CPR3_CPR_STEP_QUOT_MIN_MASK;
1841 + val |= (ctrl->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT)
1842 + & CPR3_CPR_STEP_QUOT_MAX_MASK;
1843 + cpr3_write(ctrl, CPR3_REG_CPR_STEP_QUOT, val);
1844 +
1845 + cpr3_debug(ctrl, "step_quot_min=%u, step_quot_max=%u; STEP_QUOT=0x%08X\n",
1846 + ctrl->step_quot_init_min, ctrl->step_quot_init_max, val);
1847 +
1848 + /* Configure the CPR sensor ownership */
1849 + for (i = 0; i < ctrl->sensor_count; i++)
1850 + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(i),
1851 + ctrl->sensor_owner[i]);
1852 +
1853 + /* Configure per-thread registers */
1854 + for (i = 0; i < ctrl->thread_count; i++) {
1855 + rc = cpr3_regulator_init_thread(&ctrl->thread[i]);
1856 + if (rc) {
1857 + cpr3_err(ctrl, "CPR thread register initialization failed, rc=%d\n",
1858 + rc);
1859 + return rc;
1860 + }
1861 + }
1862 +
1863 + if (ctrl->supports_hw_closed_loop) {
1864 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
1865 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
1866 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
1867 + ctrl->use_hw_closed_loop
1868 + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
1869 + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
1870 + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
1871 + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
1872 + ctrl->use_hw_closed_loop
1873 + ? CPR3_HW_CLOSED_LOOP_ENABLE
1874 + : CPR3_HW_CLOSED_LOOP_DISABLE);
1875 +
1876 + cpr3_debug(ctrl, "PD_THROTTLE=0x%08X\n",
1877 + ctrl->proc_clock_throttle);
1878 + }
1879 +
1880 + if ((ctrl->use_hw_closed_loop ||
1881 + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) &&
1882 + ctrl->vdd_limit_regulator) {
1883 + rc = regulator_enable(ctrl->vdd_limit_regulator);
1884 + if (rc) {
1885 + cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
1886 + rc);
1887 + return rc;
1888 + }
1889 + }
1890 + }
1891 +
1892 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
1893 + rc = cpr3_regulator_init_cpr4(ctrl);
1894 + if (rc) {
1895 + cpr3_err(ctrl, "CPR4-specific controller initialization failed, rc=%d\n",
1896 + rc);
1897 + return rc;
1898 + }
1899 + }
1900 +
1901 + /* Ensure that all register writes complete before disabling clocks. */
1902 + wmb();
1903 +
1904 + cpr3_clock_disable(ctrl);
1905 + ctrl->cpr_enabled = false;
1906 +
1907 + if (!ctrl->cpr_allowed_sw || !ctrl->cpr_allowed_hw)
1908 + mode = "open-loop";
1909 + else if (ctrl->supports_hw_closed_loop)
1910 + mode = ctrl->use_hw_closed_loop
1911 + ? "HW closed-loop" : "SW closed-loop";
1912 + else
1913 + mode = "closed-loop";
1914 +
1915 + cpr3_info(ctrl, "Default CPR mode = %s", mode);
1916 +
1917 + return 0;
1918 +}
1919 +
1920 +/**
1921 + * cpr3_regulator_set_target_quot() - configure the target quotient for each
1922 + * RO of the CPR3 thread and set the RO mask
1923 + * @thread: Pointer to the CPR3 thread
1924 + *
1925 + * Return: none
1926 + */
1927 +static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread)
1928 +{
1929 + u32 new_quot, last_quot;
1930 + int i;
1931 +
1932 + if (thread->aggr_corner.ro_mask == CPR3_RO_MASK
1933 + && thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK) {
1934 + /* Avoid writing target quotients since all RO's are masked. */
1935 + return;
1936 + } else if (thread->aggr_corner.ro_mask == CPR3_RO_MASK) {
1937 + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
1938 + CPR3_RO_MASK);
1939 + thread->last_closed_loop_aggr_corner.ro_mask = CPR3_RO_MASK;
1940 + /*
1941 + * Only the RO_MASK register needs to be written since all
1942 + * RO's are masked.
1943 + */
1944 + return;
1945 + } else if (thread->aggr_corner.ro_mask
1946 + != thread->last_closed_loop_aggr_corner.ro_mask) {
1947 + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
1948 + thread->aggr_corner.ro_mask);
1949 + }
1950 +
1951 + for (i = 0; i < CPR3_RO_COUNT; i++) {
1952 + new_quot = thread->aggr_corner.target_quot[i];
1953 + last_quot = thread->last_closed_loop_aggr_corner.target_quot[i];
1954 + if (new_quot != last_quot)
1955 + cpr3_write(thread->ctrl,
1956 + CPR3_REG_TARGET_QUOT(thread->thread_id, i),
1957 + new_quot);
1958 + }
1959 +
1960 + thread->last_closed_loop_aggr_corner = thread->aggr_corner;
1961 +
1962 + return;
1963 +}
1964 +
1965 +/**
1966 + * cpr3_update_vreg_closed_loop_volt() - update the last known settled
1967 + * closed loop voltage for a CPR3 regulator
1968 + * @vreg: Pointer to the CPR3 regulator
1969 + * @vdd_volt: Last known settled voltage in microvolts for the
1970 + * VDD supply
1971 + * @reg_last_measurement: Value read from the LAST_MEASUREMENT register
1972 + *
1973 + * Return: none
1974 + */
1975 +static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg,
1976 + int vdd_volt, u32 reg_last_measurement)
1977 +{
1978 + bool step_dn, step_up, aggr_step_up, aggr_step_dn, aggr_step_mid;
1979 + bool valid, pd_valid, saw_error;
1980 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
1981 + struct cpr3_corner *corner;
1982 + u32 id;
1983 +
1984 + if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID)
1985 + return;
1986 + else
1987 + corner = &vreg->corner[vreg->last_closed_loop_corner];
1988 +
1989 + if (vreg->thread->last_closed_loop_aggr_corner.ro_mask
1990 + == CPR3_RO_MASK || !vreg->aggregated) {
1991 + return;
1992 + } else if (!ctrl->cpr_enabled || !ctrl->last_corner_was_closed_loop) {
1993 + return;
1994 + } else if (ctrl->thread_count == 1
1995 + && vdd_volt >= corner->floor_volt
1996 + && vdd_volt <= corner->ceiling_volt) {
1997 + corner->last_volt = vdd_volt;
1998 + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
1999 + vreg->last_closed_loop_corner, corner->last_volt,
2000 + vreg->last_closed_loop_corner,
2001 + corner->ceiling_volt,
2002 + vreg->last_closed_loop_corner,
2003 + corner->floor_volt);
2004 + return;
2005 + } else if (!ctrl->supports_hw_closed_loop) {
2006 + return;
2007 + } else if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPR3) {
2008 + corner->last_volt = vdd_volt;
2009 + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
2010 + vreg->last_closed_loop_corner, corner->last_volt,
2011 + vreg->last_closed_loop_corner,
2012 + corner->ceiling_volt,
2013 + vreg->last_closed_loop_corner,
2014 + corner->floor_volt);
2015 + return;
2016 + }
2017 +
2018 + /* CPR clocks are on and HW closed loop is supported */
2019 + valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
2020 + if (!valid) {
2021 + cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X valid bit not set\n",
2022 + reg_last_measurement);
2023 + return;
2024 + }
2025 +
2026 + id = vreg->thread->thread_id;
2027 +
2028 + step_dn
2029 + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_DN(id));
2030 + step_up
2031 + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_UP(id));
2032 + aggr_step_dn = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_DN);
2033 + aggr_step_mid
2034 + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_MID);
2035 + aggr_step_up = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_UP);
2036 + saw_error = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_SAW_ERROR);
2037 + pd_valid
2038 + = !((((reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
2039 + >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT)
2040 + & vreg->pd_bypass_mask) == vreg->pd_bypass_mask);
2041 +
2042 + if (!pd_valid) {
2043 + cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X, all power domains bypassed\n",
2044 + reg_last_measurement);
2045 + return;
2046 + } else if (step_dn && step_up) {
2047 + cpr3_err(vreg, "both up and down status bits set, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
2048 + reg_last_measurement);
2049 + return;
2050 + } else if (aggr_step_dn && step_dn && vdd_volt < corner->last_volt
2051 + && vdd_volt >= corner->floor_volt) {
2052 + corner->last_volt = vdd_volt;
2053 + } else if (aggr_step_up && step_up && vdd_volt > corner->last_volt
2054 + && vdd_volt <= corner->ceiling_volt) {
2055 + corner->last_volt = vdd_volt;
2056 + } else if (aggr_step_mid
2057 + && vdd_volt >= corner->floor_volt
2058 + && vdd_volt <= corner->ceiling_volt) {
2059 + corner->last_volt = vdd_volt;
2060 + } else if (saw_error && (vdd_volt == corner->ceiling_volt
2061 + || vdd_volt == corner->floor_volt)) {
2062 + corner->last_volt = vdd_volt;
2063 + } else {
2064 + cpr3_debug(vreg, "last_volt not updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, vdd_volt=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
2065 + vreg->last_closed_loop_corner, corner->last_volt,
2066 + vreg->last_closed_loop_corner,
2067 + corner->ceiling_volt,
2068 + vreg->last_closed_loop_corner, corner->floor_volt,
2069 + vdd_volt, reg_last_measurement);
2070 + return;
2071 + }
2072 +
2073 + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
2074 + vreg->last_closed_loop_corner, corner->last_volt,
2075 + vreg->last_closed_loop_corner, corner->ceiling_volt,
2076 + vreg->last_closed_loop_corner, corner->floor_volt,
2077 + reg_last_measurement);
2078 +}
2079 +
2080 +/**
2081 + * cpr3_regulator_mem_acc_bhs_used() - determines if mem-acc regulators powered
2082 + * through a BHS are associated with the CPR3 controller or any of
2083 + * the CPR3 regulators it controls.
2084 + * @ctrl: Pointer to the CPR3 controller
2085 + *
2086 + * This function determines if the CPR3 controller or any of its CPR3 regulators
2087 + * need to manage mem-acc regulators that are currently powered through a BHS
2088 + * and whose corner selection is based upon a particular voltage threshold.
2089 + *
2090 + * Return: true or false
2091 + */
2092 +static bool cpr3_regulator_mem_acc_bhs_used(struct cpr3_controller *ctrl)
2093 +{
2094 + struct cpr3_regulator *vreg;
2095 + int i, j;
2096 +
2097 + if (!ctrl->mem_acc_threshold_volt)
2098 + return false;
2099 +
2100 + if (ctrl->mem_acc_regulator)
2101 + return true;
2102 +
2103 + for (i = 0; i < ctrl->thread_count; i++) {
2104 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
2105 + vreg = &ctrl->thread[i].vreg[j];
2106 +
2107 + if (vreg->mem_acc_regulator)
2108 + return true;
2109 + }
2110 + }
2111 +
2112 + return false;
2113 +}
2114 +
2115 +/**
2116 + * cpr3_regulator_config_bhs_mem_acc() - configure the mem-acc regulator
2117 + * settings for hardware blocks currently powered through the BHS.
2118 + * @ctrl: Pointer to the CPR3 controller
2119 + * @new_volt: New voltage in microvolts that VDD supply needs to
2120 + * end up at
2121 + * @last_volt: Pointer to the last known voltage in microvolts for the
2122 + * VDD supply
2123 + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
2124 + * corner aggregated from all CPR3 threads managed by the
2125 + * CPR3 controller
2126 + *
2127 + * This function programs the mem-acc regulator corners for CPR3 regulators
2128 + * whose LDO regulators are in bypassed state. The function also handles
2129 + * CPR3 controllers which utilize mem-acc regulators that operate independently
2130 + * from the LDO hardware and that must be programmed when the VDD supply
2131 + * crosses a particular voltage threshold.
2132 + *
2133 + * Return: 0 on success, errno on failure. If the VDD supply voltage is
2134 + * modified, last_volt is updated to reflect the new voltage setpoint.
2135 + */
2136 +static int cpr3_regulator_config_bhs_mem_acc(struct cpr3_controller *ctrl,
2137 + int new_volt, int *last_volt,
2138 + struct cpr3_corner *aggr_corner)
2139 +{
2140 + struct cpr3_regulator *vreg;
2141 + int i, j, rc, mem_acc_corn, safe_volt;
2142 + int mem_acc_volt = ctrl->mem_acc_threshold_volt;
2143 + int ref_volt;
2144 +
2145 + if (!cpr3_regulator_mem_acc_bhs_used(ctrl))
2146 + return 0;
2147 +
2148 + ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
2149 + new_volt;
2150 +
2151 + if (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
2152 + (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))) {
2153 + if (ref_volt < *last_volt)
2154 + safe_volt = max(mem_acc_volt, aggr_corner->last_volt);
2155 + else
2156 + safe_volt = max(mem_acc_volt, *last_volt);
2157 +
2158 + rc = regulator_set_voltage(ctrl->vdd_regulator, safe_volt,
2159 + new_volt < *last_volt ?
2160 + ctrl->aggr_corner.ceiling_volt :
2161 + new_volt);
2162 + if (rc) {
2163 + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
2164 + safe_volt, rc);
2165 + return rc;
2166 + }
2167 +
2168 + *last_volt = safe_volt;
2169 +
2170 + mem_acc_corn = ref_volt < mem_acc_volt ?
2171 + ctrl->mem_acc_corner_map[CPR3_MEM_ACC_LOW_CORNER] :
2172 + ctrl->mem_acc_corner_map[CPR3_MEM_ACC_HIGH_CORNER];
2173 +
2174 + if (ctrl->mem_acc_regulator) {
2175 + rc = regulator_set_voltage(ctrl->mem_acc_regulator,
2176 + mem_acc_corn, mem_acc_corn);
2177 + if (rc) {
2178 + cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
2179 + mem_acc_corn, rc);
2180 + return rc;
2181 + }
2182 + }
2183 +
2184 + for (i = 0; i < ctrl->thread_count; i++) {
2185 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
2186 + vreg = &ctrl->thread[i].vreg[j];
2187 +
2188 + if (!vreg->mem_acc_regulator)
2189 + continue;
2190 +
2191 + rc = regulator_set_voltage(
2192 + vreg->mem_acc_regulator, mem_acc_corn,
2193 + mem_acc_corn);
2194 + if (rc) {
2195 + cpr3_err(vreg, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
2196 + mem_acc_corn, rc);
2197 + return rc;
2198 + }
2199 + }
2200 + }
2201 + }
2202 +
2203 + return 0;
2204 +}
2205 +
2206 +/**
2207 + * cpr3_regulator_switch_apm_mode() - switch the mode of the APM controller
2208 + * associated with a given CPR3 controller
2209 + * @ctrl: Pointer to the CPR3 controller
2210 + * @new_volt: New voltage in microvolts that VDD supply needs to
2211 + * end up at
2212 + * @last_volt: Pointer to the last known voltage in microvolts for the
2213 + * VDD supply
2214 + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
2215 + * corner aggregated from all CPR3 threads managed by the
2216 + * CPR3 controller
2217 + *
2218 + * This function requests a switch of the APM mode while guaranteeing
2219 + * any LDO regulator hardware requirements are satisfied. The function must
2220 + * be called once it is known a new VDD supply setpoint crosses the APM
2221 + * voltage threshold.
2222 + *
2223 + * Return: 0 on success, errno on failure. If the VDD supply voltage is
2224 + * modified, last_volt is updated to reflect the new voltage setpoint.
2225 + */
2226 +static int cpr3_regulator_switch_apm_mode(struct cpr3_controller *ctrl,
2227 + int new_volt, int *last_volt,
2228 + struct cpr3_corner *aggr_corner)
2229 +{
2230 + struct regulator *vdd = ctrl->vdd_regulator;
2231 + int apm_volt = ctrl->apm_threshold_volt;
2232 + int orig_last_volt = *last_volt;
2233 + int rc;
2234 +
2235 + rc = regulator_set_voltage(vdd, apm_volt, apm_volt);
2236 + if (rc) {
2237 + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
2238 + apm_volt, rc);
2239 + return rc;
2240 + }
2241 +
2242 + *last_volt = apm_volt;
2243 +
2244 + rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt
2245 + ? ctrl->apm_high_supply : ctrl->apm_low_supply);
2246 + if (rc) {
2247 + cpr3_err(ctrl, "APM switch failed, rc=%d\n", rc);
2248 + /* Roll back the voltage. */
2249 + regulator_set_voltage(vdd, orig_last_volt, INT_MAX);
2250 + *last_volt = orig_last_volt;
2251 + return rc;
2252 + }
2253 + return 0;
2254 +}
2255 +
2256 +/**
2257 + * cpr3_regulator_config_voltage_crossings() - configure APM and mem-acc
2258 + * settings depending upon a new VDD supply setpoint
2259 + *
2260 + * @ctrl: Pointer to the CPR3 controller
2261 + * @new_volt: New voltage in microvolts that VDD supply needs to
2262 + * end up at
2263 + * @last_volt: Pointer to the last known voltage in microvolts for the
2264 + * VDD supply
2265 + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
2266 + * corner aggregated from all CPR3 threads managed by the
2267 + * CPR3 controller
2268 + *
2269 + * This function handles the APM and mem-acc regulator reconfiguration if
2270 + * the new VDD supply voltage will result in crossing their respective voltage
2271 + * thresholds.
2272 + *
2273 + * Return: 0 on success, errno on failure. If the VDD supply voltage is
2274 + * modified, last_volt is updated to reflect the new voltage setpoint.
2275 + */
2276 +static int cpr3_regulator_config_voltage_crossings(struct cpr3_controller *ctrl,
2277 + int new_volt, int *last_volt,
2278 + struct cpr3_corner *aggr_corner)
2279 +{
2280 + bool apm_crossing = false, mem_acc_crossing = false;
2281 + bool mem_acc_bhs_used;
2282 + int apm_volt = ctrl->apm_threshold_volt;
2283 + int mem_acc_volt = ctrl->mem_acc_threshold_volt;
2284 + int ref_volt, rc;
2285 +
2286 + if (ctrl->apm && apm_volt > 0
2287 + && ((*last_volt < apm_volt && apm_volt <= new_volt)
2288 + || (*last_volt >= apm_volt && apm_volt > new_volt)))
2289 + apm_crossing = true;
2290 +
2291 + mem_acc_bhs_used = cpr3_regulator_mem_acc_bhs_used(ctrl);
2292 +
2293 + ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
2294 + new_volt;
2295 +
2296 + if (mem_acc_bhs_used &&
2297 + (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
2298 + (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))))
2299 + mem_acc_crossing = true;
2300 +
2301 + if (apm_crossing && mem_acc_crossing) {
2302 + if ((new_volt < *last_volt && apm_volt >= mem_acc_volt) ||
2303 + (new_volt >= *last_volt && apm_volt < mem_acc_volt)) {
2304 + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
2305 + last_volt,
2306 + aggr_corner);
2307 + if (rc) {
2308 + cpr3_err(ctrl, "unable to switch APM mode\n");
2309 + return rc;
2310 + }
2311 +
2312 + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
2313 + last_volt, aggr_corner);
2314 + if (rc) {
2315 + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
2316 + return rc;
2317 + }
2318 + } else {
2319 + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
2320 + last_volt, aggr_corner);
2321 + if (rc) {
2322 + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
2323 + return rc;
2324 + }
2325 +
2326 + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
2327 + last_volt,
2328 + aggr_corner);
2329 + if (rc) {
2330 + cpr3_err(ctrl, "unable to switch APM mode\n");
2331 + return rc;
2332 + }
2333 + }
2334 + } else if (apm_crossing) {
2335 + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, last_volt,
2336 + aggr_corner);
2337 + if (rc) {
2338 + cpr3_err(ctrl, "unable to switch APM mode\n");
2339 + return rc;
2340 + }
2341 + } else if (mem_acc_crossing) {
2342 + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
2343 + last_volt, aggr_corner);
2344 + if (rc) {
2345 + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
2346 + return rc;
2347 + }
2348 + }
2349 +
2350 + return 0;
2351 +}
2352 +
2353 +/**
2354 + * cpr3_regulator_config_mem_acc() - configure the corner of the mem-acc
2355 + * regulator associated with the CPR3 controller
2356 + * @ctrl: Pointer to the CPR3 controller
2357 + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
2358 + * corner aggregated from all CPR3 threads managed by the
2359 + * CPR3 controller
2360 + *
2361 + * Return: 0 on success, errno on failure
2362 + */
2363 +static int cpr3_regulator_config_mem_acc(struct cpr3_controller *ctrl,
2364 + struct cpr3_corner *aggr_corner)
2365 +{
2366 + int rc;
2367 +
2368 + if (ctrl->mem_acc_regulator && aggr_corner->mem_acc_volt) {
2369 + rc = regulator_set_voltage(ctrl->mem_acc_regulator,
2370 + aggr_corner->mem_acc_volt,
2371 + aggr_corner->mem_acc_volt);
2372 + if (rc) {
2373 + cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
2374 + aggr_corner->mem_acc_volt, rc);
2375 + return rc;
2376 + }
2377 + }
2378 +
2379 + return 0;
2380 +}
2381 +
2382 +/**
2383 + * cpr3_regulator_scale_vdd_voltage() - scale the CPR controlled VDD supply
2384 + * voltage to the new level while satisfying any other hardware
2385 + * requirements
2386 + * @ctrl: Pointer to the CPR3 controller
2387 + * @new_volt: New voltage in microvolts that VDD supply needs to end
2388 + * up at
2389 + * @last_volt: Last known voltage in microvolts for the VDD supply
2390 + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
2391 + * corner aggregated from all CPR3 threads managed by the
2392 + * CPR3 controller
2393 + *
2394 + * This function scales the CPR controlled VDD supply voltage from its
2395 + * current level to the new voltage that is specified. If the supply is
2396 + * configured to use the APM and the APM threshold is crossed as a result of
2397 + * the voltage scaling, then this function also stops at the APM threshold,
2398 + * switches the APM source, and finally sets the final new voltage.
2399 + *
2400 + * Return: 0 on success, errno on failure
2401 + */
2402 +static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl,
2403 + int new_volt, int last_volt,
2404 + struct cpr3_corner *aggr_corner)
2405 +{
2406 + struct regulator *vdd = ctrl->vdd_regulator;
2407 + int rc;
2408 +
2409 + if (new_volt < last_volt) {
2410 + rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
2411 + if (rc)
2412 + return rc;
2413 + } else {
2414 + /* Increasing VDD voltage */
2415 + if (ctrl->system_regulator) {
2416 + rc = regulator_set_voltage(ctrl->system_regulator,
2417 + aggr_corner->system_volt, INT_MAX);
2418 + if (rc) {
2419 + cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
2420 + aggr_corner->system_volt, rc);
2421 + return rc;
2422 + }
2423 + }
2424 + }
2425 +
2426 + rc = cpr3_regulator_config_voltage_crossings(ctrl, new_volt, &last_volt,
2427 + aggr_corner);
2428 + if (rc) {
2429 + cpr3_err(ctrl, "unable to handle voltage threshold crossing configurations, rc=%d\n",
2430 + rc);
2431 + return rc;
2432 + }
2433 +
2434 + /*
2435 + * Subtract a small amount from the min_uV parameter so that the
2436 + * set voltage request is not dropped by the framework due to being
2437 + * duplicate. This is needed in order to switch from hardware
2438 + * closed-loop to open-loop successfully.
2439 + */
2440 + rc = regulator_set_voltage(vdd, new_volt - (ctrl->cpr_enabled ? 0 : 1),
2441 + aggr_corner->ceiling_volt);
2442 + if (rc) {
2443 + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
2444 + new_volt, rc);
2445 + return rc;
2446 + }
2447 +
2448 + if (new_volt == last_volt && ctrl->supports_hw_closed_loop
2449 + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
2450 + /*
2451 + * CPR4 features enforce voltage reprogramming when the last
2452 + * set voltage and new set voltage are same. This way, we can
2453 + * ensure that SAW PMIC STATUS register is updated with newly
2454 + * programmed voltage.
2455 + */
2456 + rc = regulator_sync_voltage(vdd);
2457 + if (rc) {
2458 + cpr3_err(ctrl, "regulator_sync_voltage(vdd) == %d failed, rc=%d\n",
2459 + new_volt, rc);
2460 + return rc;
2461 + }
2462 + }
2463 +
2464 + if (new_volt >= last_volt) {
2465 + rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
2466 + if (rc)
2467 + return rc;
2468 + } else {
2469 + /* Decreasing VDD voltage */
2470 + if (ctrl->system_regulator) {
2471 + rc = regulator_set_voltage(ctrl->system_regulator,
2472 + aggr_corner->system_volt, INT_MAX);
2473 + if (rc) {
2474 + cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
2475 + aggr_corner->system_volt, rc);
2476 + return rc;
2477 + }
2478 + }
2479 + }
2480 +
2481 + return 0;
2482 +}
2483 +
2484 +/**
2485 + * cpr3_regulator_get_dynamic_floor_volt() - returns the current dynamic floor
2486 + * voltage based upon static configurations and the state of all
2487 + * power domains during the last CPR measurement
2488 + * @ctrl: Pointer to the CPR3 controller
2489 + * @reg_last_measurement: Value read from the LAST_MEASUREMENT register
2490 + *
2491 + * When using HW closed-loop, the dynamic floor voltage is always returned
2492 + * regardless of the current state of the power domains.
2493 + *
2494 + * Return: dynamic floor voltage in microvolts or 0 if dynamic floor is not
2495 + * currently required
2496 + */
2497 +static int cpr3_regulator_get_dynamic_floor_volt(struct cpr3_controller *ctrl,
2498 + u32 reg_last_measurement)
2499 +{
2500 + int dynamic_floor_volt = 0;
2501 + struct cpr3_regulator *vreg;
2502 + bool valid, pd_valid;
2503 + u32 bypass_bits;
2504 + int i, j;
2505 +
2506 + if (!ctrl->supports_hw_closed_loop)
2507 + return 0;
2508 +
2509 + if (likely(!ctrl->use_hw_closed_loop)) {
2510 + valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
2511 + bypass_bits
2512 + = (reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
2513 + >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT;
2514 + } else {
2515 + /*
2516 + * Ensure that the dynamic floor voltage is always used for
2517 + * HW closed-loop since the conditions below cannot be evaluated
2518 + * after each CPR measurement.
2519 + */
2520 + valid = false;
2521 + bypass_bits = 0;
2522 + }
2523 +
2524 + for (i = 0; i < ctrl->thread_count; i++) {
2525 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
2526 + vreg = &ctrl->thread[i].vreg[j];
2527 +
2528 + if (!vreg->uses_dynamic_floor)
2529 + continue;
2530 +
2531 + pd_valid = !((bypass_bits & vreg->pd_bypass_mask)
2532 + == vreg->pd_bypass_mask);
2533 +
2534 + if (!valid || !pd_valid)
2535 + dynamic_floor_volt = max(dynamic_floor_volt,
2536 + vreg->corner[
2537 + vreg->dynamic_floor_corner].last_volt);
2538 + }
2539 + }
2540 +
2541 + return dynamic_floor_volt;
2542 +}
2543 +
2544 +/**
2545 + * cpr3_regulator_max_sdelta_diff() - returns the maximum voltage difference in
2546 + * microvolts that can result from different operating conditions
2547 + * for the specified sdelta struct
2548 + * @sdelta: Pointer to the sdelta structure
2549 + * @step_volt: Step size in microvolts between available set
2550 + * points of the VDD supply.
2551 + *
2552 + * Return: voltage difference between the highest and lowest adjustments if
2553 + * sdelta and sdelta->table are valid, else 0.
2554 + */
2555 +static int cpr3_regulator_max_sdelta_diff(const struct cpr4_sdelta *sdelta,
2556 + int step_volt)
2557 +{
2558 + int i, j, index, sdelta_min = INT_MAX, sdelta_max = INT_MIN;
2559 +
2560 + if (!sdelta || !sdelta->table)
2561 + return 0;
2562 +
2563 + for (i = 0; i < sdelta->max_core_count; i++) {
2564 + for (j = 0; j < sdelta->temp_band_count; j++) {
2565 + index = i * sdelta->temp_band_count + j;
2566 + sdelta_min = min(sdelta_min, sdelta->table[index]);
2567 + sdelta_max = max(sdelta_max, sdelta->table[index]);
2568 + }
2569 + }
2570 +
2571 + return (sdelta_max - sdelta_min) * step_volt;
2572 +}
2573 +
2574 +/**
2575 + * cpr3_regulator_aggregate_sdelta() - check open-loop voltages of current
2576 + * aggregated corner and current corner of a given regulator
2577 + * and adjust the sdelta strucuture data of aggregate corner.
2578 + * @aggr_corner: Pointer to accumulated aggregated corner which
2579 + * is both an input and an output
2580 + * @corner: Pointer to the corner to be aggregated with
2581 + * aggr_corner
2582 + * @step_volt: Step size in microvolts between available set
2583 + * points of the VDD supply.
2584 + *
2585 + * Return: none
2586 + */
2587 +static void cpr3_regulator_aggregate_sdelta(
2588 + struct cpr3_corner *aggr_corner,
2589 + const struct cpr3_corner *corner, int step_volt)
2590 +{
2591 + struct cpr4_sdelta *aggr_sdelta, *sdelta;
2592 + int aggr_core_count, core_count, temp_band_count;
2593 + u32 aggr_index, index;
2594 + int i, j, sdelta_size, cap_steps, adjust_sdelta;
2595 +
2596 + aggr_sdelta = aggr_corner->sdelta;
2597 + sdelta = corner->sdelta;
2598 +
2599 + if (aggr_corner->open_loop_volt < corner->open_loop_volt) {
2600 + /*
2601 + * Found the new dominant regulator as its open-loop requirement
2602 + * is higher than previous dominant regulator. Calculate cap
2603 + * voltage to limit the SDELTA values to make sure the runtime
2604 + * (Core-count/temp) adjustments do not violate other
2605 + * regulators' voltage requirements. Use cpr4_sdelta values of
2606 + * new dominant regulator.
2607 + */
2608 + aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
2609 + (corner->open_loop_volt -
2610 + aggr_corner->open_loop_volt));
2611 +
2612 + /* Clear old data in the sdelta table */
2613 + sdelta_size = aggr_sdelta->max_core_count
2614 + * aggr_sdelta->temp_band_count;
2615 +
2616 + if (aggr_sdelta->allow_core_count_adj
2617 + || aggr_sdelta->allow_temp_adj)
2618 + memset(aggr_sdelta->table, 0, sdelta_size
2619 + * sizeof(*aggr_sdelta->table));
2620 +
2621 + if (sdelta->allow_temp_adj || sdelta->allow_core_count_adj) {
2622 + /* Copy new data in sdelta table */
2623 + sdelta_size = sdelta->max_core_count
2624 + * sdelta->temp_band_count;
2625 + if (sdelta->table)
2626 + memcpy(aggr_sdelta->table, sdelta->table,
2627 + sdelta_size * sizeof(*sdelta->table));
2628 + }
2629 +
2630 + if (sdelta->allow_boost) {
2631 + memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
2632 + sdelta->temp_band_count
2633 + * sizeof(*sdelta->boost_table));
2634 + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
2635 + } else if (aggr_sdelta->allow_boost) {
2636 + for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
2637 + adjust_sdelta = (corner->open_loop_volt
2638 + - aggr_corner->open_loop_volt)
2639 + / step_volt;
2640 + aggr_sdelta->boost_table[i] += adjust_sdelta;
2641 + aggr_sdelta->boost_table[i]
2642 + = min(aggr_sdelta->boost_table[i], 0);
2643 + }
2644 + }
2645 +
2646 + aggr_corner->open_loop_volt = corner->open_loop_volt;
2647 + aggr_sdelta->allow_temp_adj = sdelta->allow_temp_adj;
2648 + aggr_sdelta->allow_core_count_adj
2649 + = sdelta->allow_core_count_adj;
2650 + aggr_sdelta->max_core_count = sdelta->max_core_count;
2651 + aggr_sdelta->temp_band_count = sdelta->temp_band_count;
2652 + } else if (aggr_corner->open_loop_volt > corner->open_loop_volt) {
2653 + /*
2654 + * Adjust the cap voltage if the open-loop requirement of new
2655 + * regulator is the next highest.
2656 + */
2657 + aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
2658 + (aggr_corner->open_loop_volt
2659 + - corner->open_loop_volt));
2660 +
2661 + if (sdelta->allow_boost) {
2662 + for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
2663 + adjust_sdelta = (aggr_corner->open_loop_volt
2664 + - corner->open_loop_volt)
2665 + / step_volt;
2666 + aggr_sdelta->boost_table[i] =
2667 + sdelta->boost_table[i] + adjust_sdelta;
2668 + aggr_sdelta->boost_table[i]
2669 + = min(aggr_sdelta->boost_table[i], 0);
2670 + }
2671 + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
2672 + }
2673 + } else {
2674 + /*
2675 + * Found another dominant regulator with same open-loop
2676 + * requirement. Make cap voltage to '0'. Disable core-count
2677 + * adjustments as we couldn't support for both regulators.
2678 + * Keep enable temp based adjustments if enabled for both
2679 + * regulators and choose mininum margin adjustment values
2680 + * between them.
2681 + */
2682 + aggr_sdelta->cap_volt = 0;
2683 + aggr_sdelta->allow_core_count_adj = false;
2684 +
2685 + if (aggr_sdelta->allow_temp_adj
2686 + && sdelta->allow_temp_adj) {
2687 + aggr_core_count = aggr_sdelta->max_core_count - 1;
2688 + core_count = sdelta->max_core_count - 1;
2689 + temp_band_count = sdelta->temp_band_count;
2690 + for (j = 0; j < temp_band_count; j++) {
2691 + aggr_index = aggr_core_count * temp_band_count
2692 + + j;
2693 + index = core_count * temp_band_count + j;
2694 + aggr_sdelta->table[aggr_index] =
2695 + min(aggr_sdelta->table[aggr_index],
2696 + sdelta->table[index]);
2697 + }
2698 + } else {
2699 + aggr_sdelta->allow_temp_adj = false;
2700 + }
2701 +
2702 + if (sdelta->allow_boost) {
2703 + memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
2704 + sdelta->temp_band_count
2705 + * sizeof(*sdelta->boost_table));
2706 + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
2707 + }
2708 + }
2709 +
2710 + /* Keep non-dominant clients boost enable state */
2711 + aggr_sdelta->allow_boost |= sdelta->allow_boost;
2712 + if (aggr_sdelta->allow_boost)
2713 + aggr_sdelta->allow_core_count_adj = false;
2714 +
2715 + if (aggr_sdelta->cap_volt && !(aggr_sdelta->cap_volt == INT_MAX)) {
2716 + core_count = aggr_sdelta->max_core_count;
2717 + temp_band_count = aggr_sdelta->temp_band_count;
2718 + /*
2719 + * Convert cap voltage from uV to PMIC steps and use to limit
2720 + * sdelta margin adjustments.
2721 + */
2722 + cap_steps = aggr_sdelta->cap_volt / step_volt;
2723 + for (i = 0; i < core_count; i++)
2724 + for (j = 0; j < temp_band_count; j++) {
2725 + index = i * temp_band_count + j;
2726 + aggr_sdelta->table[index] =
2727 + min(aggr_sdelta->table[index],
2728 + cap_steps);
2729 + }
2730 + }
2731 +}
2732 +
2733 +/**
2734 + * cpr3_regulator_aggregate_corners() - aggregate two corners together
2735 + * @aggr_corner: Pointer to accumulated aggregated corner which
2736 + * is both an input and an output
2737 + * @corner: Pointer to the corner to be aggregated with
2738 + * aggr_corner
2739 + * @aggr_quot: Flag indicating that target quotients should be
2740 + * aggregated as well.
2741 + * @step_volt: Step size in microvolts between available set
2742 + * points of the VDD supply.
2743 + *
2744 + * Return: none
2745 + */
2746 +static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner,
2747 + const struct cpr3_corner *corner, bool aggr_quot,
2748 + int step_volt)
2749 +{
2750 + int i;
2751 +
2752 + aggr_corner->ceiling_volt
2753 + = max(aggr_corner->ceiling_volt, corner->ceiling_volt);
2754 + aggr_corner->floor_volt
2755 + = max(aggr_corner->floor_volt, corner->floor_volt);
2756 + aggr_corner->last_volt
2757 + = max(aggr_corner->last_volt, corner->last_volt);
2758 + aggr_corner->system_volt
2759 + = max(aggr_corner->system_volt, corner->system_volt);
2760 + aggr_corner->mem_acc_volt
2761 + = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt);
2762 + aggr_corner->irq_en |= corner->irq_en;
2763 + aggr_corner->use_open_loop |= corner->use_open_loop;
2764 +
2765 + if (aggr_quot) {
2766 + aggr_corner->ro_mask &= corner->ro_mask;
2767 +
2768 + for (i = 0; i < CPR3_RO_COUNT; i++)
2769 + aggr_corner->target_quot[i]
2770 + = max(aggr_corner->target_quot[i],
2771 + corner->target_quot[i]);
2772 + }
2773 +
2774 + if (aggr_corner->sdelta && corner->sdelta
2775 + && (aggr_corner->sdelta->table
2776 + || aggr_corner->sdelta->boost_table)) {
2777 + cpr3_regulator_aggregate_sdelta(aggr_corner, corner, step_volt);
2778 + } else {
2779 + aggr_corner->open_loop_volt
2780 + = max(aggr_corner->open_loop_volt,
2781 + corner->open_loop_volt);
2782 + }
2783 +}
2784 +
2785 +/**
2786 + * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller
2787 + * to reflect the corners used by all CPR3 regulators as well as
2788 + * the CPR operating mode
2789 + * @ctrl: Pointer to the CPR3 controller
2790 + *
2791 + * This function aggregates the CPR parameters for all CPR3 regulators
2792 + * associated with the VDD supply. Upon success, it sets the aggregated last
2793 + * known good voltage.
2794 + *
2795 + * The VDD supply voltage will not be physically configured unless this
2796 + * condition is met by at least one of the regulators of the controller:
2797 + * regulator->vreg_enabled == true &&
2798 + * regulator->current_corner != CPR3_REGULATOR_CORNER_INVALID
2799 + *
2800 + * CPR registers for the controller and each thread are updated as long as
2801 + * ctrl->cpr_enabled == true.
2802 + *
2803 + * Note, CPR3 controller lock must be held by the caller.
2804 + *
2805 + * Return: 0 on success, errno on failure
2806 + */
2807 +static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
2808 +{
2809 + struct cpr3_corner aggr_corner = {};
2810 + struct cpr3_thread *thread;
2811 + struct cpr3_regulator *vreg;
2812 + struct cpr4_sdelta *sdelta;
2813 + bool valid = false;
2814 + bool thread_valid;
2815 + int i, j, rc, new_volt, vdd_volt, dynamic_floor_volt, last_corner_volt;
2816 + u32 reg_last_measurement = 0, sdelta_size;
2817 + int *sdelta_table, *boost_table;
2818 +
2819 + last_corner_volt = 0;
2820 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
2821 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
2822 + if (rc) {
2823 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
2824 + rc);
2825 + return rc;
2826 + }
2827 + }
2828 +
2829 + cpr3_ctrl_loop_disable(ctrl);
2830 +
2831 + vdd_volt = regulator_get_voltage(ctrl->vdd_regulator);
2832 + if (vdd_volt < 0) {
2833 + cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
2834 + vdd_volt);
2835 + return vdd_volt;
2836 + }
2837 +
2838 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
2839 + /*
2840 + * Save aggregated corner open-loop voltage which was programmed
2841 + * during last corner switch which is used when programming new
2842 + * aggregated corner open-loop voltage.
2843 + */
2844 + last_corner_volt = ctrl->aggr_corner.open_loop_volt;
2845 + }
2846 +
2847 + if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop &&
2848 + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
2849 + reg_last_measurement
2850 + = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
2851 +
2852 + aggr_corner.sdelta = ctrl->aggr_corner.sdelta;
2853 + if (aggr_corner.sdelta) {
2854 + sdelta = aggr_corner.sdelta;
2855 + sdelta_table = sdelta->table;
2856 + if (sdelta_table) {
2857 + sdelta_size = sdelta->max_core_count *
2858 + sdelta->temp_band_count;
2859 + memset(sdelta_table, 0, sdelta_size
2860 + * sizeof(*sdelta_table));
2861 + }
2862 +
2863 + boost_table = sdelta->boost_table;
2864 + if (boost_table)
2865 + memset(boost_table, 0, sdelta->temp_band_count
2866 + * sizeof(*boost_table));
2867 +
2868 + memset(sdelta, 0, sizeof(*sdelta));
2869 + sdelta->table = sdelta_table;
2870 + sdelta->cap_volt = INT_MAX;
2871 + sdelta->boost_table = boost_table;
2872 + }
2873 +
2874 + /* Aggregate the requests of all threads */
2875 + for (i = 0; i < ctrl->thread_count; i++) {
2876 + thread = &ctrl->thread[i];
2877 + thread_valid = false;
2878 +
2879 + sdelta = thread->aggr_corner.sdelta;
2880 + if (sdelta) {
2881 + sdelta_table = sdelta->table;
2882 + if (sdelta_table) {
2883 + sdelta_size = sdelta->max_core_count *
2884 + sdelta->temp_band_count;
2885 + memset(sdelta_table, 0, sdelta_size
2886 + * sizeof(*sdelta_table));
2887 + }
2888 +
2889 + boost_table = sdelta->boost_table;
2890 + if (boost_table)
2891 + memset(boost_table, 0, sdelta->temp_band_count
2892 + * sizeof(*boost_table));
2893 +
2894 + memset(sdelta, 0, sizeof(*sdelta));
2895 + sdelta->table = sdelta_table;
2896 + sdelta->cap_volt = INT_MAX;
2897 + sdelta->boost_table = boost_table;
2898 + }
2899 +
2900 + memset(&thread->aggr_corner, 0, sizeof(thread->aggr_corner));
2901 + thread->aggr_corner.sdelta = sdelta;
2902 + thread->aggr_corner.ro_mask = CPR3_RO_MASK;
2903 +
2904 + for (j = 0; j < thread->vreg_count; j++) {
2905 + vreg = &thread->vreg[j];
2906 +
2907 + if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop)
2908 + cpr3_update_vreg_closed_loop_volt(vreg,
2909 + vdd_volt, reg_last_measurement);
2910 +
2911 + if (!vreg->vreg_enabled
2912 + || vreg->current_corner
2913 + == CPR3_REGULATOR_CORNER_INVALID) {
2914 + /* Cannot participate in aggregation. */
2915 + vreg->aggregated = false;
2916 + continue;
2917 + } else {
2918 + vreg->aggregated = true;
2919 + thread_valid = true;
2920 + }
2921 +
2922 + cpr3_regulator_aggregate_corners(&thread->aggr_corner,
2923 + &vreg->corner[vreg->current_corner],
2924 + true, ctrl->step_volt);
2925 + }
2926 +
2927 + valid |= thread_valid;
2928 +
2929 + if (thread_valid)
2930 + cpr3_regulator_aggregate_corners(&aggr_corner,
2931 + &thread->aggr_corner,
2932 + false, ctrl->step_volt);
2933 + }
2934 +
2935 + if (valid && ctrl->cpr_allowed_hw && ctrl->cpr_allowed_sw) {
2936 + rc = cpr3_closed_loop_enable(ctrl);
2937 + if (rc) {
2938 + cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
2939 + return rc;
2940 + }
2941 + } else {
2942 + rc = cpr3_closed_loop_disable(ctrl);
2943 + if (rc) {
2944 + cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
2945 + return rc;
2946 + }
2947 + }
2948 +
2949 + /* No threads are enabled with a valid corner so exit. */
2950 + if (!valid)
2951 + return 0;
2952 +
2953 + /*
2954 + * When using CPR hardware closed-loop, the voltage may vary anywhere
2955 + * between the floor and ceiling voltage without software notification.
2956 + * Therefore, it is required that the floor to ceiling range for the
2957 + * aggregated corner not intersect the APM threshold voltage. Adjust
2958 + * the floor to ceiling range if this requirement is violated.
2959 + *
2960 + * The following algorithm is applied in the case that
2961 + * floor < threshold <= ceiling:
2962 + * if open_loop >= threshold - adj, then floor = threshold
2963 + * else ceiling = threshold - step
2964 + * where adj = an adjustment factor to ensure sufficient voltage margin
2965 + * and step = VDD output step size
2966 + *
2967 + * The open-loop and last known voltages are also bounded by the new
2968 + * floor or ceiling value as needed.
2969 + */
2970 + if (ctrl->use_hw_closed_loop
2971 + && aggr_corner.ceiling_volt >= ctrl->apm_threshold_volt
2972 + && aggr_corner.floor_volt < ctrl->apm_threshold_volt) {
2973 +
2974 + if (aggr_corner.open_loop_volt
2975 + >= ctrl->apm_threshold_volt - ctrl->apm_adj_volt)
2976 + aggr_corner.floor_volt = ctrl->apm_threshold_volt;
2977 + else
2978 + aggr_corner.ceiling_volt
2979 + = ctrl->apm_threshold_volt - ctrl->step_volt;
2980 +
2981 + aggr_corner.last_volt
2982 + = max(aggr_corner.last_volt, aggr_corner.floor_volt);
2983 + aggr_corner.last_volt
2984 + = min(aggr_corner.last_volt, aggr_corner.ceiling_volt);
2985 + aggr_corner.open_loop_volt
2986 + = max(aggr_corner.open_loop_volt, aggr_corner.floor_volt);
2987 + aggr_corner.open_loop_volt
2988 + = min(aggr_corner.open_loop_volt, aggr_corner.ceiling_volt);
2989 + }
2990 +
2991 + if (ctrl->use_hw_closed_loop
2992 + && aggr_corner.ceiling_volt >= ctrl->mem_acc_threshold_volt
2993 + && aggr_corner.floor_volt < ctrl->mem_acc_threshold_volt) {
2994 + aggr_corner.floor_volt = ctrl->mem_acc_threshold_volt;
2995 + aggr_corner.last_volt = max(aggr_corner.last_volt,
2996 + aggr_corner.floor_volt);
2997 + aggr_corner.open_loop_volt = max(aggr_corner.open_loop_volt,
2998 + aggr_corner.floor_volt);
2999 + }
3000 +
3001 + if (ctrl->use_hw_closed_loop) {
3002 + dynamic_floor_volt
3003 + = cpr3_regulator_get_dynamic_floor_volt(ctrl,
3004 + reg_last_measurement);
3005 + if (aggr_corner.floor_volt < dynamic_floor_volt) {
3006 + aggr_corner.floor_volt = dynamic_floor_volt;
3007 + aggr_corner.last_volt = max(aggr_corner.last_volt,
3008 + aggr_corner.floor_volt);
3009 + aggr_corner.open_loop_volt
3010 + = max(aggr_corner.open_loop_volt,
3011 + aggr_corner.floor_volt);
3012 + aggr_corner.ceiling_volt = max(aggr_corner.ceiling_volt,
3013 + aggr_corner.floor_volt);
3014 + }
3015 + }
3016 +
3017 + if (ctrl->cpr_enabled && ctrl->last_corner_was_closed_loop) {
3018 + /*
3019 + * Always program open-loop voltage for CPR4 controllers which
3020 + * support hardware closed-loop. Storing the last closed loop
3021 + * voltage in corner structure can still help with debugging.
3022 + */
3023 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
3024 + new_volt = aggr_corner.last_volt;
3025 + else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
3026 + && ctrl->supports_hw_closed_loop)
3027 + new_volt = aggr_corner.open_loop_volt;
3028 + else
3029 + new_volt = min(aggr_corner.last_volt +
3030 + cpr3_regulator_max_sdelta_diff(aggr_corner.sdelta,
3031 + ctrl->step_volt),
3032 + aggr_corner.ceiling_volt);
3033 +
3034 + aggr_corner.last_volt = new_volt;
3035 + } else {
3036 + new_volt = aggr_corner.open_loop_volt;
3037 + aggr_corner.last_volt = aggr_corner.open_loop_volt;
3038 + }
3039 +
3040 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
3041 + && ctrl->supports_hw_closed_loop) {
3042 + /*
3043 + * Store last aggregated corner open-loop voltage in vdd_volt
3044 + * which is used when programming current aggregated corner
3045 + * required voltage.
3046 + */
3047 + vdd_volt = last_corner_volt;
3048 + }
3049 +
3050 + cpr3_debug(ctrl, "setting new voltage=%d uV\n", new_volt);
3051 + rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
3052 + vdd_volt, &aggr_corner);
3053 + if (rc) {
3054 + cpr3_err(ctrl, "vdd voltage scaling failed, rc=%d\n", rc);
3055 + return rc;
3056 + }
3057 +
3058 + /* Only update registers if CPR is enabled. */
3059 + if (ctrl->cpr_enabled) {
3060 + if (ctrl->use_hw_closed_loop) {
3061 + /* Hardware closed-loop */
3062 +
3063 + /* Set ceiling and floor limits in hardware */
3064 + rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
3065 + aggr_corner.floor_volt,
3066 + aggr_corner.ceiling_volt);
3067 + if (rc) {
3068 + cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
3069 + rc);
3070 + return rc;
3071 + }
3072 + } else {
3073 + /* Software closed-loop */
3074 +
3075 + /*
3076 + * Disable UP or DOWN interrupts when at ceiling or
3077 + * floor respectively.
3078 + */
3079 + if (new_volt == aggr_corner.floor_volt)
3080 + aggr_corner.irq_en &= ~CPR3_IRQ_DOWN;
3081 + if (new_volt == aggr_corner.ceiling_volt)
3082 + aggr_corner.irq_en &= ~CPR3_IRQ_UP;
3083 +
3084 + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
3085 + CPR3_IRQ_UP | CPR3_IRQ_DOWN);
3086 + cpr3_write(ctrl, CPR3_REG_IRQ_EN, aggr_corner.irq_en);
3087 + }
3088 +
3089 + for (i = 0; i < ctrl->thread_count; i++) {
3090 + cpr3_regulator_set_target_quot(&ctrl->thread[i]);
3091 +
3092 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
3093 + vreg = &ctrl->thread[i].vreg[j];
3094 +
3095 + if (vreg->vreg_enabled)
3096 + vreg->last_closed_loop_corner
3097 + = vreg->current_corner;
3098 + }
3099 + }
3100 +
3101 + if (ctrl->proc_clock_throttle) {
3102 + if (aggr_corner.ceiling_volt > aggr_corner.floor_volt
3103 + && (ctrl->use_hw_closed_loop
3104 + || new_volt < aggr_corner.ceiling_volt))
3105 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
3106 + ctrl->proc_clock_throttle);
3107 + else
3108 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
3109 + CPR3_PD_THROTTLE_DISABLE);
3110 + }
3111 +
3112 + /*
3113 + * Ensure that all CPR register writes complete before
3114 + * re-enabling CPR loop operation.
3115 + */
3116 + wmb();
3117 + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
3118 + && ctrl->vdd_limit_regulator) {
3119 + /* Set ceiling and floor limits in hardware */
3120 + rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
3121 + aggr_corner.floor_volt,
3122 + aggr_corner.ceiling_volt);
3123 + if (rc) {
3124 + cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
3125 + rc);
3126 + return rc;
3127 + }
3128 + }
3129 +
3130 + ctrl->aggr_corner = aggr_corner;
3131 +
3132 + if (ctrl->allow_core_count_adj || ctrl->allow_temp_adj
3133 + || ctrl->allow_boost) {
3134 + rc = cpr3_controller_program_sdelta(ctrl);
3135 + if (rc) {
3136 + cpr3_err(ctrl, "failed to program sdelta, rc=%d\n", rc);
3137 + return rc;
3138 + }
3139 + }
3140 +
3141 + /*
3142 + * Only enable the CPR controller if it is possible to set more than
3143 + * one vdd-supply voltage.
3144 + */
3145 + if (aggr_corner.ceiling_volt > aggr_corner.floor_volt &&
3146 + !aggr_corner.use_open_loop)
3147 + cpr3_ctrl_loop_enable(ctrl);
3148 +
3149 + ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled;
3150 + cpr3_debug(ctrl, "CPR configuration updated\n");
3151 +
3152 + return 0;
3153 +}
3154 +
3155 +/**
3156 + * cpr3_regulator_wait_for_idle() - wait for the CPR controller to no longer be
3157 + * busy
3158 + * @ctrl: Pointer to the CPR3 controller
3159 + * @max_wait_ns: Max wait time in nanoseconds
3160 + *
3161 + * Return: 0 on success or -ETIMEDOUT if the controller was still busy after
3162 + * the maximum delay time
3163 + */
3164 +static int cpr3_regulator_wait_for_idle(struct cpr3_controller *ctrl,
3165 + s64 max_wait_ns)
3166 +{
3167 + ktime_t start, end;
3168 + s64 time_ns;
3169 + u32 reg;
3170 +
3171 + /*
3172 + * Ensure that all previous CPR register writes have completed before
3173 + * checking the status register.
3174 + */
3175 + mb();
3176 +
3177 + start = ktime_get();
3178 + do {
3179 + end = ktime_get();
3180 + time_ns = ktime_to_ns(ktime_sub(end, start));
3181 + if (time_ns > max_wait_ns) {
3182 + cpr3_err(ctrl, "CPR controller still busy after %lld us\n",
3183 + div_s64(time_ns, 1000));
3184 + return -ETIMEDOUT;
3185 + }
3186 + usleep_range(50, 100);
3187 + reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
3188 + } while (reg & CPR3_CPR_STATUS_BUSY_MASK);
3189 +
3190 + return 0;
3191 +}
3192 +
3193 +/**
3194 + * cmp_int() - int comparison function to be passed into the sort() function
3195 + * which leads to ascending sorting
3196 + * @a: First int value
3197 + * @b: Second int value
3198 + *
3199 + * Return: >0 if a > b, 0 if a == b, <0 if a < b
3200 + */
3201 +static int cmp_int(const void *a, const void *b)
3202 +{
3203 + return *(int *)a - *(int *)b;
3204 +}
3205 +
3206 +/**
3207 + * cpr3_regulator_measure_aging() - measure the quotient difference for the
3208 + * specified CPR aging sensor
3209 + * @ctrl: Pointer to the CPR3 controller
3210 + * @aging_sensor: Aging sensor to measure
3211 + *
3212 + * Note that vdd-supply must be configured to the aging reference voltage before
3213 + * calling this function.
3214 + *
3215 + * Return: 0 on success, errno on failure
3216 + */
3217 +static int cpr3_regulator_measure_aging(struct cpr3_controller *ctrl,
3218 + struct cpr3_aging_sensor_info *aging_sensor)
3219 +{
3220 + u32 mask, reg, result, quot_min, quot_max, sel_min, sel_max;
3221 + u32 quot_min_scaled, quot_max_scaled;
3222 + u32 gcnt, gcnt_ref, gcnt0_restore, gcnt1_restore, irq_restore;
3223 + u32 ro_mask_restore, cont_dly_restore, up_down_dly_restore = 0;
3224 + int quot_delta, quot_delta_scaled, quot_delta_scaled_sum;
3225 + int *quot_delta_results;
3226 + int rc, rc2, i, aging_measurement_count, filtered_count;
3227 + bool is_aging_measurement;
3228 +
3229 + quot_delta_results = kcalloc(CPR3_AGING_MEASUREMENT_ITERATIONS,
3230 + sizeof(*quot_delta_results), GFP_KERNEL);
3231 + if (!quot_delta_results)
3232 + return -ENOMEM;
3233 +
3234 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
3235 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
3236 + if (rc) {
3237 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
3238 + rc);
3239 + kfree(quot_delta_results);
3240 + return rc;
3241 + }
3242 + }
3243 +
3244 + cpr3_ctrl_loop_disable(ctrl);
3245 +
3246 + /* Enable up, down, and mid CPR interrupts */
3247 + irq_restore = cpr3_read(ctrl, CPR3_REG_IRQ_EN);
3248 + cpr3_write(ctrl, CPR3_REG_IRQ_EN,
3249 + CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
3250 +
3251 + /* Ensure that the aging sensor is assigned to CPR thread 0 */
3252 + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id), 0);
3253 +
3254 + /* Switch from HW to SW closed-loop if necessary */
3255 + if (ctrl->supports_hw_closed_loop) {
3256 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
3257 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
3258 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
3259 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
3260 + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
3261 + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
3262 + CPR3_HW_CLOSED_LOOP_DISABLE);
3263 + }
3264 + }
3265 +
3266 + /* Configure the GCNT for RO0 and RO1 that are used for aging */
3267 + gcnt0_restore = cpr3_read(ctrl, CPR3_REG_GCNT(0));
3268 + gcnt1_restore = cpr3_read(ctrl, CPR3_REG_GCNT(1));
3269 + gcnt_ref = cpr3_regulator_get_gcnt(ctrl);
3270 + gcnt = gcnt_ref * 3 / 2;
3271 + cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt);
3272 + cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt);
3273 +
3274 + /* Unmask all RO's */
3275 + ro_mask_restore = cpr3_read(ctrl, CPR3_REG_RO_MASK(0));
3276 + cpr3_write(ctrl, CPR3_REG_RO_MASK(0), 0);
3277 +
3278 + /*
3279 + * Mask all sensors except for the one to measure and bypass all
3280 + * sensors in collapsible domains.
3281 + */
3282 + for (i = 0; i <= ctrl->sensor_count / 32; i++) {
3283 + mask = GENMASK(min(31, ctrl->sensor_count - i * 32), 0);
3284 + if (aging_sensor->sensor_id / 32 >= i
3285 + && aging_sensor->sensor_id / 32 < (i + 1))
3286 + mask &= ~BIT(aging_sensor->sensor_id % 32);
3287 + cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), mask);
3288 + cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i),
3289 + aging_sensor->bypass_mask[i]);
3290 + }
3291 +
3292 + /* Set CPR loop delays to 0 us */
3293 + if (ctrl->supports_hw_closed_loop
3294 + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
3295 + cont_dly_restore = cpr3_read(ctrl, CPR3_REG_CPR_TIMER_MID_CONT);
3296 + up_down_dly_restore = cpr3_read(ctrl,
3297 + CPR3_REG_CPR_TIMER_UP_DN_CONT);
3298 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, 0);
3299 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, 0);
3300 + } else {
3301 + cont_dly_restore = cpr3_read(ctrl,
3302 + CPR3_REG_CPR_TIMER_AUTO_CONT);
3303 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, 0);
3304 + }
3305 +
3306 + /* Set count mode to all-at-once min with no repeat */
3307 + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
3308 + CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
3309 + CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN
3310 + << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
3311 +
3312 + cpr3_ctrl_loop_enable(ctrl);
3313 +
3314 + rc = cpr3_regulator_wait_for_idle(ctrl,
3315 + CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
3316 + if (rc)
3317 + goto cleanup;
3318 +
3319 + /* Set count mode to all-at-once aging */
3320 + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, CPR3_CPR_CTL_COUNT_MODE_MASK,
3321 + CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE
3322 + << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
3323 +
3324 + aging_measurement_count = 0;
3325 + for (i = 0; i < CPR3_AGING_MEASUREMENT_ITERATIONS; i++) {
3326 + /* Send CONT_NACK */
3327 + cpr3_write(ctrl, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK);
3328 +
3329 + rc = cpr3_regulator_wait_for_idle(ctrl,
3330 + CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
3331 + if (rc)
3332 + goto cleanup;
3333 +
3334 + /* Check for PAGE_IS_AGE flag in status register */
3335 + reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
3336 + is_aging_measurement
3337 + = reg & CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK;
3338 +
3339 + /* Read CPR measurement results */
3340 + result = cpr3_read(ctrl, CPR3_REG_RESULT1(0));
3341 + quot_min = (result & CPR3_RESULT1_QUOT_MIN_MASK)
3342 + >> CPR3_RESULT1_QUOT_MIN_SHIFT;
3343 + quot_max = (result & CPR3_RESULT1_QUOT_MAX_MASK)
3344 + >> CPR3_RESULT1_QUOT_MAX_SHIFT;
3345 + sel_min = (result & CPR3_RESULT1_RO_MIN_MASK)
3346 + >> CPR3_RESULT1_RO_MIN_SHIFT;
3347 + sel_max = (result & CPR3_RESULT1_RO_MAX_MASK)
3348 + >> CPR3_RESULT1_RO_MAX_SHIFT;
3349 +
3350 + /*
3351 + * Scale the quotients so that they are equivalent to the fused
3352 + * values. This accounts for the difference in measurement
3353 + * interval times.
3354 + */
3355 + quot_min_scaled = quot_min * (gcnt_ref + 1) / (gcnt + 1);
3356 + quot_max_scaled = quot_max * (gcnt_ref + 1) / (gcnt + 1);
3357 +
3358 + if (sel_max == 1) {
3359 + quot_delta = quot_max - quot_min;
3360 + quot_delta_scaled = quot_max_scaled - quot_min_scaled;
3361 + } else {
3362 + quot_delta = quot_min - quot_max;
3363 + quot_delta_scaled = quot_min_scaled - quot_max_scaled;
3364 + }
3365 +
3366 + if (is_aging_measurement)
3367 + quot_delta_results[aging_measurement_count++]
3368 + = quot_delta_scaled;
3369 +
3370 + cpr3_debug(ctrl, "aging results: page_is_age=%u, sel_min=%u, sel_max=%u, quot_min=%u, quot_max=%u, quot_delta=%d, quot_min_scaled=%u, quot_max_scaled=%u, quot_delta_scaled=%d\n",
3371 + is_aging_measurement, sel_min, sel_max, quot_min,
3372 + quot_max, quot_delta, quot_min_scaled, quot_max_scaled,
3373 + quot_delta_scaled);
3374 + }
3375 +
3376 + filtered_count
3377 + = aging_measurement_count - CPR3_AGING_MEASUREMENT_FILTER * 2;
3378 + if (filtered_count > 0) {
3379 + sort(quot_delta_results, aging_measurement_count,
3380 + sizeof(*quot_delta_results), cmp_int, NULL);
3381 +
3382 + quot_delta_scaled_sum = 0;
3383 + for (i = 0; i < filtered_count; i++)
3384 + quot_delta_scaled_sum
3385 + += quot_delta_results[i
3386 + + CPR3_AGING_MEASUREMENT_FILTER];
3387 +
3388 + aging_sensor->measured_quot_diff
3389 + = quot_delta_scaled_sum / filtered_count;
3390 + cpr3_info(ctrl, "average quotient delta=%d (count=%d)\n",
3391 + aging_sensor->measured_quot_diff,
3392 + filtered_count);
3393 + } else {
3394 + cpr3_err(ctrl, "%d aging measurements completed after %d iterations\n",
3395 + aging_measurement_count,
3396 + CPR3_AGING_MEASUREMENT_ITERATIONS);
3397 + rc = -EBUSY;
3398 + }
3399 +
3400 +cleanup:
3401 + kfree(quot_delta_results);
3402 +
3403 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
3404 + rc2 = cpr3_ctrl_clear_cpr4_config(ctrl);
3405 + if (rc2) {
3406 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
3407 + rc2);
3408 + rc = rc2;
3409 + }
3410 + }
3411 +
3412 + cpr3_ctrl_loop_disable(ctrl);
3413 +
3414 + cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_restore);
3415 +
3416 + cpr3_write(ctrl, CPR3_REG_RO_MASK(0), ro_mask_restore);
3417 +
3418 + cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt0_restore);
3419 + cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt1_restore);
3420 +
3421 + if (ctrl->supports_hw_closed_loop
3422 + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
3423 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly_restore);
3424 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
3425 + up_down_dly_restore);
3426 + } else {
3427 + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT,
3428 + cont_dly_restore);
3429 + }
3430 +
3431 + for (i = 0; i <= ctrl->sensor_count / 32; i++) {
3432 + cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), 0);
3433 + cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i), 0);
3434 + }
3435 +
3436 + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
3437 + CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
3438 + (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
3439 + | (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT));
3440 +
3441 + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id),
3442 + ctrl->sensor_owner[aging_sensor->sensor_id]);
3443 +
3444 + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
3445 + CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
3446 +
3447 + if (ctrl->supports_hw_closed_loop) {
3448 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
3449 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
3450 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
3451 + ctrl->use_hw_closed_loop
3452 + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
3453 + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
3454 + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
3455 + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
3456 + ctrl->use_hw_closed_loop
3457 + ? CPR3_HW_CLOSED_LOOP_ENABLE
3458 + : CPR3_HW_CLOSED_LOOP_DISABLE);
3459 + }
3460 + }
3461 +
3462 + return rc;
3463 +}
3464 +
3465 +/**
3466 + * cpr3_regulator_readjust_volt_and_quot() - readjust the target quotients as
3467 + * well as the floor, ceiling, and open-loop voltages for the
3468 + * regulator by removing the old adjustment and adding the new one
3469 + * @vreg: Pointer to the CPR3 regulator
3470 + * @old_adjust_volt: Old aging adjustment voltage in microvolts
3471 + * @new_adjust_volt: New aging adjustment voltage in microvolts
3472 + *
3473 + * Also reset the cached closed loop voltage (last_volt) to equal the open-loop
3474 + * voltage for each corner.
3475 + *
3476 + * Return: None
3477 + */
3478 +static void cpr3_regulator_readjust_volt_and_quot(struct cpr3_regulator *vreg,
3479 + int old_adjust_volt, int new_adjust_volt)
3480 +{
3481 + unsigned long long temp;
3482 + int i, j, old_volt, new_volt, rounded_volt;
3483 +
3484 + if (!vreg->aging_allowed)
3485 + return;
3486 +
3487 + for (i = 0; i < vreg->corner_count; i++) {
3488 + temp = (unsigned long long)old_adjust_volt
3489 + * (unsigned long long)vreg->corner[i].aging_derate;
3490 + do_div(temp, 1000);
3491 + old_volt = temp;
3492 +
3493 + temp = (unsigned long long)new_adjust_volt
3494 + * (unsigned long long)vreg->corner[i].aging_derate;
3495 + do_div(temp, 1000);
3496 + new_volt = temp;
3497 +
3498 + old_volt = min(vreg->aging_max_adjust_volt, old_volt);
3499 + new_volt = min(vreg->aging_max_adjust_volt, new_volt);
3500 +
3501 + for (j = 0; j < CPR3_RO_COUNT; j++) {
3502 + if (vreg->corner[i].target_quot[j] != 0) {
3503 + vreg->corner[i].target_quot[j]
3504 + += cpr3_quot_adjustment(
3505 + vreg->corner[i].ro_scale[j],
3506 + new_volt)
3507 + - cpr3_quot_adjustment(
3508 + vreg->corner[i].ro_scale[j],
3509 + old_volt);
3510 + }
3511 + }
3512 +
3513 + rounded_volt = CPR3_ROUND(new_volt,
3514 + vreg->thread->ctrl->step_volt);
3515 +
3516 + if (!vreg->aging_allow_open_loop_adj)
3517 + rounded_volt = 0;
3518 +
3519 + vreg->corner[i].ceiling_volt
3520 + = vreg->corner[i].unaged_ceiling_volt + rounded_volt;
3521 + vreg->corner[i].ceiling_volt = min(vreg->corner[i].ceiling_volt,
3522 + vreg->corner[i].abs_ceiling_volt);
3523 + vreg->corner[i].floor_volt
3524 + = vreg->corner[i].unaged_floor_volt + rounded_volt;
3525 + vreg->corner[i].floor_volt = min(vreg->corner[i].floor_volt,
3526 + vreg->corner[i].ceiling_volt);
3527 + vreg->corner[i].open_loop_volt
3528 + = vreg->corner[i].unaged_open_loop_volt + rounded_volt;
3529 + vreg->corner[i].open_loop_volt
3530 + = min(vreg->corner[i].open_loop_volt,
3531 + vreg->corner[i].ceiling_volt);
3532 +
3533 + vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
3534 +
3535 + cpr3_debug(vreg, "corner %d: applying %d uV closed-loop and %d uV open-loop voltage margin adjustment\n",
3536 + i, new_volt, rounded_volt);
3537 + }
3538 +}
3539 +
3540 +/**
3541 + * cpr3_regulator_set_aging_ref_adjustment() - adjust target quotients for the
3542 + * regulators managed by this CPR controller to account for aging
3543 + * @ctrl: Pointer to the CPR3 controller
3544 + * @ref_adjust_volt: New aging reference adjustment voltage in microvolts to
3545 + * apply to all regulators managed by this CPR controller
3546 + *
3547 + * The existing aging adjustment as defined by ctrl->aging_ref_adjust_volt is
3548 + * first removed and then the adjustment is applied. Lastly, the value of
3549 + * ctrl->aging_ref_adjust_volt is updated to ref_adjust_volt.
3550 + */
3551 +static void cpr3_regulator_set_aging_ref_adjustment(
3552 + struct cpr3_controller *ctrl, int ref_adjust_volt)
3553 +{
3554 + struct cpr3_regulator *vreg;
3555 + int i, j;
3556 +
3557 + for (i = 0; i < ctrl->thread_count; i++) {
3558 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
3559 + vreg = &ctrl->thread[i].vreg[j];
3560 + cpr3_regulator_readjust_volt_and_quot(vreg,
3561 + ctrl->aging_ref_adjust_volt, ref_adjust_volt);
3562 + }
3563 + }
3564 +
3565 + ctrl->aging_ref_adjust_volt = ref_adjust_volt;
3566 +}
3567 +
3568 +/**
3569 + * cpr3_regulator_aging_adjust() - adjust the target quotients for regulators
3570 + * based on the output of CPR aging sensors
3571 + * @ctrl: Pointer to the CPR3 controller
3572 + *
3573 + * Return: 0 on success, errno on failure
3574 + */
3575 +static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl)
3576 +{
3577 + struct cpr3_regulator *vreg;
3578 + struct cpr3_corner restore_aging_corner;
3579 + struct cpr3_corner *corner;
3580 + int *restore_current_corner;
3581 + bool *restore_vreg_enabled;
3582 + int i, j, id, rc, rc2, vreg_count, aging_volt, max_aging_volt = 0;
3583 + u32 reg;
3584 +
3585 + if (!ctrl->aging_required || !ctrl->cpr_enabled
3586 + || ctrl->aggr_corner.ceiling_volt == 0
3587 + || ctrl->aggr_corner.ceiling_volt > ctrl->aging_ref_volt)
3588 + return 0;
3589 +
3590 + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
3591 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
3592 + vreg = &ctrl->thread[i].vreg[j];
3593 + vreg_count++;
3594 +
3595 + if (vreg->aging_allowed && vreg->vreg_enabled
3596 + && vreg->current_corner > vreg->aging_corner)
3597 + return 0;
3598 + }
3599 + }
3600 +
3601 + /* Verify that none of the aging sensors are currently masked. */
3602 + for (i = 0; i < ctrl->aging_sensor_count; i++) {
3603 + id = ctrl->aging_sensor[i].sensor_id;
3604 + reg = cpr3_read(ctrl, CPR3_REG_SENSOR_MASK_READ(id));
3605 + if (reg & BIT(id % 32))
3606 + return 0;
3607 + }
3608 +
3609 + /*
3610 + * Verify that the aging possible register (if specified) has an
3611 + * acceptable value.
3612 + */
3613 + if (ctrl->aging_possible_reg) {
3614 + reg = readl_relaxed(ctrl->aging_possible_reg);
3615 + reg &= ctrl->aging_possible_mask;
3616 + if (reg != ctrl->aging_possible_val)
3617 + return 0;
3618 + }
3619 +
3620 + restore_current_corner = kcalloc(vreg_count,
3621 + sizeof(*restore_current_corner), GFP_KERNEL);
3622 + restore_vreg_enabled = kcalloc(vreg_count,
3623 + sizeof(*restore_vreg_enabled), GFP_KERNEL);
3624 + if (!restore_current_corner || !restore_vreg_enabled) {
3625 + kfree(restore_current_corner);
3626 + kfree(restore_vreg_enabled);
3627 + return -ENOMEM;
3628 + }
3629 +
3630 + /* Force all regulators to the aging corner */
3631 + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
3632 + for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
3633 + vreg = &ctrl->thread[i].vreg[j];
3634 +
3635 + restore_current_corner[vreg_count]
3636 + = vreg->current_corner;
3637 + restore_vreg_enabled[vreg_count]
3638 + = vreg->vreg_enabled;
3639 +
3640 + vreg->current_corner = vreg->aging_corner;
3641 + vreg->vreg_enabled = true;
3642 + }
3643 + }
3644 +
3645 + /* Force one of the regulators to require the aging reference voltage */
3646 + vreg = &ctrl->thread[0].vreg[0];
3647 + corner = &vreg->corner[vreg->current_corner];
3648 + restore_aging_corner = *corner;
3649 + corner->ceiling_volt = ctrl->aging_ref_volt;
3650 + corner->floor_volt = ctrl->aging_ref_volt;
3651 + corner->open_loop_volt = ctrl->aging_ref_volt;
3652 + corner->last_volt = ctrl->aging_ref_volt;
3653 +
3654 + /* Skip last_volt caching */
3655 + ctrl->last_corner_was_closed_loop = false;
3656 +
3657 + /* Set the vdd supply voltage to the aging reference voltage */
3658 + rc = _cpr3_regulator_update_ctrl_state(ctrl);
3659 + if (rc) {
3660 + cpr3_err(ctrl, "unable to force vdd-supply to the aging reference voltage=%d uV, rc=%d\n",
3661 + ctrl->aging_ref_volt, rc);
3662 + goto cleanup;
3663 + }
3664 +
3665 + if (ctrl->aging_vdd_mode) {
3666 + rc = regulator_set_mode(ctrl->vdd_regulator,
3667 + ctrl->aging_vdd_mode);
3668 + if (rc) {
3669 + cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
3670 + ctrl->aging_vdd_mode, rc);
3671 + goto cleanup;
3672 + }
3673 + }
3674 +
3675 + /* Perform aging measurement on all aging sensors */
3676 + for (i = 0; i < ctrl->aging_sensor_count; i++) {
3677 + for (j = 0; j < CPR3_AGING_RETRY_COUNT; j++) {
3678 + rc = cpr3_regulator_measure_aging(ctrl,
3679 + &ctrl->aging_sensor[i]);
3680 + if (!rc)
3681 + break;
3682 + }
3683 +
3684 + if (!rc) {
3685 + aging_volt =
3686 + cpr3_voltage_adjustment(
3687 + ctrl->aging_sensor[i].ro_scale,
3688 + ctrl->aging_sensor[i].measured_quot_diff
3689 + - ctrl->aging_sensor[i].init_quot_diff);
3690 + max_aging_volt = max(max_aging_volt, aging_volt);
3691 + } else {
3692 + cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n",
3693 + j, rc);
3694 + ctrl->aging_failed = true;
3695 + ctrl->aging_required = false;
3696 + goto cleanup;
3697 + }
3698 + }
3699 +
3700 +cleanup:
3701 + vreg = &ctrl->thread[0].vreg[0];
3702 + vreg->corner[vreg->current_corner] = restore_aging_corner;
3703 +
3704 + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
3705 + for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
3706 + vreg = &ctrl->thread[i].vreg[j];
3707 + vreg->current_corner
3708 + = restore_current_corner[vreg_count];
3709 + vreg->vreg_enabled = restore_vreg_enabled[vreg_count];
3710 + }
3711 + }
3712 +
3713 + kfree(restore_current_corner);
3714 + kfree(restore_vreg_enabled);
3715 +
3716 + /* Adjust the CPR target quotients according to the aging measurement */
3717 + if (!rc) {
3718 + cpr3_regulator_set_aging_ref_adjustment(ctrl, max_aging_volt);
3719 +
3720 + cpr3_info(ctrl, "aging measurement successful; aging reference adjustment voltage=%d uV\n",
3721 + ctrl->aging_ref_adjust_volt);
3722 + ctrl->aging_succeeded = true;
3723 + ctrl->aging_required = false;
3724 + }
3725 +
3726 + if (ctrl->aging_complete_vdd_mode) {
3727 + rc = regulator_set_mode(ctrl->vdd_regulator,
3728 + ctrl->aging_complete_vdd_mode);
3729 + if (rc)
3730 + cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
3731 + ctrl->aging_complete_vdd_mode, rc);
3732 + }
3733 +
3734 + /* Skip last_volt caching */
3735 + ctrl->last_corner_was_closed_loop = false;
3736 +
3737 + /*
3738 + * Restore vdd-supply to the voltage before the aging measurement and
3739 + * restore the CPR3 controller hardware state.
3740 + */
3741 + rc2 = _cpr3_regulator_update_ctrl_state(ctrl);
3742 +
3743 + /* Stop last_volt caching on for the next request */
3744 + ctrl->last_corner_was_closed_loop = false;
3745 +
3746 + return rc ? rc : rc2;
3747 +}
3748 +
3749 +/**
3750 + * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller
3751 + * to reflect the corners used by all CPR3 regulators as well as
3752 + * the CPR operating mode and perform aging adjustments if needed
3753 + * @ctrl: Pointer to the CPR3 controller
3754 + *
3755 + * Note, CPR3 controller lock must be held by the caller.
3756 + *
3757 + * Return: 0 on success, errno on failure
3758 + */
3759 +static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
3760 +{
3761 + int rc;
3762 +
3763 + rc = _cpr3_regulator_update_ctrl_state(ctrl);
3764 + if (rc)
3765 + return rc;
3766 +
3767 + return cpr3_regulator_aging_adjust(ctrl);
3768 +}
3769 +
3770 +/**
3771 + * cpr3_regulator_set_voltage() - set the voltage corner for the CPR3 regulator
3772 + * associated with the regulator device
3773 + * @rdev: Regulator device pointer for the cpr3-regulator
3774 + * @corner: New voltage corner to set (offset by CPR3_CORNER_OFFSET)
3775 + * @corner_max: Maximum voltage corner allowed (offset by
3776 + * CPR3_CORNER_OFFSET)
3777 + * @selector: Pointer which is filled with the selector value for the
3778 + * corner
3779 + *
3780 + * This function is passed as a callback function into the regulator ops that
3781 + * are registered for each cpr3-regulator device. The VDD voltage will not be
3782 + * physically configured until both this function and cpr3_regulator_enable()
3783 + * are called.
3784 + *
3785 + * Return: 0 on success, errno on failure
3786 + */
3787 +static int cpr3_regulator_set_voltage(struct regulator_dev *rdev,
3788 + int corner, int corner_max, unsigned *selector)
3789 +{
3790 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3791 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
3792 + int rc = 0;
3793 + int last_corner;
3794 +
3795 + corner -= CPR3_CORNER_OFFSET;
3796 + corner_max -= CPR3_CORNER_OFFSET;
3797 + *selector = corner;
3798 +
3799 + mutex_lock(&ctrl->lock);
3800 +
3801 + if (!vreg->vreg_enabled) {
3802 + vreg->current_corner = corner;
3803 + cpr3_debug(vreg, "stored corner=%d\n", corner);
3804 + goto done;
3805 + } else if (vreg->current_corner == corner) {
3806 + goto done;
3807 + }
3808 +
3809 + last_corner = vreg->current_corner;
3810 + vreg->current_corner = corner;
3811 +
3812 + if (vreg->cpr4_regulator_data != NULL)
3813 + if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL)
3814 + vreg->cpr4_regulator_data->mem_acc_funcs->set_mem_acc(rdev);
3815 +
3816 + rc = cpr3_regulator_update_ctrl_state(ctrl);
3817 + if (rc) {
3818 + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
3819 + vreg->current_corner = last_corner;
3820 + }
3821 +
3822 + if (vreg->cpr4_regulator_data != NULL)
3823 + if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL)
3824 + vreg->cpr4_regulator_data->mem_acc_funcs->clear_mem_acc(rdev);
3825 +
3826 + cpr3_debug(vreg, "set corner=%d\n", corner);
3827 +done:
3828 + mutex_unlock(&ctrl->lock);
3829 +
3830 + return rc;
3831 +}
3832 +
3833 +/**
3834 + * cpr3_handle_temp_open_loop_adjustment() - voltage based cold temperature
3835 + *
3836 + * @rdev: Regulator device pointer for the cpr3-regulator
3837 + * @is_cold: Flag to denote enter/exit cold condition
3838 + *
3839 + * This function is adjusts voltage margin based on cold condition
3840 + *
3841 + * Return: 0 = success
3842 + */
3843 +
3844 +int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
3845 + bool is_cold)
3846 +{
3847 + int i ,j, k, rc;
3848 + struct cpr3_regulator *vreg;
3849 +
3850 + mutex_lock(&ctrl->lock);
3851 + for (i = 0; i < ctrl->thread_count; i++) {
3852 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
3853 + vreg = &ctrl->thread[i].vreg[j];
3854 + for (k = 0; k < vreg->corner_count; k++) {
3855 + vreg->corner[k].open_loop_volt = is_cold ?
3856 + vreg->corner[k].cold_temp_open_loop_volt :
3857 + vreg->corner[k].normal_temp_open_loop_volt;
3858 + }
3859 + }
3860 + }
3861 + rc = cpr3_regulator_update_ctrl_state(ctrl);
3862 + mutex_unlock(&ctrl->lock);
3863 +
3864 + return rc;
3865 +}
3866 +
3867 +/**
3868 + * cpr3_regulator_get_voltage() - get the voltage corner for the CPR3 regulator
3869 + * associated with the regulator device
3870 + * @rdev: Regulator device pointer for the cpr3-regulator
3871 + *
3872 + * This function is passed as a callback function into the regulator ops that
3873 + * are registered for each cpr3-regulator device.
3874 + *
3875 + * Return: voltage corner value offset by CPR3_CORNER_OFFSET
3876 + */
3877 +static int cpr3_regulator_get_voltage(struct regulator_dev *rdev)
3878 +{
3879 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3880 +
3881 + if (vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID)
3882 + return CPR3_CORNER_OFFSET;
3883 + else
3884 + return vreg->current_corner + CPR3_CORNER_OFFSET;
3885 +}
3886 +
3887 +/**
3888 + * cpr3_regulator_list_voltage() - return the voltage corner mapped to the
3889 + * specified selector
3890 + * @rdev: Regulator device pointer for the cpr3-regulator
3891 + * @selector: Regulator selector
3892 + *
3893 + * This function is passed as a callback function into the regulator ops that
3894 + * are registered for each cpr3-regulator device.
3895 + *
3896 + * Return: voltage corner value offset by CPR3_CORNER_OFFSET
3897 + */
3898 +static int cpr3_regulator_list_voltage(struct regulator_dev *rdev,
3899 + unsigned selector)
3900 +{
3901 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3902 +
3903 + if (selector < vreg->corner_count)
3904 + return selector + CPR3_CORNER_OFFSET;
3905 + else
3906 + return 0;
3907 +}
3908 +
3909 +/**
3910 + * cpr3_regulator_is_enabled() - return the enable state of the CPR3 regulator
3911 + * @rdev: Regulator device pointer for the cpr3-regulator
3912 + *
3913 + * This function is passed as a callback function into the regulator ops that
3914 + * are registered for each cpr3-regulator device.
3915 + *
3916 + * Return: true if regulator is enabled, false if regulator is disabled
3917 + */
3918 +static int cpr3_regulator_is_enabled(struct regulator_dev *rdev)
3919 +{
3920 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3921 +
3922 + return vreg->vreg_enabled;
3923 +}
3924 +
3925 +/**
3926 + * cpr3_regulator_enable() - enable the CPR3 regulator
3927 + * @rdev: Regulator device pointer for the cpr3-regulator
3928 + *
3929 + * This function is passed as a callback function into the regulator ops that
3930 + * are registered for each cpr3-regulator device.
3931 + *
3932 + * Return: 0 on success, errno on failure
3933 + */
3934 +static int cpr3_regulator_enable(struct regulator_dev *rdev)
3935 +{
3936 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3937 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
3938 + int rc = 0;
3939 +
3940 + if (vreg->vreg_enabled == true)
3941 + return 0;
3942 +
3943 + mutex_lock(&ctrl->lock);
3944 +
3945 + if (ctrl->system_regulator) {
3946 + rc = regulator_enable(ctrl->system_regulator);
3947 + if (rc) {
3948 + cpr3_err(ctrl, "regulator_enable(system) failed, rc=%d\n",
3949 + rc);
3950 + goto done;
3951 + }
3952 + }
3953 +
3954 + rc = regulator_enable(ctrl->vdd_regulator);
3955 + if (rc) {
3956 + cpr3_err(vreg, "regulator_enable(vdd) failed, rc=%d\n", rc);
3957 + goto done;
3958 + }
3959 +
3960 + vreg->vreg_enabled = true;
3961 + rc = cpr3_regulator_update_ctrl_state(ctrl);
3962 + if (rc) {
3963 + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
3964 + regulator_disable(ctrl->vdd_regulator);
3965 + vreg->vreg_enabled = false;
3966 + goto done;
3967 + }
3968 +
3969 + cpr3_debug(vreg, "Enabled\n");
3970 +done:
3971 + mutex_unlock(&ctrl->lock);
3972 +
3973 + return rc;
3974 +}
3975 +
3976 +/**
3977 + * cpr3_regulator_disable() - disable the CPR3 regulator
3978 + * @rdev: Regulator device pointer for the cpr3-regulator
3979 + *
3980 + * This function is passed as a callback function into the regulator ops that
3981 + * are registered for each cpr3-regulator device.
3982 + *
3983 + * Return: 0 on success, errno on failure
3984 + */
3985 +static int cpr3_regulator_disable(struct regulator_dev *rdev)
3986 +{
3987 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
3988 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
3989 + int rc, rc2;
3990 +
3991 + if (vreg->vreg_enabled == false)
3992 + return 0;
3993 +
3994 + mutex_lock(&ctrl->lock);
3995 + rc = regulator_disable(ctrl->vdd_regulator);
3996 + if (rc) {
3997 + cpr3_err(vreg, "regulator_disable(vdd) failed, rc=%d\n", rc);
3998 + goto done;
3999 + }
4000 +
4001 + vreg->vreg_enabled = false;
4002 + rc = cpr3_regulator_update_ctrl_state(ctrl);
4003 + if (rc) {
4004 + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
4005 + rc2 = regulator_enable(ctrl->vdd_regulator);
4006 + vreg->vreg_enabled = true;
4007 + goto done;
4008 + }
4009 +
4010 + if (ctrl->system_regulator) {
4011 + rc = regulator_disable(ctrl->system_regulator);
4012 + if (rc) {
4013 + cpr3_err(ctrl, "regulator_disable(system) failed, rc=%d\n",
4014 + rc);
4015 + goto done;
4016 + }
4017 + }
4018 +
4019 + cpr3_debug(vreg, "Disabled\n");
4020 +done:
4021 + mutex_unlock(&ctrl->lock);
4022 +
4023 + return rc;
4024 +}
4025 +
4026 +static struct regulator_ops cpr3_regulator_ops = {
4027 + .enable = cpr3_regulator_enable,
4028 + .disable = cpr3_regulator_disable,
4029 + .is_enabled = cpr3_regulator_is_enabled,
4030 + .set_voltage = cpr3_regulator_set_voltage,
4031 + .get_voltage = cpr3_regulator_get_voltage,
4032 + .list_voltage = cpr3_regulator_list_voltage,
4033 +};
4034 +
4035 +/**
4036 + * cpr3_print_result() - print CPR measurement results to the kernel log for
4037 + * debugging purposes
4038 + * @thread: Pointer to the CPR3 thread
4039 + *
4040 + * Return: None
4041 + */
4042 +static void cpr3_print_result(struct cpr3_thread *thread)
4043 +{
4044 + struct cpr3_controller *ctrl = thread->ctrl;
4045 + u32 result[3], busy, step_dn, step_up, error_steps, error, negative;
4046 + u32 quot_min, quot_max, ro_min, ro_max, step_quot_min, step_quot_max;
4047 + u32 sensor_min, sensor_max;
4048 + char *sign;
4049 +
4050 + result[0] = cpr3_read(ctrl, CPR3_REG_RESULT0(thread->thread_id));
4051 + result[1] = cpr3_read(ctrl, CPR3_REG_RESULT1(thread->thread_id));
4052 + result[2] = cpr3_read(ctrl, CPR3_REG_RESULT2(thread->thread_id));
4053 +
4054 + busy = !!(result[0] & CPR3_RESULT0_BUSY_MASK);
4055 + step_dn = !!(result[0] & CPR3_RESULT0_STEP_DN_MASK);
4056 + step_up = !!(result[0] & CPR3_RESULT0_STEP_UP_MASK);
4057 + error_steps = (result[0] & CPR3_RESULT0_ERROR_STEPS_MASK)
4058 + >> CPR3_RESULT0_ERROR_STEPS_SHIFT;
4059 + error = (result[0] & CPR3_RESULT0_ERROR_MASK)
4060 + >> CPR3_RESULT0_ERROR_SHIFT;
4061 + negative = !!(result[0] & CPR3_RESULT0_NEGATIVE_MASK);
4062 +
4063 + quot_min = (result[1] & CPR3_RESULT1_QUOT_MIN_MASK)
4064 + >> CPR3_RESULT1_QUOT_MIN_SHIFT;
4065 + quot_max = (result[1] & CPR3_RESULT1_QUOT_MAX_MASK)
4066 + >> CPR3_RESULT1_QUOT_MAX_SHIFT;
4067 + ro_min = (result[1] & CPR3_RESULT1_RO_MIN_MASK)
4068 + >> CPR3_RESULT1_RO_MIN_SHIFT;
4069 + ro_max = (result[1] & CPR3_RESULT1_RO_MAX_MASK)
4070 + >> CPR3_RESULT1_RO_MAX_SHIFT;
4071 +
4072 + step_quot_min = (result[2] & CPR3_RESULT2_STEP_QUOT_MIN_MASK)
4073 + >> CPR3_RESULT2_STEP_QUOT_MIN_SHIFT;
4074 + step_quot_max = (result[2] & CPR3_RESULT2_STEP_QUOT_MAX_MASK)
4075 + >> CPR3_RESULT2_STEP_QUOT_MAX_SHIFT;
4076 + sensor_min = (result[2] & CPR3_RESULT2_SENSOR_MIN_MASK)
4077 + >> CPR3_RESULT2_SENSOR_MIN_SHIFT;
4078 + sensor_max = (result[2] & CPR3_RESULT2_SENSOR_MAX_MASK)
4079 + >> CPR3_RESULT2_SENSOR_MAX_SHIFT;
4080 +
4081 + sign = negative ? "-" : "";
4082 + cpr3_debug(ctrl, "thread %u: busy=%u, step_dn=%u, step_up=%u, error_steps=%s%u, error=%s%u\n",
4083 + thread->thread_id, busy, step_dn, step_up, sign, error_steps,
4084 + sign, error);
4085 + cpr3_debug(ctrl, "thread %u: quot_min=%u, quot_max=%u, ro_min=%u, ro_max=%u\n",
4086 + thread->thread_id, quot_min, quot_max, ro_min, ro_max);
4087 + cpr3_debug(ctrl, "thread %u: step_quot_min=%u, step_quot_max=%u, sensor_min=%u, sensor_max=%u\n",
4088 + thread->thread_id, step_quot_min, step_quot_max, sensor_min,
4089 + sensor_max);
4090 +}
4091 +
4092 +/**
4093 + * cpr3_thread_busy() - returns if the specified CPR3 thread is busy taking
4094 + * a measurement
4095 + * @thread: Pointer to the CPR3 thread
4096 + *
4097 + * Return: CPR3 busy status
4098 + */
4099 +static bool cpr3_thread_busy(struct cpr3_thread *thread)
4100 +{
4101 + u32 result;
4102 +
4103 + result = cpr3_read(thread->ctrl, CPR3_REG_RESULT0(thread->thread_id));
4104 +
4105 + return !!(result & CPR3_RESULT0_BUSY_MASK);
4106 +}
4107 +
4108 +/**
4109 + * cpr3_irq_handler() - CPR interrupt handler callback function used for
4110 + * software closed-loop operation
4111 + * @irq: CPR interrupt number
4112 + * @data: Private data corresponding to the CPR3 controller
4113 + * pointer
4114 + *
4115 + * This function increases or decreases the vdd supply voltage based upon the
4116 + * CPR controller recommendation.
4117 + *
4118 + * Return: IRQ_HANDLED
4119 + */
4120 +static irqreturn_t cpr3_irq_handler(int irq, void *data)
4121 +{
4122 + struct cpr3_controller *ctrl = data;
4123 + struct cpr3_corner *aggr = &ctrl->aggr_corner;
4124 + u32 cont = CPR3_CONT_CMD_NACK;
4125 + u32 reg_last_measurement = 0;
4126 + struct cpr3_regulator *vreg;
4127 + struct cpr3_corner *corner;
4128 + unsigned long flags;
4129 + int i, j, new_volt, last_volt, dynamic_floor_volt, rc;
4130 + u32 irq_en, status, cpr_status, ctl;
4131 + bool up, down;
4132 +
4133 + mutex_lock(&ctrl->lock);
4134 +
4135 + if (!ctrl->cpr_enabled) {
4136 + cpr3_debug(ctrl, "CPR interrupt received but CPR is disabled\n");
4137 + mutex_unlock(&ctrl->lock);
4138 + return IRQ_HANDLED;
4139 + } else if (ctrl->use_hw_closed_loop) {
4140 + cpr3_debug(ctrl, "CPR interrupt received but CPR is using HW closed-loop\n");
4141 + goto done;
4142 + }
4143 +
4144 + /*
4145 + * CPR IRQ status checking and CPR controller disabling must happen
4146 + * atomically and without invening delay in order to avoid an interrupt
4147 + * storm caused by the handler racing with the CPR controller.
4148 + */
4149 + local_irq_save(flags);
4150 + preempt_disable();
4151 +
4152 + status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
4153 + up = status & CPR3_IRQ_UP;
4154 + down = status & CPR3_IRQ_DOWN;
4155 +
4156 + if (!up && !down) {
4157 + /*
4158 + * Toggle the CPR controller off and then back on since the
4159 + * hardware and software states are out of sync. This condition
4160 + * occurs after an aging measurement completes as the CPR IRQ
4161 + * physically triggers during the aging measurement but the
4162 + * handler is stuck waiting on the mutex lock.
4163 + */
4164 + cpr3_ctrl_loop_disable(ctrl);
4165 +
4166 + local_irq_restore(flags);
4167 + preempt_enable();
4168 +
4169 + /* Wait for the loop disable write to complete */
4170 + mb();
4171 +
4172 + /* Wait for BUSY=1 and LOOP_EN=0 in CPR controller registers. */
4173 + for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
4174 + cpr_status = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
4175 + ctl = cpr3_read(ctrl, CPR3_REG_CPR_CTL);
4176 + if (cpr_status & CPR3_CPR_STATUS_BUSY_MASK
4177 + && (ctl & CPR3_CPR_CTL_LOOP_EN_MASK)
4178 + == CPR3_CPR_CTL_LOOP_DISABLE)
4179 + break;
4180 + udelay(10);
4181 + }
4182 + if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
4183 + cpr3_debug(ctrl, "CPR controller not disabled after %d us\n",
4184 + CPR3_REGISTER_WRITE_DELAY_US);
4185 +
4186 + /* Clear interrupt status */
4187 + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
4188 + CPR3_IRQ_UP | CPR3_IRQ_DOWN);
4189 +
4190 + /* Wait for the interrupt clearing write to complete */
4191 + mb();
4192 +
4193 + /* Wait for IRQ_STATUS register to be cleared. */
4194 + for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
4195 + status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
4196 + if (!(status & (CPR3_IRQ_UP | CPR3_IRQ_DOWN)))
4197 + break;
4198 + udelay(10);
4199 + }
4200 + if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
4201 + cpr3_debug(ctrl, "CPR interrupts not cleared after %d us\n",
4202 + CPR3_REGISTER_WRITE_DELAY_US);
4203 +
4204 + cpr3_ctrl_loop_enable(ctrl);
4205 +
4206 + cpr3_debug(ctrl, "CPR interrupt received but no up or down status bit is set\n");
4207 +
4208 + mutex_unlock(&ctrl->lock);
4209 + return IRQ_HANDLED;
4210 + } else if (up && down) {
4211 + cpr3_debug(ctrl, "both up and down status bits set\n");
4212 + /* The up flag takes precedence over the down flag. */
4213 + down = false;
4214 + }
4215 +
4216 + if (ctrl->supports_hw_closed_loop)
4217 + reg_last_measurement
4218 + = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
4219 + dynamic_floor_volt = cpr3_regulator_get_dynamic_floor_volt(ctrl,
4220 + reg_last_measurement);
4221 +
4222 + local_irq_restore(flags);
4223 + preempt_enable();
4224 +
4225 + irq_en = aggr->irq_en;
4226 + last_volt = aggr->last_volt;
4227 +
4228 + for (i = 0; i < ctrl->thread_count; i++) {
4229 + if (cpr3_thread_busy(&ctrl->thread[i])) {
4230 + cpr3_debug(ctrl, "CPR thread %u busy when it should be waiting for SW cont\n",
4231 + ctrl->thread[i].thread_id);
4232 + goto done;
4233 + }
4234 + }
4235 +
4236 + new_volt = up ? last_volt + ctrl->step_volt
4237 + : last_volt - ctrl->step_volt;
4238 +
4239 + /* Re-enable UP/DOWN interrupt when its opposite is received. */
4240 + irq_en |= up ? CPR3_IRQ_DOWN : CPR3_IRQ_UP;
4241 +
4242 + if (new_volt > aggr->ceiling_volt) {
4243 + new_volt = aggr->ceiling_volt;
4244 + irq_en &= ~CPR3_IRQ_UP;
4245 + cpr3_debug(ctrl, "limiting to ceiling=%d uV\n",
4246 + aggr->ceiling_volt);
4247 + } else if (new_volt < aggr->floor_volt) {
4248 + new_volt = aggr->floor_volt;
4249 + irq_en &= ~CPR3_IRQ_DOWN;
4250 + cpr3_debug(ctrl, "limiting to floor=%d uV\n", aggr->floor_volt);
4251 + }
4252 +
4253 + if (down && new_volt < dynamic_floor_volt) {
4254 + /*
4255 + * The vdd-supply voltage should not be decreased below the
4256 + * dynamic floor voltage. However, it is not necessary (and
4257 + * counter productive) to force the voltage up to this level
4258 + * if it happened to be below it since the closed-loop voltage
4259 + * must have gotten there in a safe manner while the power
4260 + * domains for the CPR3 regulator imposing the dynamic floor
4261 + * were not bypassed.
4262 + */
4263 + new_volt = last_volt;
4264 + irq_en &= ~CPR3_IRQ_DOWN;
4265 + cpr3_debug(ctrl, "limiting to dynamic floor=%d uV\n",
4266 + dynamic_floor_volt);
4267 + }
4268 +
4269 + for (i = 0; i < ctrl->thread_count; i++)
4270 + cpr3_print_result(&ctrl->thread[i]);
4271 +
4272 + cpr3_debug(ctrl, "%s: new_volt=%d uV, last_volt=%d uV\n",
4273 + up ? "UP" : "DN", new_volt, last_volt);
4274 +
4275 + if (ctrl->proc_clock_throttle && last_volt == aggr->ceiling_volt
4276 + && new_volt < last_volt)
4277 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
4278 + ctrl->proc_clock_throttle);
4279 +
4280 + if (new_volt != last_volt) {
4281 + rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
4282 + last_volt,
4283 + aggr);
4284 + if (rc) {
4285 + cpr3_err(ctrl, "scale_vdd() failed to set vdd=%d uV, rc=%d\n",
4286 + new_volt, rc);
4287 + goto done;
4288 + }
4289 + cont = CPR3_CONT_CMD_ACK;
4290 +
4291 + /*
4292 + * Update the closed-loop voltage for all regulators managed
4293 + * by this CPR controller.
4294 + */
4295 + for (i = 0; i < ctrl->thread_count; i++) {
4296 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
4297 + vreg = &ctrl->thread[i].vreg[j];
4298 + cpr3_update_vreg_closed_loop_volt(vreg,
4299 + new_volt, reg_last_measurement);
4300 + }
4301 + }
4302 + }
4303 +
4304 + if (ctrl->proc_clock_throttle && new_volt == aggr->ceiling_volt)
4305 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
4306 + CPR3_PD_THROTTLE_DISABLE);
4307 +
4308 + corner = &ctrl->thread[0].vreg[0].corner[
4309 + ctrl->thread[0].vreg[0].current_corner];
4310 +
4311 + if (irq_en != aggr->irq_en) {
4312 + aggr->irq_en = irq_en;
4313 + cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_en);
4314 + }
4315 +
4316 + aggr->last_volt = new_volt;
4317 +
4318 +done:
4319 + /* Clear interrupt status */
4320 + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_UP | CPR3_IRQ_DOWN);
4321 +
4322 + /* ACK or NACK the CPR controller */
4323 + cpr3_write(ctrl, CPR3_REG_CONT_CMD, cont);
4324 +
4325 + mutex_unlock(&ctrl->lock);
4326 + return IRQ_HANDLED;
4327 +}
4328 +
4329 +/**
4330 + * cpr3_ceiling_irq_handler() - CPR ceiling reached interrupt handler callback
4331 + * function used for hardware closed-loop operation
4332 + * @irq: CPR ceiling interrupt number
4333 + * @data: Private data corresponding to the CPR3 controller
4334 + * pointer
4335 + *
4336 + * This function disables processor clock throttling and closed-loop operation
4337 + * when the ceiling voltage is reached.
4338 + *
4339 + * Return: IRQ_HANDLED
4340 + */
4341 +static irqreturn_t cpr3_ceiling_irq_handler(int irq, void *data)
4342 +{
4343 + struct cpr3_controller *ctrl = data;
4344 + int volt;
4345 +
4346 + mutex_lock(&ctrl->lock);
4347 +
4348 + if (!ctrl->cpr_enabled) {
4349 + cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is disabled\n");
4350 + goto done;
4351 + } else if (!ctrl->use_hw_closed_loop) {
4352 + cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is using SW closed-loop\n");
4353 + goto done;
4354 + }
4355 +
4356 + volt = regulator_get_voltage(ctrl->vdd_regulator);
4357 + if (volt < 0) {
4358 + cpr3_err(ctrl, "could not get vdd voltage, rc=%d\n", volt);
4359 + goto done;
4360 + } else if (volt != ctrl->aggr_corner.ceiling_volt) {
4361 + cpr3_debug(ctrl, "CPR ceiling interrupt received but vdd voltage: %d uV != ceiling voltage: %d uV\n",
4362 + volt, ctrl->aggr_corner.ceiling_volt);
4363 + goto done;
4364 + }
4365 +
4366 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
4367 + /*
4368 + * Since the ceiling voltage has been reached, disable processor
4369 + * clock throttling as well as CPR closed-loop operation.
4370 + */
4371 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
4372 + CPR3_PD_THROTTLE_DISABLE);
4373 + cpr3_ctrl_loop_disable(ctrl);
4374 + cpr3_debug(ctrl, "CPR closed-loop and throttling disabled\n");
4375 + }
4376 +
4377 +done:
4378 + mutex_unlock(&ctrl->lock);
4379 + return IRQ_HANDLED;
4380 +}
4381 +
4382 +/**
4383 + * cpr3_regulator_vreg_register() - register a regulator device for a CPR3
4384 + * regulator
4385 + * @vreg: Pointer to the CPR3 regulator
4386 + *
4387 + * This function initializes all regulator framework related structures and then
4388 + * calls regulator_register() for the CPR3 regulator.
4389 + *
4390 + * Return: 0 on success, errno on failure
4391 + */
4392 +static int cpr3_regulator_vreg_register(struct cpr3_regulator *vreg)
4393 +{
4394 + struct regulator_config config = {};
4395 + struct regulator_desc *rdesc;
4396 + struct regulator_init_data *init_data;
4397 + int rc;
4398 +
4399 + init_data = of_get_regulator_init_data(vreg->thread->ctrl->dev,
4400 + vreg->of_node, &vreg->rdesc);
4401 + if (!init_data) {
4402 + cpr3_err(vreg, "regulator init data is missing\n");
4403 + return -EINVAL;
4404 + }
4405 +
4406 + init_data->constraints.input_uV = init_data->constraints.max_uV;
4407 + rdesc = &vreg->rdesc;
4408 + init_data->constraints.valid_ops_mask |=
4409 + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS;
4410 + rdesc->ops = &cpr3_regulator_ops;
4411 +
4412 + rdesc->n_voltages = vreg->corner_count;
4413 + rdesc->name = init_data->constraints.name;
4414 + rdesc->owner = THIS_MODULE;
4415 + rdesc->type = REGULATOR_VOLTAGE;
4416 +
4417 + config.dev = vreg->thread->ctrl->dev;
4418 + config.driver_data = vreg;
4419 + config.init_data = init_data;
4420 + config.of_node = vreg->of_node;
4421 +
4422 + vreg->rdev = regulator_register(rdesc, &config);
4423 + if (IS_ERR(vreg->rdev)) {
4424 + rc = PTR_ERR(vreg->rdev);
4425 + cpr3_err(vreg, "regulator_register failed, rc=%d\n", rc);
4426 + return rc;
4427 + }
4428 +
4429 + return 0;
4430 +}
4431 +
4432 +static int debugfs_int_set(void *data, u64 val)
4433 +{
4434 + *(int *)data = val;
4435 + return 0;
4436 +}
4437 +
4438 +static int debugfs_int_get(void *data, u64 *val)
4439 +{
4440 + *val = *(int *)data;
4441 + return 0;
4442 +}
4443 +DEFINE_SIMPLE_ATTRIBUTE(fops_int, debugfs_int_get, debugfs_int_set, "%lld\n");
4444 +DEFINE_SIMPLE_ATTRIBUTE(fops_int_ro, debugfs_int_get, NULL, "%lld\n");
4445 +DEFINE_SIMPLE_ATTRIBUTE(fops_int_wo, NULL, debugfs_int_set, "%lld\n");
4446 +
4447 +/**
4448 + * debugfs_create_int - create a debugfs file that is used to read and write a
4449 + * signed int value
4450 + * @name: Pointer to a string containing the name of the file to
4451 + * create
4452 + * @mode: The permissions that the file should have
4453 + * @parent: Pointer to the parent dentry for this file. This should
4454 + * be a directory dentry if set. If this parameter is
4455 + * %NULL, then the file will be created in the root of the
4456 + * debugfs filesystem.
4457 + * @value: Pointer to the variable that the file should read to and
4458 + * write from
4459 + *
4460 + * This function creates a file in debugfs with the given name that
4461 + * contains the value of the variable @value. If the @mode variable is so
4462 + * set, it can be read from, and written to.
4463 + *
4464 + * This function will return a pointer to a dentry if it succeeds. This
4465 + * pointer must be passed to the debugfs_remove() function when the file is
4466 + * to be removed. If an error occurs, %NULL will be returned.
4467 + */
4468 +static struct dentry *debugfs_create_int(const char *name, umode_t mode,
4469 + struct dentry *parent, int *value)
4470 +{
4471 + /* if there are no write bits set, make read only */
4472 + if (!(mode & S_IWUGO))
4473 + return debugfs_create_file(name, mode, parent, value,
4474 + &fops_int_ro);
4475 + /* if there are no read bits set, make write only */
4476 + if (!(mode & S_IRUGO))
4477 + return debugfs_create_file(name, mode, parent, value,
4478 + &fops_int_wo);
4479 +
4480 + return debugfs_create_file(name, mode, parent, value, &fops_int);
4481 +}
4482 +
4483 +static int debugfs_bool_get(void *data, u64 *val)
4484 +{
4485 + *val = *(bool *)data;
4486 + return 0;
4487 +}
4488 +DEFINE_SIMPLE_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%lld\n");
4489 +
4490 +/**
4491 + * struct cpr3_debug_corner_info - data structure used by the
4492 + * cpr3_debugfs_create_corner_int function
4493 + * @vreg: Pointer to the CPR3 regulator
4494 + * @index: Pointer to the corner array index
4495 + * @member_offset: Offset in bytes from the beginning of struct cpr3_corner
4496 + * to the beginning of the value to be read from
4497 + * @corner: Pointer to the CPR3 corner array
4498 + */
4499 +struct cpr3_debug_corner_info {
4500 + struct cpr3_regulator *vreg;
4501 + int *index;
4502 + size_t member_offset;
4503 + struct cpr3_corner *corner;
4504 +};
4505 +
4506 +static int cpr3_debug_corner_int_get(void *data, u64 *val)
4507 +{
4508 + struct cpr3_debug_corner_info *info = data;
4509 + struct cpr3_controller *ctrl = info->vreg->thread->ctrl;
4510 + int i;
4511 +
4512 + mutex_lock(&ctrl->lock);
4513 +
4514 + i = *info->index;
4515 + if (i < 0)
4516 + i = 0;
4517 +
4518 + *val = *(int *)((char *)&info->vreg->corner[i] + info->member_offset);
4519 +
4520 + mutex_unlock(&ctrl->lock);
4521 +
4522 + return 0;
4523 +}
4524 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_int_fops, cpr3_debug_corner_int_get,
4525 + NULL, "%lld\n");
4526 +
4527 +/**
4528 + * cpr3_debugfs_create_corner_int - create a debugfs file that is used to read
4529 + * a signed int value out of a CPR3 regulator's corner array
4530 + * @vreg: Pointer to the CPR3 regulator
4531 + * @name: Pointer to a string containing the name of the file to
4532 + * create
4533 + * @mode: The permissions that the file should have
4534 + * @parent: Pointer to the parent dentry for this file. This should
4535 + * be a directory dentry if set. If this parameter is
4536 + * %NULL, then the file will be created in the root of the
4537 + * debugfs filesystem.
4538 + * @index: Pointer to the corner array index
4539 + * @member_offset: Offset in bytes from the beginning of struct cpr3_corner
4540 + * to the beginning of the value to be read from
4541 + *
4542 + * This function creates a file in debugfs with the given name that
4543 + * contains the value of the int type variable vreg->corner[index].member
4544 + * where member_offset == offsetof(struct cpr3_corner, member).
4545 + */
4546 +static struct dentry *cpr3_debugfs_create_corner_int(
4547 + struct cpr3_regulator *vreg, const char *name, umode_t mode,
4548 + struct dentry *parent, int *index, size_t member_offset)
4549 +{
4550 + struct cpr3_debug_corner_info *info;
4551 +
4552 + info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
4553 + if (!info)
4554 + return NULL;
4555 +
4556 + info->vreg = vreg;
4557 + info->index = index;
4558 + info->member_offset = member_offset;
4559 +
4560 + return debugfs_create_file(name, mode, parent, info,
4561 + &cpr3_debug_corner_int_fops);
4562 +}
4563 +
4564 +static int cpr3_debug_quot_open(struct inode *inode, struct file *file)
4565 +{
4566 + struct cpr3_debug_corner_info *info = inode->i_private;
4567 + struct cpr3_thread *thread = info->vreg->thread;
4568 + int size, i, pos;
4569 + u32 *quot;
4570 + char *buf;
4571 +
4572 + /*
4573 + * Max size:
4574 + * - 10 digits + ' ' or '\n' = 11 bytes per number
4575 + * - terminating '\0'
4576 + */
4577 + size = CPR3_RO_COUNT * 11;
4578 + buf = kzalloc(size + 1, GFP_KERNEL);
4579 + if (!buf)
4580 + return -ENOMEM;
4581 +
4582 + file->private_data = buf;
4583 +
4584 + mutex_lock(&thread->ctrl->lock);
4585 +
4586 + quot = info->corner[*info->index].target_quot;
4587 +
4588 + for (i = 0, pos = 0; i < CPR3_RO_COUNT; i++)
4589 + pos += scnprintf(buf + pos, size - pos, "%u%c",
4590 + quot[i], i < CPR3_RO_COUNT - 1 ? ' ' : '\n');
4591 +
4592 + mutex_unlock(&thread->ctrl->lock);
4593 +
4594 + return nonseekable_open(inode, file);
4595 +}
4596 +
4597 +static ssize_t cpr3_debug_quot_read(struct file *file, char __user *buf,
4598 + size_t len, loff_t *ppos)
4599 +{
4600 + return simple_read_from_buffer(buf, len, ppos, file->private_data,
4601 + strlen(file->private_data));
4602 +}
4603 +
4604 +static int cpr3_debug_quot_release(struct inode *inode, struct file *file)
4605 +{
4606 + kfree(file->private_data);
4607 +
4608 + return 0;
4609 +}
4610 +
4611 +static const struct file_operations cpr3_debug_quot_fops = {
4612 + .owner = THIS_MODULE,
4613 + .open = cpr3_debug_quot_open,
4614 + .release = cpr3_debug_quot_release,
4615 + .read = cpr3_debug_quot_read,
4616 + .llseek = no_llseek,
4617 +};
4618 +
4619 +/**
4620 + * cpr3_regulator_debugfs_corner_add() - add debugfs files to expose
4621 + * configuration data for the CPR corner
4622 + * @vreg: Pointer to the CPR3 regulator
4623 + * @corner_dir: Pointer to the parent corner dentry for the new files
4624 + * @index: Pointer to the corner array index
4625 + *
4626 + * Return: none
4627 + */
4628 +static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg,
4629 + struct dentry *corner_dir, int *index)
4630 +{
4631 + struct cpr3_debug_corner_info *info;
4632 + struct dentry *temp;
4633 +
4634 + temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", S_IRUGO,
4635 + corner_dir, index, offsetof(struct cpr3_corner, floor_volt));
4636 + if (IS_ERR_OR_NULL(temp)) {
4637 + cpr3_err(vreg, "floor_volt debugfs file creation failed\n");
4638 + return;
4639 + }
4640 +
4641 + temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", S_IRUGO,
4642 + corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt));
4643 + if (IS_ERR_OR_NULL(temp)) {
4644 + cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n");
4645 + return;
4646 + }
4647 +
4648 + temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", S_IRUGO,
4649 + corner_dir, index,
4650 + offsetof(struct cpr3_corner, open_loop_volt));
4651 + if (IS_ERR_OR_NULL(temp)) {
4652 + cpr3_err(vreg, "open_loop_volt debugfs file creation failed\n");
4653 + return;
4654 + }
4655 +
4656 + temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", S_IRUGO,
4657 + corner_dir, index, offsetof(struct cpr3_corner, last_volt));
4658 + if (IS_ERR_OR_NULL(temp)) {
4659 + cpr3_err(vreg, "last_volt debugfs file creation failed\n");
4660 + return;
4661 + }
4662 +
4663 + info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
4664 + if (!info)
4665 + return;
4666 +
4667 + info->vreg = vreg;
4668 + info->index = index;
4669 + info->corner = vreg->corner;
4670 +
4671 + temp = debugfs_create_file("target_quots", S_IRUGO, corner_dir,
4672 + info, &cpr3_debug_quot_fops);
4673 + if (IS_ERR_OR_NULL(temp)) {
4674 + cpr3_err(vreg, "target_quots debugfs file creation failed\n");
4675 + return;
4676 + }
4677 +}
4678 +
4679 +/**
4680 + * cpr3_debug_corner_index_set() - debugfs callback used to change the
4681 + * value of the CPR3 regulator debug_corner index
4682 + * @data: Pointer to private data which is equal to the CPR3
4683 + * regulator pointer
4684 + * @val: New value for debug_corner
4685 + *
4686 + * Return: 0 on success, errno on failure
4687 + */
4688 +static int cpr3_debug_corner_index_set(void *data, u64 val)
4689 +{
4690 + struct cpr3_regulator *vreg = data;
4691 +
4692 + if (val < CPR3_CORNER_OFFSET || val > vreg->corner_count) {
4693 + cpr3_err(vreg, "invalid corner index %llu; allowed values: %d-%d\n",
4694 + val, CPR3_CORNER_OFFSET, vreg->corner_count);
4695 + return -EINVAL;
4696 + }
4697 +
4698 + mutex_lock(&vreg->thread->ctrl->lock);
4699 + vreg->debug_corner = val - CPR3_CORNER_OFFSET;
4700 + mutex_unlock(&vreg->thread->ctrl->lock);
4701 +
4702 + return 0;
4703 +}
4704 +
4705 +/**
4706 + * cpr3_debug_corner_index_get() - debugfs callback used to retrieve
4707 + * the value of the CPR3 regulator debug_corner index
4708 + * @data: Pointer to private data which is equal to the CPR3
4709 + * regulator pointer
4710 + * @val: Output parameter written with the value of
4711 + * debug_corner
4712 + *
4713 + * Return: 0 on success, errno on failure
4714 + */
4715 +static int cpr3_debug_corner_index_get(void *data, u64 *val)
4716 +{
4717 + struct cpr3_regulator *vreg = data;
4718 +
4719 + *val = vreg->debug_corner + CPR3_CORNER_OFFSET;
4720 +
4721 + return 0;
4722 +}
4723 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_index_fops,
4724 + cpr3_debug_corner_index_get,
4725 + cpr3_debug_corner_index_set,
4726 + "%llu\n");
4727 +
4728 +/**
4729 + * cpr3_debug_current_corner_index_get() - debugfs callback used to retrieve
4730 + * the value of the CPR3 regulator current_corner index
4731 + * @data: Pointer to private data which is equal to the CPR3
4732 + * regulator pointer
4733 + * @val: Output parameter written with the value of
4734 + * current_corner
4735 + *
4736 + * Return: 0 on success, errno on failure
4737 + */
4738 +static int cpr3_debug_current_corner_index_get(void *data, u64 *val)
4739 +{
4740 + struct cpr3_regulator *vreg = data;
4741 +
4742 + *val = vreg->current_corner + CPR3_CORNER_OFFSET;
4743 +
4744 + return 0;
4745 +}
4746 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_current_corner_index_fops,
4747 + cpr3_debug_current_corner_index_get,
4748 + NULL, "%llu\n");
4749 +
4750 +/**
4751 + * cpr3_regulator_debugfs_vreg_add() - add debugfs files to expose configuration
4752 + * data for the CPR3 regulator
4753 + * @vreg: Pointer to the CPR3 regulator
4754 + * @thread_dir CPR3 thread debugfs directory handle
4755 + *
4756 + * Return: none
4757 + */
4758 +static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg,
4759 + struct dentry *thread_dir)
4760 +{
4761 + struct dentry *temp, *corner_dir, *vreg_dir;
4762 +
4763 + vreg_dir = debugfs_create_dir(vreg->name, thread_dir);
4764 + if (IS_ERR_OR_NULL(vreg_dir)) {
4765 + cpr3_err(vreg, "%s debugfs directory creation failed\n",
4766 + vreg->name);
4767 + return;
4768 + }
4769 +
4770 + temp = debugfs_create_int("speed_bin_fuse", S_IRUGO, vreg_dir,
4771 + &vreg->speed_bin_fuse);
4772 + if (IS_ERR_OR_NULL(temp)) {
4773 + cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n");
4774 + return;
4775 + }
4776 +
4777 + temp = debugfs_create_int("cpr_rev_fuse", S_IRUGO, vreg_dir,
4778 + &vreg->cpr_rev_fuse);
4779 + if (IS_ERR_OR_NULL(temp)) {
4780 + cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n");
4781 + return;
4782 + }
4783 +
4784 + temp = debugfs_create_int("fuse_combo", S_IRUGO, vreg_dir,
4785 + &vreg->fuse_combo);
4786 + if (IS_ERR_OR_NULL(temp)) {
4787 + cpr3_err(vreg, "fuse_combo debugfs file creation failed\n");
4788 + return;
4789 + }
4790 +
4791 + temp = debugfs_create_int("corner_count", S_IRUGO, vreg_dir,
4792 + &vreg->corner_count);
4793 + if (IS_ERR_OR_NULL(temp)) {
4794 + cpr3_err(vreg, "corner_count debugfs file creation failed\n");
4795 + return;
4796 + }
4797 +
4798 + corner_dir = debugfs_create_dir("corner", vreg_dir);
4799 + if (IS_ERR_OR_NULL(corner_dir)) {
4800 + cpr3_err(vreg, "corner debugfs directory creation failed\n");
4801 + return;
4802 + }
4803 +
4804 + temp = debugfs_create_file("index", S_IRUGO | S_IWUSR, corner_dir,
4805 + vreg, &cpr3_debug_corner_index_fops);
4806 + if (IS_ERR_OR_NULL(temp)) {
4807 + cpr3_err(vreg, "index debugfs file creation failed\n");
4808 + return;
4809 + }
4810 +
4811 + cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
4812 + &vreg->debug_corner);
4813 +
4814 + corner_dir = debugfs_create_dir("current_corner", vreg_dir);
4815 + if (IS_ERR_OR_NULL(corner_dir)) {
4816 + cpr3_err(vreg, "current_corner debugfs directory creation failed\n");
4817 + return;
4818 + }
4819 +
4820 + temp = debugfs_create_file("index", S_IRUGO, corner_dir,
4821 + vreg, &cpr3_debug_current_corner_index_fops);
4822 + if (IS_ERR_OR_NULL(temp)) {
4823 + cpr3_err(vreg, "index debugfs file creation failed\n");
4824 + return;
4825 + }
4826 +
4827 + cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
4828 + &vreg->current_corner);
4829 +}
4830 +
4831 +/**
4832 + * cpr3_regulator_debugfs_thread_add() - add debugfs files to expose
4833 + * configuration data for the CPR thread
4834 + * @thread: Pointer to the CPR3 thread
4835 + *
4836 + * Return: none
4837 + */
4838 +static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread)
4839 +{
4840 + struct cpr3_controller *ctrl = thread->ctrl;
4841 + struct dentry *aggr_dir, *temp, *thread_dir;
4842 + struct cpr3_debug_corner_info *info;
4843 + char buf[20];
4844 + int *index;
4845 + int i;
4846 +
4847 + scnprintf(buf, sizeof(buf), "thread%u", thread->thread_id);
4848 + thread_dir = debugfs_create_dir(buf, thread->ctrl->debugfs);
4849 + if (IS_ERR_OR_NULL(thread_dir)) {
4850 + cpr3_err(ctrl, "thread %u %s debugfs directory creation failed\n",
4851 + thread->thread_id, buf);
4852 + return;
4853 + }
4854 +
4855 + aggr_dir = debugfs_create_dir("max_aggregated_params", thread_dir);
4856 + if (IS_ERR_OR_NULL(aggr_dir)) {
4857 + cpr3_err(ctrl, "thread %u max_aggregated_params debugfs directory creation failed\n",
4858 + thread->thread_id);
4859 + return;
4860 + }
4861 +
4862 + temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir,
4863 + &thread->aggr_corner.floor_volt);
4864 + if (IS_ERR_OR_NULL(temp)) {
4865 + cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n",
4866 + thread->thread_id);
4867 + return;
4868 + }
4869 +
4870 + temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir,
4871 + &thread->aggr_corner.ceiling_volt);
4872 + if (IS_ERR_OR_NULL(temp)) {
4873 + cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n",
4874 + thread->thread_id);
4875 + return;
4876 + }
4877 +
4878 + temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir,
4879 + &thread->aggr_corner.open_loop_volt);
4880 + if (IS_ERR_OR_NULL(temp)) {
4881 + cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n",
4882 + thread->thread_id);
4883 + return;
4884 + }
4885 +
4886 + temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir,
4887 + &thread->aggr_corner.last_volt);
4888 + if (IS_ERR_OR_NULL(temp)) {
4889 + cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n",
4890 + thread->thread_id);
4891 + return;
4892 + }
4893 +
4894 + info = devm_kzalloc(thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
4895 + index = devm_kzalloc(thread->ctrl->dev, sizeof(*index), GFP_KERNEL);
4896 + if (!info || !index)
4897 + return;
4898 + *index = 0;
4899 + info->vreg = &thread->vreg[0];
4900 + info->index = index;
4901 + info->corner = &thread->aggr_corner;
4902 +
4903 + temp = debugfs_create_file("target_quots", S_IRUGO, aggr_dir,
4904 + info, &cpr3_debug_quot_fops);
4905 + if (IS_ERR_OR_NULL(temp)) {
4906 + cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n",
4907 + thread->thread_id);
4908 + return;
4909 + }
4910 +
4911 + for (i = 0; i < thread->vreg_count; i++)
4912 + cpr3_regulator_debugfs_vreg_add(&thread->vreg[i], thread_dir);
4913 +}
4914 +
4915 +/**
4916 + * cpr3_debug_closed_loop_enable_set() - debugfs callback used to change the
4917 + * value of the CPR controller cpr_allowed_sw flag which enables or
4918 + * disables closed-loop operation
4919 + * @data: Pointer to private data which is equal to the CPR
4920 + * controller pointer
4921 + * @val: New value for cpr_allowed_sw
4922 + *
4923 + * Return: 0 on success, errno on failure
4924 + */
4925 +static int cpr3_debug_closed_loop_enable_set(void *data, u64 val)
4926 +{
4927 + struct cpr3_controller *ctrl = data;
4928 + bool enable = !!val;
4929 + int rc;
4930 +
4931 + mutex_lock(&ctrl->lock);
4932 +
4933 + if (ctrl->cpr_allowed_sw == enable)
4934 + goto done;
4935 +
4936 + if (enable && !ctrl->cpr_allowed_hw) {
4937 + cpr3_err(ctrl, "CPR closed-loop operation is not allowed\n");
4938 + goto done;
4939 + }
4940 +
4941 + ctrl->cpr_allowed_sw = enable;
4942 +
4943 + rc = cpr3_regulator_update_ctrl_state(ctrl);
4944 + if (rc) {
4945 + cpr3_err(ctrl, "could not change CPR enable state=%u, rc=%d\n",
4946 + enable, rc);
4947 + goto done;
4948 + }
4949 +
4950 + if (ctrl->proc_clock_throttle && !ctrl->cpr_enabled) {
4951 + rc = cpr3_clock_enable(ctrl);
4952 + if (rc) {
4953 + cpr3_err(ctrl, "clock enable failed, rc=%d\n",
4954 + rc);
4955 + goto done;
4956 + }
4957 + ctrl->cpr_enabled = true;
4958 +
4959 + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
4960 + CPR3_PD_THROTTLE_DISABLE);
4961 +
4962 + cpr3_clock_disable(ctrl);
4963 + ctrl->cpr_enabled = false;
4964 + }
4965 +
4966 + cpr3_debug(ctrl, "closed-loop=%s\n", enable ? "enabled" : "disabled");
4967 +done:
4968 + mutex_unlock(&ctrl->lock);
4969 + return 0;
4970 +}
4971 +
4972 +/**
4973 + * cpr3_debug_closed_loop_enable_get() - debugfs callback used to retrieve
4974 + * the value of the CPR controller cpr_allowed_sw flag which
4975 + * indicates if closed-loop operation is enabled
4976 + * @data: Pointer to private data which is equal to the CPR
4977 + * controller pointer
4978 + * @val: Output parameter written with the value of
4979 + * cpr_allowed_sw
4980 + *
4981 + * Return: 0 on success, errno on failure
4982 + */
4983 +static int cpr3_debug_closed_loop_enable_get(void *data, u64 *val)
4984 +{
4985 + struct cpr3_controller *ctrl = data;
4986 +
4987 + *val = ctrl->cpr_allowed_sw;
4988 +
4989 + return 0;
4990 +}
4991 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_closed_loop_enable_fops,
4992 + cpr3_debug_closed_loop_enable_get,
4993 + cpr3_debug_closed_loop_enable_set,
4994 + "%llu\n");
4995 +
4996 +/**
4997 + * cpr3_debug_hw_closed_loop_enable_set() - debugfs callback used to change the
4998 + * value of the CPR controller use_hw_closed_loop flag which
4999 + * switches between software closed-loop and hardware closed-loop
5000 + * operation for CPR3 and CPR4 controllers and between open-loop
5001 + * and full hardware closed-loop operation for CPRh controllers.
5002 + * @data: Pointer to private data which is equal to the CPR
5003 + * controller pointer
5004 + * @val: New value for use_hw_closed_loop
5005 + *
5006 + * Return: 0 on success, errno on failure
5007 + */
5008 +static int cpr3_debug_hw_closed_loop_enable_set(void *data, u64 val)
5009 +{
5010 + struct cpr3_controller *ctrl = data;
5011 + bool use_hw_closed_loop = !!val;
5012 + struct cpr3_regulator *vreg;
5013 + bool cpr_enabled;
5014 + int i, j, k, rc;
5015 +
5016 + mutex_lock(&ctrl->lock);
5017 +
5018 + if (ctrl->use_hw_closed_loop == use_hw_closed_loop)
5019 + goto done;
5020 +
5021 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
5022 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
5023 + if (rc) {
5024 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
5025 + rc);
5026 + goto done;
5027 + }
5028 + }
5029 +
5030 + cpr3_ctrl_loop_disable(ctrl);
5031 +
5032 + ctrl->use_hw_closed_loop = use_hw_closed_loop;
5033 +
5034 + cpr_enabled = ctrl->cpr_enabled;
5035 +
5036 + /* Ensure that CPR clocks are enabled before writing to registers. */
5037 + if (!cpr_enabled) {
5038 + rc = cpr3_clock_enable(ctrl);
5039 + if (rc) {
5040 + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
5041 + goto done;
5042 + }
5043 + ctrl->cpr_enabled = true;
5044 + }
5045 +
5046 + if (ctrl->use_hw_closed_loop)
5047 + cpr3_write(ctrl, CPR3_REG_IRQ_EN, 0);
5048 +
5049 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
5050 + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
5051 + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
5052 + ctrl->use_hw_closed_loop
5053 + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
5054 + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
5055 + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
5056 + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
5057 + ctrl->use_hw_closed_loop
5058 + ? CPR3_HW_CLOSED_LOOP_ENABLE
5059 + : CPR3_HW_CLOSED_LOOP_DISABLE);
5060 + }
5061 +
5062 + /* Turn off CPR clocks if they were off before this function call. */
5063 + if (!cpr_enabled) {
5064 + cpr3_clock_disable(ctrl);
5065 + ctrl->cpr_enabled = false;
5066 + }
5067 +
5068 + if (ctrl->use_hw_closed_loop && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
5069 + rc = regulator_enable(ctrl->vdd_limit_regulator);
5070 + if (rc) {
5071 + cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
5072 + rc);
5073 + goto done;
5074 + }
5075 + } else if (!ctrl->use_hw_closed_loop
5076 + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
5077 + rc = regulator_disable(ctrl->vdd_limit_regulator);
5078 + if (rc) {
5079 + cpr3_err(ctrl, "CPR limit regulator disable failed, rc=%d\n",
5080 + rc);
5081 + goto done;
5082 + }
5083 + }
5084 +
5085 + /*
5086 + * Due to APM and mem-acc floor restriction constraints,
5087 + * the closed-loop voltage may be different when using
5088 + * software closed-loop vs hardware closed-loop. Therefore,
5089 + * reset the cached closed-loop voltage for all corners to the
5090 + * corresponding open-loop voltage when switching between
5091 + * SW and HW closed-loop mode.
5092 + */
5093 + for (i = 0; i < ctrl->thread_count; i++) {
5094 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
5095 + vreg = &ctrl->thread[i].vreg[j];
5096 + for (k = 0; k < vreg->corner_count; k++)
5097 + vreg->corner[k].last_volt
5098 + = vreg->corner[k].open_loop_volt;
5099 + }
5100 + }
5101 +
5102 + /* Skip last_volt caching */
5103 + ctrl->last_corner_was_closed_loop = false;
5104 +
5105 + rc = cpr3_regulator_update_ctrl_state(ctrl);
5106 + if (rc) {
5107 + cpr3_err(ctrl, "could not change CPR HW closed-loop enable state=%u, rc=%d\n",
5108 + use_hw_closed_loop, rc);
5109 + goto done;
5110 + }
5111 +
5112 + cpr3_debug(ctrl, "CPR mode=%s\n",
5113 + use_hw_closed_loop ?
5114 + "HW closed-loop" : "SW closed-loop");
5115 +done:
5116 + mutex_unlock(&ctrl->lock);
5117 + return 0;
5118 +}
5119 +
5120 +/**
5121 + * cpr3_debug_hw_closed_loop_enable_get() - debugfs callback used to retrieve
5122 + * the value of the CPR controller use_hw_closed_loop flag which
5123 + * indicates if hardware closed-loop operation is being used in
5124 + * place of software closed-loop operation
5125 + * @data: Pointer to private data which is equal to the CPR
5126 + * controller pointer
5127 + * @val: Output parameter written with the value of
5128 + * use_hw_closed_loop
5129 + *
5130 + * Return: 0 on success, errno on failure
5131 + */
5132 +static int cpr3_debug_hw_closed_loop_enable_get(void *data, u64 *val)
5133 +{
5134 + struct cpr3_controller *ctrl = data;
5135 +
5136 + *val = ctrl->use_hw_closed_loop;
5137 +
5138 + return 0;
5139 +}
5140 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_hw_closed_loop_enable_fops,
5141 + cpr3_debug_hw_closed_loop_enable_get,
5142 + cpr3_debug_hw_closed_loop_enable_set,
5143 + "%llu\n");
5144 +
5145 +/**
5146 + * cpr3_debug_trigger_aging_measurement_set() - debugfs callback used to trigger
5147 + * another CPR measurement
5148 + * @data: Pointer to private data which is equal to the CPR
5149 + * controller pointer
5150 + * @val: Unused
5151 + *
5152 + * Return: 0 on success, errno on failure
5153 + */
5154 +static int cpr3_debug_trigger_aging_measurement_set(void *data, u64 val)
5155 +{
5156 + struct cpr3_controller *ctrl = data;
5157 + int rc;
5158 +
5159 + mutex_lock(&ctrl->lock);
5160 +
5161 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
5162 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
5163 + if (rc) {
5164 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
5165 + rc);
5166 + goto done;
5167 + }
5168 + }
5169 +
5170 + cpr3_ctrl_loop_disable(ctrl);
5171 +
5172 + cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
5173 + ctrl->aging_required = true;
5174 + ctrl->aging_succeeded = false;
5175 + ctrl->aging_failed = false;
5176 +
5177 + rc = cpr3_regulator_update_ctrl_state(ctrl);
5178 + if (rc) {
5179 + cpr3_err(ctrl, "could not update the CPR controller state, rc=%d\n",
5180 + rc);
5181 + goto done;
5182 + }
5183 +
5184 +done:
5185 + mutex_unlock(&ctrl->lock);
5186 + return 0;
5187 +}
5188 +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_trigger_aging_measurement_fops,
5189 + NULL,
5190 + cpr3_debug_trigger_aging_measurement_set,
5191 + "%llu\n");
5192 +
5193 +/**
5194 + * cpr3_regulator_debugfs_ctrl_add() - add debugfs files to expose configuration
5195 + * data for the CPR controller
5196 + * @ctrl: Pointer to the CPR3 controller
5197 + *
5198 + * Return: none
5199 + */
5200 +static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl)
5201 +{
5202 + struct dentry *temp, *aggr_dir;
5203 + int i;
5204 +
5205 + /* Add cpr3-regulator base directory if it isn't present already. */
5206 + if (cpr3_debugfs_base == NULL) {
5207 + cpr3_debugfs_base = debugfs_create_dir("cpr3-regulator", NULL);
5208 + if (IS_ERR_OR_NULL(cpr3_debugfs_base)) {
5209 + cpr3_err(ctrl, "cpr3-regulator debugfs base directory creation failed\n");
5210 + cpr3_debugfs_base = NULL;
5211 + return;
5212 + }
5213 + }
5214 +
5215 + ctrl->debugfs = debugfs_create_dir(ctrl->name, cpr3_debugfs_base);
5216 + if (IS_ERR_OR_NULL(ctrl->debugfs)) {
5217 + cpr3_err(ctrl, "cpr3-regulator controller debugfs directory creation failed\n");
5218 + return;
5219 + }
5220 +
5221 + temp = debugfs_create_file("cpr_closed_loop_enable", S_IRUGO | S_IWUSR,
5222 + ctrl->debugfs, ctrl,
5223 + &cpr3_debug_closed_loop_enable_fops);
5224 + if (IS_ERR_OR_NULL(temp)) {
5225 + cpr3_err(ctrl, "cpr_closed_loop_enable debugfs file creation failed\n");
5226 + return;
5227 + }
5228 +
5229 + if (ctrl->supports_hw_closed_loop) {
5230 + temp = debugfs_create_file("use_hw_closed_loop",
5231 + S_IRUGO | S_IWUSR, ctrl->debugfs, ctrl,
5232 + &cpr3_debug_hw_closed_loop_enable_fops);
5233 + if (IS_ERR_OR_NULL(temp)) {
5234 + cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n");
5235 + return;
5236 + }
5237 + }
5238 +
5239 + temp = debugfs_create_int("thread_count", S_IRUGO, ctrl->debugfs,
5240 + &ctrl->thread_count);
5241 + if (IS_ERR_OR_NULL(temp)) {
5242 + cpr3_err(ctrl, "thread_count debugfs file creation failed\n");
5243 + return;
5244 + }
5245 +
5246 + if (ctrl->apm) {
5247 + temp = debugfs_create_int("apm_threshold_volt", S_IRUGO,
5248 + ctrl->debugfs, &ctrl->apm_threshold_volt);
5249 + if (IS_ERR_OR_NULL(temp)) {
5250 + cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n");
5251 + return;
5252 + }
5253 + }
5254 +
5255 + if (ctrl->aging_required || ctrl->aging_succeeded
5256 + || ctrl->aging_failed) {
5257 + temp = debugfs_create_int("aging_adj_volt", S_IRUGO,
5258 + ctrl->debugfs, &ctrl->aging_ref_adjust_volt);
5259 + if (IS_ERR_OR_NULL(temp)) {
5260 + cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n");
5261 + return;
5262 + }
5263 +
5264 + temp = debugfs_create_file("aging_succeeded", S_IRUGO,
5265 + ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro);
5266 + if (IS_ERR_OR_NULL(temp)) {
5267 + cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n");
5268 + return;
5269 + }
5270 +
5271 + temp = debugfs_create_file("aging_failed", S_IRUGO,
5272 + ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro);
5273 + if (IS_ERR_OR_NULL(temp)) {
5274 + cpr3_err(ctrl, "aging_failed debugfs file creation failed\n");
5275 + return;
5276 + }
5277 +
5278 + temp = debugfs_create_file("aging_trigger", S_IWUSR,
5279 + ctrl->debugfs, ctrl,
5280 + &cpr3_debug_trigger_aging_measurement_fops);
5281 + if (IS_ERR_OR_NULL(temp)) {
5282 + cpr3_err(ctrl, "aging_trigger debugfs file creation failed\n");
5283 + return;
5284 + }
5285 + }
5286 +
5287 + aggr_dir = debugfs_create_dir("max_aggregated_voltages", ctrl->debugfs);
5288 + if (IS_ERR_OR_NULL(aggr_dir)) {
5289 + cpr3_err(ctrl, "max_aggregated_voltages debugfs directory creation failed\n");
5290 + return;
5291 + }
5292 +
5293 + temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir,
5294 + &ctrl->aggr_corner.floor_volt);
5295 + if (IS_ERR_OR_NULL(temp)) {
5296 + cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n");
5297 + return;
5298 + }
5299 +
5300 + temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir,
5301 + &ctrl->aggr_corner.ceiling_volt);
5302 + if (IS_ERR_OR_NULL(temp)) {
5303 + cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n");
5304 + return;
5305 + }
5306 +
5307 + temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir,
5308 + &ctrl->aggr_corner.open_loop_volt);
5309 + if (IS_ERR_OR_NULL(temp)) {
5310 + cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n");
5311 + return;
5312 + }
5313 +
5314 + temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir,
5315 + &ctrl->aggr_corner.last_volt);
5316 + if (IS_ERR_OR_NULL(temp)) {
5317 + cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n");
5318 + return;
5319 + }
5320 +
5321 + for (i = 0; i < ctrl->thread_count; i++)
5322 + cpr3_regulator_debugfs_thread_add(&ctrl->thread[i]);
5323 +}
5324 +
5325 +/**
5326 + * cpr3_regulator_debugfs_ctrl_remove() - remove debugfs files for the CPR
5327 + * controller
5328 + * @ctrl: Pointer to the CPR3 controller
5329 + *
5330 + * Note, this function must be called after the controller has been removed from
5331 + * cpr3_controller_list and while the cpr3_controller_list_mutex lock is held.
5332 + *
5333 + * Return: none
5334 + */
5335 +static void cpr3_regulator_debugfs_ctrl_remove(struct cpr3_controller *ctrl)
5336 +{
5337 + if (list_empty(&cpr3_controller_list)) {
5338 + debugfs_remove_recursive(cpr3_debugfs_base);
5339 + cpr3_debugfs_base = NULL;
5340 + } else {
5341 + debugfs_remove_recursive(ctrl->debugfs);
5342 + }
5343 +}
5344 +
5345 +/**
5346 + * cpr3_regulator_init_ctrl_data() - performs initialization of CPR controller
5347 + * elements
5348 + * @ctrl: Pointer to the CPR3 controller
5349 + *
5350 + * Return: 0 on success, errno on failure
5351 + */
5352 +static int cpr3_regulator_init_ctrl_data(struct cpr3_controller *ctrl)
5353 +{
5354 + /* Read the initial vdd voltage from hardware. */
5355 + ctrl->aggr_corner.last_volt
5356 + = regulator_get_voltage(ctrl->vdd_regulator);
5357 + if (ctrl->aggr_corner.last_volt < 0) {
5358 + cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
5359 + ctrl->aggr_corner.last_volt);
5360 + return ctrl->aggr_corner.last_volt;
5361 + }
5362 + ctrl->aggr_corner.open_loop_volt = ctrl->aggr_corner.last_volt;
5363 +
5364 + return 0;
5365 +}
5366 +
5367 +/**
5368 + * cpr3_regulator_init_vreg_data() - performs initialization of common CPR3
5369 + * regulator elements and validate aging configurations
5370 + * @vreg: Pointer to the CPR3 regulator
5371 + *
5372 + * Return: 0 on success, errno on failure
5373 + */
5374 +static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg)
5375 +{
5376 + int i, j;
5377 + bool init_aging;
5378 +
5379 + vreg->current_corner = CPR3_REGULATOR_CORNER_INVALID;
5380 + vreg->last_closed_loop_corner = CPR3_REGULATOR_CORNER_INVALID;
5381 +
5382 + init_aging = vreg->aging_allowed && vreg->thread->ctrl->aging_required;
5383 +
5384 + for (i = 0; i < vreg->corner_count; i++) {
5385 + vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
5386 + vreg->corner[i].irq_en = CPR3_IRQ_UP | CPR3_IRQ_DOWN;
5387 +
5388 + vreg->corner[i].ro_mask = 0;
5389 + for (j = 0; j < CPR3_RO_COUNT; j++) {
5390 + if (vreg->corner[i].target_quot[j] == 0)
5391 + vreg->corner[i].ro_mask |= BIT(j);
5392 + }
5393 +
5394 + if (init_aging) {
5395 + vreg->corner[i].unaged_floor_volt
5396 + = vreg->corner[i].floor_volt;
5397 + vreg->corner[i].unaged_ceiling_volt
5398 + = vreg->corner[i].ceiling_volt;
5399 + vreg->corner[i].unaged_open_loop_volt
5400 + = vreg->corner[i].open_loop_volt;
5401 + }
5402 +
5403 + if (vreg->aging_allowed) {
5404 + if (vreg->corner[i].unaged_floor_volt <= 0) {
5405 + cpr3_err(vreg, "invalid unaged_floor_volt[%d] = %d\n",
5406 + i, vreg->corner[i].unaged_floor_volt);
5407 + return -EINVAL;
5408 + }
5409 + if (vreg->corner[i].unaged_ceiling_volt <= 0) {
5410 + cpr3_err(vreg, "invalid unaged_ceiling_volt[%d] = %d\n",
5411 + i, vreg->corner[i].unaged_ceiling_volt);
5412 + return -EINVAL;
5413 + }
5414 + if (vreg->corner[i].unaged_open_loop_volt <= 0) {
5415 + cpr3_err(vreg, "invalid unaged_open_loop_volt[%d] = %d\n",
5416 + i, vreg->corner[i].unaged_open_loop_volt);
5417 + return -EINVAL;
5418 + }
5419 + }
5420 + }
5421 +
5422 + if (vreg->aging_allowed && vreg->corner[vreg->aging_corner].ceiling_volt
5423 + > vreg->thread->ctrl->aging_ref_volt) {
5424 + cpr3_err(vreg, "aging corner %d ceiling voltage = %d > aging ref voltage = %d uV\n",
5425 + vreg->aging_corner,
5426 + vreg->corner[vreg->aging_corner].ceiling_volt,
5427 + vreg->thread->ctrl->aging_ref_volt);
5428 + return -EINVAL;
5429 + }
5430 +
5431 + return 0;
5432 +}
5433 +
5434 +/**
5435 + * cpr3_regulator_suspend() - perform common required CPR3 power down steps
5436 + * before the system enters suspend
5437 + * @ctrl: Pointer to the CPR3 controller
5438 + *
5439 + * Return: 0 on success, errno on failure
5440 + */
5441 +int cpr3_regulator_suspend(struct cpr3_controller *ctrl)
5442 +{
5443 + int rc;
5444 +
5445 + mutex_lock(&ctrl->lock);
5446 +
5447 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
5448 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
5449 + if (rc) {
5450 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
5451 + rc);
5452 + mutex_unlock(&ctrl->lock);
5453 + return rc;
5454 + }
5455 + }
5456 +
5457 + cpr3_ctrl_loop_disable(ctrl);
5458 +
5459 + rc = cpr3_closed_loop_disable(ctrl);
5460 + if (rc)
5461 + cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
5462 +
5463 + ctrl->cpr_suspended = true;
5464 +
5465 + mutex_unlock(&ctrl->lock);
5466 + return 0;
5467 +}
5468 +
5469 +/**
5470 + * cpr3_regulator_resume() - perform common required CPR3 power up steps after
5471 + * the system resumes from suspend
5472 + * @ctrl: Pointer to the CPR3 controller
5473 + *
5474 + * Return: 0 on success, errno on failure
5475 + */
5476 +int cpr3_regulator_resume(struct cpr3_controller *ctrl)
5477 +{
5478 + int rc;
5479 +
5480 + mutex_lock(&ctrl->lock);
5481 +
5482 + ctrl->cpr_suspended = false;
5483 + rc = cpr3_regulator_update_ctrl_state(ctrl);
5484 + if (rc)
5485 + cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
5486 +
5487 + mutex_unlock(&ctrl->lock);
5488 + return 0;
5489 +}
5490 +
5491 +/**
5492 + * cpr3_regulator_validate_controller() - verify the data passed in via the
5493 + * cpr3_controller data structure
5494 + * @ctrl: Pointer to the CPR3 controller
5495 + *
5496 + * Return: 0 on success, errno on failure
5497 + */
5498 +static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl)
5499 +{
5500 + struct cpr3_thread *thread;
5501 + struct cpr3_regulator *vreg;
5502 + int i, j, allow_boost_vreg_count = 0;
5503 +
5504 + if (!ctrl->vdd_regulator) {
5505 + cpr3_err(ctrl, "vdd regulator missing\n");
5506 + return -EINVAL;
5507 + } else if (ctrl->sensor_count <= 0
5508 + || ctrl->sensor_count > CPR3_MAX_SENSOR_COUNT) {
5509 + cpr3_err(ctrl, "invalid CPR sensor count=%d\n",
5510 + ctrl->sensor_count);
5511 + return -EINVAL;
5512 + } else if (!ctrl->sensor_owner) {
5513 + cpr3_err(ctrl, "CPR sensor ownership table missing\n");
5514 + return -EINVAL;
5515 + }
5516 +
5517 + if (ctrl->aging_required) {
5518 + for (i = 0; i < ctrl->aging_sensor_count; i++) {
5519 + if (ctrl->aging_sensor[i].sensor_id
5520 + >= ctrl->sensor_count) {
5521 + cpr3_err(ctrl, "aging_sensor[%d] id=%u is not in the value range 0-%d",
5522 + i, ctrl->aging_sensor[i].sensor_id,
5523 + ctrl->sensor_count - 1);
5524 + return -EINVAL;
5525 + }
5526 + }
5527 + }
5528 +
5529 + for (i = 0; i < ctrl->thread_count; i++) {
5530 + thread = &ctrl->thread[i];
5531 + for (j = 0; j < thread->vreg_count; j++) {
5532 + vreg = &thread->vreg[j];
5533 + if (vreg->allow_boost)
5534 + allow_boost_vreg_count++;
5535 + }
5536 + }
5537 +
5538 + if (allow_boost_vreg_count > 1) {
5539 + /*
5540 + * Boost feature is not allowed to be used for more
5541 + * than one CPR3 regulator of a CPR3 controller.
5542 + */
5543 + cpr3_err(ctrl, "Boost feature is enabled for more than one regulator\n");
5544 + return -EINVAL;
5545 + }
5546 +
5547 + return 0;
5548 +}
5549 +
5550 +/**
5551 + * cpr3_panic_callback() - panic notification callback function. This function
5552 + * is invoked when a kernel panic occurs.
5553 + * @nfb: Notifier block pointer of CPR3 controller
5554 + * @event: Value passed unmodified to notifier function
5555 + * @data: Pointer passed unmodified to notifier function
5556 + *
5557 + * Return: NOTIFY_OK
5558 + */
5559 +static int cpr3_panic_callback(struct notifier_block *nfb,
5560 + unsigned long event, void *data)
5561 +{
5562 + struct cpr3_controller *ctrl = container_of(nfb,
5563 + struct cpr3_controller, panic_notifier);
5564 + struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info;
5565 + struct cpr3_reg_info *reg;
5566 + int i = 0;
5567 +
5568 + for (i = 0; i < regs_info->reg_count; i++) {
5569 + reg = &(regs_info->regs[i]);
5570 + reg->value = readl_relaxed(reg->virt_addr);
5571 + pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr,
5572 + reg->value);
5573 + }
5574 + /*
5575 + * Barrier to ensure that the information has been updated in the
5576 + * structure.
5577 + */
5578 + mb();
5579 +
5580 + return NOTIFY_OK;
5581 +}
5582 +
5583 +/**
5584 + * cpr3_regulator_register() - register the regulators for a CPR3 controller and
5585 + * perform CPR hardware initialization
5586 + * @pdev: Platform device pointer for the CPR3 controller
5587 + * @ctrl: Pointer to the CPR3 controller
5588 + *
5589 + * Return: 0 on success, errno on failure
5590 + */
5591 +int cpr3_regulator_register(struct platform_device *pdev,
5592 + struct cpr3_controller *ctrl)
5593 +{
5594 + struct device *dev = &pdev->dev;
5595 + struct resource *res;
5596 + int i, j, rc;
5597 +
5598 + if (!dev->of_node) {
5599 + dev_err(dev, "%s: Device tree node is missing\n", __func__);
5600 + return -EINVAL;
5601 + }
5602 +
5603 + if (!ctrl || !ctrl->name) {
5604 + dev_err(dev, "%s: CPR controller data is missing\n", __func__);
5605 + return -EINVAL;
5606 + }
5607 +
5608 + rc = cpr3_regulator_validate_controller(ctrl);
5609 + if (rc) {
5610 + cpr3_err(ctrl, "controller validation failed, rc=%d\n", rc);
5611 + return rc;
5612 + }
5613 +
5614 + mutex_init(&ctrl->lock);
5615 +
5616 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cpr_ctrl");
5617 + if (!res || !res->start) {
5618 + cpr3_err(ctrl, "CPR controller address is missing\n");
5619 + return -ENXIO;
5620 + }
5621 + ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res));
5622 +
5623 + if (ctrl->aging_possible_mask) {
5624 + /*
5625 + * Aging possible register address is required if an aging
5626 + * possible mask has been specified.
5627 + */
5628 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
5629 + "aging_allowed");
5630 + if (!res || !res->start) {
5631 + cpr3_err(ctrl, "CPR aging allowed address is missing\n");
5632 + return -ENXIO;
5633 + }
5634 + ctrl->aging_possible_reg = devm_ioremap(dev, res->start,
5635 + resource_size(res));
5636 + }
5637 +
5638 + ctrl->irq = platform_get_irq_byname(pdev, "cpr");
5639 + if (ctrl->irq < 0) {
5640 + cpr3_err(ctrl, "missing CPR interrupt\n");
5641 + return ctrl->irq;
5642 + }
5643 +
5644 + if (ctrl->supports_hw_closed_loop) {
5645 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
5646 + ctrl->ceiling_irq = platform_get_irq_byname(pdev,
5647 + "ceiling");
5648 + if (ctrl->ceiling_irq < 0) {
5649 + cpr3_err(ctrl, "missing ceiling interrupt\n");
5650 + return ctrl->ceiling_irq;
5651 + }
5652 + }
5653 + }
5654 +
5655 + rc = cpr3_regulator_init_ctrl_data(ctrl);
5656 + if (rc) {
5657 + cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n",
5658 + rc);
5659 + return rc;
5660 + }
5661 +
5662 + for (i = 0; i < ctrl->thread_count; i++) {
5663 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
5664 + rc = cpr3_regulator_init_vreg_data(
5665 + &ctrl->thread[i].vreg[j]);
5666 + if (rc)
5667 + return rc;
5668 + cpr3_print_quots(&ctrl->thread[i].vreg[j]);
5669 + }
5670 + }
5671 +
5672 + /*
5673 + * Add the maximum possible aging voltage margin until it is possible
5674 + * to perform an aging measurement.
5675 + */
5676 + if (ctrl->aging_required)
5677 + cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
5678 +
5679 + rc = cpr3_regulator_init_ctrl(ctrl);
5680 + if (rc) {
5681 + cpr3_err(ctrl, "CPR controller initialization failed, rc=%d\n",
5682 + rc);
5683 + return rc;
5684 + }
5685 +
5686 + /* Register regulator devices for all threads. */
5687 + for (i = 0; i < ctrl->thread_count; i++) {
5688 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
5689 + rc = cpr3_regulator_vreg_register(
5690 + &ctrl->thread[i].vreg[j]);
5691 + if (rc) {
5692 + cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n",
5693 + rc);
5694 + goto free_regulators;
5695 + }
5696 + }
5697 + }
5698 +
5699 + rc = devm_request_threaded_irq(dev, ctrl->irq, NULL,
5700 + cpr3_irq_handler,
5701 + IRQF_ONESHOT |
5702 + IRQF_TRIGGER_RISING,
5703 + "cpr3", ctrl);
5704 + if (rc) {
5705 + cpr3_err(ctrl, "could not request IRQ %d, rc=%d\n",
5706 + ctrl->irq, rc);
5707 + goto free_regulators;
5708 + }
5709 +
5710 + if (ctrl->supports_hw_closed_loop &&
5711 + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
5712 + rc = devm_request_threaded_irq(dev, ctrl->ceiling_irq, NULL,
5713 + cpr3_ceiling_irq_handler,
5714 + IRQF_ONESHOT | IRQF_TRIGGER_RISING,
5715 + "cpr3_ceiling", ctrl);
5716 + if (rc) {
5717 + cpr3_err(ctrl, "could not request ceiling IRQ %d, rc=%d\n",
5718 + ctrl->ceiling_irq, rc);
5719 + goto free_regulators;
5720 + }
5721 + }
5722 +
5723 + mutex_lock(&cpr3_controller_list_mutex);
5724 + cpr3_regulator_debugfs_ctrl_add(ctrl);
5725 + list_add(&ctrl->list, &cpr3_controller_list);
5726 + mutex_unlock(&cpr3_controller_list_mutex);
5727 +
5728 + if (ctrl->panic_regs_info) {
5729 + /* Register panic notification call back */
5730 + ctrl->panic_notifier.notifier_call = cpr3_panic_callback;
5731 + atomic_notifier_chain_register(&panic_notifier_list,
5732 + &ctrl->panic_notifier);
5733 + }
5734 +
5735 + return 0;
5736 +
5737 +free_regulators:
5738 + for (i = 0; i < ctrl->thread_count; i++)
5739 + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
5740 + if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev))
5741 + regulator_unregister(
5742 + ctrl->thread[i].vreg[j].rdev);
5743 + return rc;
5744 +}
5745 +
5746 +/**
5747 + * cpr3_open_loop_regulator_register() - register the regulators for a CPR3
5748 + * controller which will always work in Open loop and
5749 + * won't support close loop.
5750 + * @pdev: Platform device pointer for the CPR3 controller
5751 + * @ctrl: Pointer to the CPR3 controller
5752 + *
5753 + * Return: 0 on success, errno on failure
5754 + */
5755 +int cpr3_open_loop_regulator_register(struct platform_device *pdev,
5756 + struct cpr3_controller *ctrl)
5757 +{
5758 + struct device *dev = &pdev->dev;
5759 + struct cpr3_regulator *vreg;
5760 + int i, j, rc;
5761 +
5762 + if (!dev->of_node) {
5763 + dev_err(dev, "%s: Device tree node is missing\n", __func__);
5764 + return -EINVAL;
5765 + }
5766 +
5767 + if (!ctrl || !ctrl->name) {
5768 + dev_err(dev, "%s: CPR controller data is missing\n", __func__);
5769 + return -EINVAL;
5770 + }
5771 +
5772 + if (!ctrl->vdd_regulator) {
5773 + cpr3_err(ctrl, "vdd regulator missing\n");
5774 + return -EINVAL;
5775 + }
5776 +
5777 + mutex_init(&ctrl->lock);
5778 +
5779 + rc = cpr3_regulator_init_ctrl_data(ctrl);
5780 + if (rc) {
5781 + cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n",
5782 + rc);
5783 + return rc;
5784 + }
5785 +
5786 + for (i = 0; i < ctrl->thread_count; i++) {
5787 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
5788 + vreg = &ctrl->thread[i].vreg[j];
5789 + vreg->corner[i].last_volt =
5790 + vreg->corner[i].open_loop_volt;
5791 + }
5792 + }
5793 +
5794 + /* Register regulator devices for all threads. */
5795 + for (i = 0; i < ctrl->thread_count; i++) {
5796 + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
5797 + rc = cpr3_regulator_vreg_register(
5798 + &ctrl->thread[i].vreg[j]);
5799 + if (rc) {
5800 + cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n",
5801 + rc);
5802 + goto free_regulators;
5803 + }
5804 + }
5805 + }
5806 +
5807 + mutex_lock(&cpr3_controller_list_mutex);
5808 + list_add(&ctrl->list, &cpr3_controller_list);
5809 + mutex_unlock(&cpr3_controller_list_mutex);
5810 +
5811 + return 0;
5812 +
5813 +free_regulators:
5814 + for (i = 0; i < ctrl->thread_count; i++)
5815 + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
5816 + if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev))
5817 + regulator_unregister(
5818 + ctrl->thread[i].vreg[j].rdev);
5819 + return rc;
5820 +}
5821 +
5822 +/**
5823 + * cpr3_regulator_unregister() - unregister the regulators for a CPR3 controller
5824 + * and perform CPR hardware shutdown
5825 + * @ctrl: Pointer to the CPR3 controller
5826 + *
5827 + * Return: 0 on success, errno on failure
5828 + */
5829 +int cpr3_regulator_unregister(struct cpr3_controller *ctrl)
5830 +{
5831 + int i, j, rc = 0;
5832 +
5833 + mutex_lock(&cpr3_controller_list_mutex);
5834 + list_del(&ctrl->list);
5835 + cpr3_regulator_debugfs_ctrl_remove(ctrl);
5836 + mutex_unlock(&cpr3_controller_list_mutex);
5837 +
5838 + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
5839 + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
5840 + if (rc)
5841 + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
5842 + rc);
5843 + }
5844 +
5845 + cpr3_ctrl_loop_disable(ctrl);
5846 +
5847 + cpr3_closed_loop_disable(ctrl);
5848 +
5849 + if (ctrl->vdd_limit_regulator) {
5850 + regulator_disable(ctrl->vdd_limit_regulator);
5851 + }
5852 +
5853 + for (i = 0; i < ctrl->thread_count; i++)
5854 + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
5855 + regulator_unregister(ctrl->thread[i].vreg[j].rdev);
5856 +
5857 + if (ctrl->panic_notifier.notifier_call)
5858 + atomic_notifier_chain_unregister(&panic_notifier_list,
5859 + &ctrl->panic_notifier);
5860 +
5861 + return 0;
5862 +}
5863 +
5864 +/**
5865 + * cpr3_open_loop_regulator_unregister() - unregister the regulators for a CPR3
5866 + * open loop controller and perform CPR hardware shutdown
5867 + * @ctrl: Pointer to the CPR3 controller
5868 + *
5869 + * Return: 0 on success, errno on failure
5870 + */
5871 +int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl)
5872 +{
5873 + int i, j;
5874 +
5875 + mutex_lock(&cpr3_controller_list_mutex);
5876 + list_del(&ctrl->list);
5877 + mutex_unlock(&cpr3_controller_list_mutex);
5878 +
5879 + if (ctrl->vdd_limit_regulator) {
5880 + regulator_disable(ctrl->vdd_limit_regulator);
5881 + }
5882 +
5883 + for (i = 0; i < ctrl->thread_count; i++)
5884 + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
5885 + regulator_unregister(ctrl->thread[i].vreg[j].rdev);
5886 +
5887 + if (ctrl->panic_notifier.notifier_call)
5888 + atomic_notifier_chain_unregister(&panic_notifier_list,
5889 + &ctrl->panic_notifier);
5890 +
5891 + return 0;
5892 +}
5893 --- /dev/null
5894 +++ b/drivers/regulator/cpr3-regulator.h
5895 @@ -0,0 +1,1211 @@
5896 +/*
5897 + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
5898 + *
5899 + * This program is free software; you can redistribute it and/or modify
5900 + * it under the terms of the GNU General Public License version 2 and
5901 + * only version 2 as published by the Free Software Foundation.
5902 + *
5903 + * This program is distributed in the hope that it will be useful,
5904 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5905 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5906 + * GNU General Public License for more details.
5907 + */
5908 +
5909 +#ifndef __REGULATOR_CPR3_REGULATOR_H__
5910 +#define __REGULATOR_CPR3_REGULATOR_H__
5911 +
5912 +#include <linux/clk.h>
5913 +#include <linux/mutex.h>
5914 +#include <linux/of.h>
5915 +#include <linux/platform_device.h>
5916 +#include <linux/types.h>
5917 +#include <linux/power/qcom/apm.h>
5918 +#include <linux/regulator/driver.h>
5919 +
5920 +struct cpr3_controller;
5921 +struct cpr3_thread;
5922 +
5923 +/**
5924 + * struct cpr3_fuse_param - defines one contiguous segment of a fuse parameter
5925 + * that is contained within a given row.
5926 + * @row: Fuse row number
5927 + * @bit_start: The first bit within the row of the fuse parameter segment
5928 + * @bit_end: The last bit within the row of the fuse parameter segment
5929 + *
5930 + * Each fuse row is 64 bits in length. bit_start and bit_end may take values
5931 + * from 0 to 63. bit_start must be less than or equal to bit_end.
5932 + */
5933 +struct cpr3_fuse_param {
5934 + unsigned row;
5935 + unsigned bit_start;
5936 + unsigned bit_end;
5937 +};
5938 +
5939 +/* Each CPR3 sensor has 16 ring oscillators */
5940 +#define CPR3_RO_COUNT 16
5941 +
5942 +/* The maximum number of sensors that can be present on a single CPR loop. */
5943 +#define CPR3_MAX_SENSOR_COUNT 256
5944 +
5945 +/* This constant is used when allocating array printing buffers. */
5946 +#define MAX_CHARS_PER_INT 10
5947 +
5948 +/**
5949 + * struct cpr4_sdelta - CPR4 controller specific data structure for the sdelta
5950 + * adjustment table which is used to adjust the VDD supply
5951 + * voltage automatically based upon the temperature and/or
5952 + * the number of online CPU cores.
5953 + * @allow_core_count_adj: Core count adjustments are allowed.
5954 + * @allow_temp_adj: Temperature based adjustments are allowed.
5955 + * @max_core_count: Maximum number of cores considered for core count
5956 + * adjustment logic.
5957 + * @temp_band_count: Number of temperature bands considered for temperature
5958 + * based adjustment logic.
5959 + * @cap_volt: CAP in uV to apply to SDELTA margins with multiple
5960 + * cpr3-regulators defined for single controller.
5961 + * @table: SDELTA table with per-online-core and temperature based
5962 + * adjustments of size (max_core_count * temp_band_count)
5963 + * Outer: core count
5964 + * Inner: temperature band
5965 + * Each element has units of VDD supply steps. Positive
5966 + * values correspond to a reduction in voltage and negative
5967 + * value correspond to an increase (this follows the SDELTA
5968 + * register semantics).
5969 + * @allow_boost: Voltage boost allowed.
5970 + * @boost_num_cores: The number of online cores at which the boost voltage
5971 + * adjustments will be applied
5972 + * @boost_table: SDELTA table with boost voltage adjustments of size
5973 + * temp_band_count. Each element has units of VDD supply
5974 + * steps. Positive values correspond to a reduction in
5975 + * voltage and negative value correspond to an increase
5976 + * (this follows the SDELTA register semantics).
5977 + */
5978 +struct cpr4_sdelta {
5979 + bool allow_core_count_adj;
5980 + bool allow_temp_adj;
5981 + int max_core_count;
5982 + int temp_band_count;
5983 + int cap_volt;
5984 + int *table;
5985 + bool allow_boost;
5986 + int boost_num_cores;
5987 + int *boost_table;
5988 +};
5989 +
5990 +/**
5991 + * struct cpr3_corner - CPR3 virtual voltage corner data structure
5992 + * @floor_volt: CPR closed-loop floor voltage in microvolts
5993 + * @ceiling_volt: CPR closed-loop ceiling voltage in microvolts
5994 + * @open_loop_volt: CPR open-loop voltage (i.e. initial voltage) in
5995 + * microvolts
5996 + * @last_volt: Last known settled CPR closed-loop voltage which is used
5997 + * when switching to a new corner
5998 + * @abs_ceiling_volt: The absolute CPR closed-loop ceiling voltage in
5999 + * microvolts. This is used to limit the ceiling_volt
6000 + * value when it is increased as a result of aging
6001 + * adjustment.
6002 + * @unaged_floor_volt: The CPR closed-loop floor voltage in microvolts before
6003 + * any aging adjustment is performed
6004 + * @unaged_ceiling_volt: The CPR closed-loop ceiling voltage in microvolts
6005 + * before any aging adjustment is performed
6006 + * @unaged_open_loop_volt: The CPR open-loop voltage (i.e. initial voltage) in
6007 + * microvolts before any aging adjusment is performed
6008 + * @system_volt: The system-supply voltage in microvolts or corners or
6009 + * levels
6010 + * @mem_acc_volt: The mem-acc-supply voltage in corners
6011 + * @proc_freq: Processor frequency in Hertz. For CPR rev. 3 and 4
6012 + * conrollers, this field is only used by platform specific
6013 + * CPR3 driver for interpolation. For CPRh-compliant
6014 + * controllers, this frequency is also utilized by the
6015 + * clock driver to determine the corner to CPU clock
6016 + * frequency mappings.
6017 + * @cpr_fuse_corner: Fused corner index associated with this virtual corner
6018 + * (only used by platform specific CPR3 driver for
6019 + * mapping purposes)
6020 + * @target_quot: Array of target quotient values to use for each ring
6021 + * oscillator (RO) for this corner. A value of 0 should be
6022 + * specified as the target quotient for each RO that is
6023 + * unused by this corner.
6024 + * @ro_scale: Array of CPR ring oscillator (RO) scaling factors. The
6025 + * scaling factor for each RO is defined from RO0 to RO15
6026 + * with units of QUOT/V. A value of 0 may be specified for
6027 + * an RO that is unused.
6028 + * @ro_mask: Bitmap where each of the 16 LSBs indicate if the
6029 + * corresponding ROs should be masked for this corner
6030 + * @irq_en: Bitmap of the CPR interrupts to enable for this corner
6031 + * @aging_derate: The amount to derate the aging voltage adjustment
6032 + * determined for the reference corner in units of uV/mV.
6033 + * E.g. a value of 900 would imply that the adjustment for
6034 + * this corner should be 90% (900/1000) of that for the
6035 + * reference corner.
6036 + * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as
6037 + * opposed to closed-loop operation must be used for this
6038 + * corner on CPRh controllers.
6039 + * @sdelta: The CPR4 controller specific data for this corner. This
6040 + * field is applicable for CPR4 controllers.
6041 + *
6042 + * The value of last_volt is initialized inside of the cpr3_regulator_register()
6043 + * call with the open_loop_volt value. It can later be updated to the settled
6044 + * VDD supply voltage. The values for unaged_floor_volt, unaged_ceiling_volt,
6045 + * and unaged_open_loop_volt are initialized inside of cpr3_regulator_register()
6046 + * if ctrl->aging_required == true. These three values must be pre-initialized
6047 + * if cpr3_regulator_register() is called with ctrl->aging_required == false and
6048 + * ctrl->aging_succeeded == true.
6049 + *
6050 + * The values of ro_mask and irq_en are initialized inside of the
6051 + * cpr3_regulator_register() call.
6052 + */
6053 +struct cpr3_corner {
6054 + int floor_volt;
6055 + int ceiling_volt;
6056 + int cold_temp_open_loop_volt;
6057 + int normal_temp_open_loop_volt;
6058 + int open_loop_volt;
6059 + int last_volt;
6060 + int abs_ceiling_volt;
6061 + int unaged_floor_volt;
6062 + int unaged_ceiling_volt;
6063 + int unaged_open_loop_volt;
6064 + int system_volt;
6065 + int mem_acc_volt;
6066 + u32 proc_freq;
6067 + int cpr_fuse_corner;
6068 + u32 target_quot[CPR3_RO_COUNT];
6069 + u32 ro_scale[CPR3_RO_COUNT];
6070 + u32 ro_mask;
6071 + u32 irq_en;
6072 + int aging_derate;
6073 + bool use_open_loop;
6074 + struct cpr4_sdelta *sdelta;
6075 +};
6076 +
6077 +/**
6078 + * struct cprh_corner_band - CPRh controller specific data structure which
6079 + * encapsulates the range of corners and the SDELTA
6080 + * adjustment table to be applied to the corners within
6081 + * the min and max bounds of the corner band.
6082 + * @corner: Corner number which defines the corner band boundary
6083 + * @sdelta: The SDELTA adjustment table which contains core-count
6084 + * and temp based margin adjustments that are applicable
6085 + * to the corner band.
6086 + */
6087 +struct cprh_corner_band {
6088 + int corner;
6089 + struct cpr4_sdelta *sdelta;
6090 +};
6091 +
6092 +/**
6093 + * struct cpr3_fuse_parameters - CPR4 fuse specific data structure which has
6094 + * the required fuse parameters need for Close Loop CPR
6095 + * @(*apss_ro_sel_param)[2]: Pointer to RO select fuse details
6096 + * @(*apss_init_voltage_param)[2]: Pointer to Target voltage fuse details
6097 + * @(*apss_target_quot_param)[2]: Pointer to Target quot fuse details
6098 + * @(*apss_quot_offset_param)[2]: Pointer to quot offset fuse details
6099 + * @cpr_fusing_rev_param: Pointer to CPR revision fuse details
6100 + * @apss_speed_bin_param: Pointer to Speed bin fuse details
6101 + * @cpr_boost_fuse_cfg_param: Pointer to Boost fuse cfg details
6102 + * @apss_boost_fuse_volt_param: Pointer to Boost fuse volt details
6103 + * @misc_fuse_volt_adj_param: Pointer to Misc fuse volt fuse details
6104 + */
6105 +struct cpr3_fuse_parameters {
6106 + struct cpr3_fuse_param (*apss_ro_sel_param)[2];
6107 + struct cpr3_fuse_param (*apss_init_voltage_param)[2];
6108 + struct cpr3_fuse_param (*apss_target_quot_param)[2];
6109 + struct cpr3_fuse_param (*apss_quot_offset_param)[2];
6110 + struct cpr3_fuse_param *cpr_fusing_rev_param;
6111 + struct cpr3_fuse_param *apss_speed_bin_param;
6112 + struct cpr3_fuse_param *cpr_boost_fuse_cfg_param;
6113 + struct cpr3_fuse_param *apss_boost_fuse_volt_param;
6114 + struct cpr3_fuse_param *misc_fuse_volt_adj_param;
6115 +};
6116 +
6117 +struct cpr4_mem_acc_func {
6118 + void (*set_mem_acc)(struct regulator_dev *);
6119 + void (*clear_mem_acc)(struct regulator_dev *);
6120 +};
6121 +
6122 +/**
6123 + * struct cpr4_reg_data - CPR4 regulator specific data structure which is
6124 + * target specific
6125 + * @cpr_valid_fuse_count: Number of valid fuse corners
6126 + * @fuse_ref_volt: Pointer to fuse reference voltage
6127 + * @fuse_step_volt: CPR step voltage available in fuse
6128 + * @cpr_clk_rate: CPR clock rate
6129 + * @boost_fuse_ref_volt: Boost fuse reference voltage
6130 + * @boost_ceiling_volt: Boost ceiling voltage
6131 + * @boost_floor_volt: Boost floor voltage
6132 + * @cpr3_fuse_params: Pointer to CPR fuse parameters
6133 + * @mem_acc_funcs: Pointer to MEM ACC set/clear functions
6134 + **/
6135 +struct cpr4_reg_data {
6136 + u32 cpr_valid_fuse_count;
6137 + int *fuse_ref_volt;
6138 + u32 fuse_step_volt;
6139 + u32 cpr_clk_rate;
6140 + int boost_fuse_ref_volt;
6141 + int boost_ceiling_volt;
6142 + int boost_floor_volt;
6143 + struct cpr3_fuse_parameters *cpr3_fuse_params;
6144 + struct cpr4_mem_acc_func *mem_acc_funcs;
6145 +};
6146 +/**
6147 + * struct cpr3_reg_data - CPR3 regulator specific data structure which is
6148 + * target specific
6149 + * @cpr_valid_fuse_count: Number of valid fuse corners
6150 + * @(*init_voltage_param)[2]: Pointer to Target voltage fuse details
6151 + * @fuse_ref_volt: Pointer to fuse reference voltage
6152 + * @fuse_step_volt: CPR step voltage available in fuse
6153 + * @cpr_clk_rate: CPR clock rate
6154 + * @cpr3_fuse_params: Pointer to CPR fuse parameters
6155 + **/
6156 +struct cpr3_reg_data {
6157 + u32 cpr_valid_fuse_count;
6158 + struct cpr3_fuse_param (*init_voltage_param)[2];
6159 + int *fuse_ref_volt;
6160 + u32 fuse_step_volt;
6161 + u32 cpr_clk_rate;
6162 +};
6163 +
6164 +/**
6165 + * struct cpr3_regulator - CPR3 logical regulator instance associated with a
6166 + * given CPR3 hardware thread
6167 + * @of_node: Device node associated with the device tree child node
6168 + * of this CPR3 regulator
6169 + * @thread: Pointer to the CPR3 thread which manages this CPR3
6170 + * regulator
6171 + * @name: Unique name for this CPR3 regulator which is filled
6172 + * using the device tree regulator-name property
6173 + * @rdesc: Regulator description for this CPR3 regulator
6174 + * @rdev: Regulator device pointer for the regulator registered
6175 + * for this CPR3 regulator
6176 + * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used
6177 + * to manage memory circuitry settings based upon CPR3
6178 + * regulator output voltage.
6179 + * @corner: Array of all corners supported by this CPR3 regulator
6180 + * @corner_count: The number of elements in the corner array
6181 + * @corner_band: Array of all corner bands supported by CPRh compatible
6182 + * controllers
6183 + * @cpr4_regulator_data Target specific cpr4 regulator data
6184 + * @cpr3_regulator_data Target specific cpr3 regulator data
6185 + * @corner_band_count: The number of elements in the corner band array
6186 + * @platform_fuses: Pointer to platform specific CPR fuse data (only used by
6187 + * platform specific CPR3 driver)
6188 + * @speed_bin_fuse: Value read from the speed bin fuse parameter
6189 + * @speed_bins_supported: The number of speed bins supported by the device tree
6190 + * configuration for this CPR3 regulator
6191 + * @cpr_rev_fuse: Value read from the CPR fusing revision fuse parameter
6192 + * @fuse_combo: Platform specific enum value identifying the specific
6193 + * combination of fuse values found on a given chip
6194 + * @fuse_combos_supported: The number of fuse combinations supported by the
6195 + * device tree configuration for this CPR3 regulator
6196 + * @fuse_corner_count: Number of corners defined by fuse parameters
6197 + * @fuse_corner_map: Array of length fuse_corner_count which specifies the
6198 + * highest corner associated with each fuse corner. Note
6199 + * that each element must correspond to a valid corner
6200 + * and that element values must be strictly increasing.
6201 + * Also, it is acceptable for the lowest fuse corner to map
6202 + * to a corner other than the lowest. Likewise, it is
6203 + * acceptable for the highest fuse corner to map to a
6204 + * corner other than the highest.
6205 + * @fuse_combo_corner_sum: The sum of the corner counts across all fuse combos
6206 + * @fuse_combo_offset: The device tree property array offset for the selected
6207 + * fuse combo
6208 + * @speed_bin_corner_sum: The sum of the corner counts across all speed bins
6209 + * This may be specified as 0 if per speed bin parsing
6210 + * support is not required.
6211 + * @speed_bin_offset: The device tree property array offset for the selected
6212 + * speed bin
6213 + * @fuse_combo_corner_band_sum: The sum of the corner band counts across all
6214 + * fuse combos
6215 + * @fuse_combo_corner_band_offset: The device tree property array offset for
6216 + * the corner band count corresponding to the selected
6217 + * fuse combo
6218 + * @speed_bin_corner_band_sum: The sum of the corner band counts across all
6219 + * speed bins. This may be specified as 0 if per speed bin
6220 + * parsing support is not required
6221 + * @speed_bin_corner_band_offset: The device tree property array offset for the
6222 + * corner band count corresponding to the selected speed
6223 + * bin
6224 + * @pd_bypass_mask: Bit mask of power domains associated with this CPR3
6225 + * regulator
6226 + * @dynamic_floor_corner: Index identifying the voltage corner for the CPR3
6227 + * regulator whose last_volt value should be used as the
6228 + * global CPR floor voltage if all of the power domains
6229 + * associated with this CPR3 regulator are bypassed
6230 + * @uses_dynamic_floor: Boolean flag indicating that dynamic_floor_corner should
6231 + * be utilized for the CPR3 regulator
6232 + * @current_corner: Index identifying the currently selected voltage corner
6233 + * for the CPR3 regulator or less than 0 if no corner has
6234 + * been requested
6235 + * @last_closed_loop_corner: Index identifying the last voltage corner for the
6236 + * CPR3 regulator which was configured when operating in
6237 + * CPR closed-loop mode or less than 0 if no corner has
6238 + * been requested. CPR registers are only written to when
6239 + * using closed-loop mode.
6240 + * @aggregated: Boolean flag indicating that this CPR3 regulator
6241 + * participated in the last aggregation event
6242 + * @debug_corner: Index identifying voltage corner used for displaying
6243 + * corner configuration values in debugfs
6244 + * @vreg_enabled: Boolean defining the enable state of the CPR3
6245 + * regulator's regulator within the regulator framework.
6246 + * @aging_allowed: Boolean defining if CPR aging adjustments are allowed
6247 + * for this CPR3 regulator given the fuse combo of the
6248 + * device
6249 + * @aging_allow_open_loop_adj: Boolean defining if the open-loop voltage of each
6250 + * corner of this regulator should be adjusted as a result
6251 + * of an aging measurement. This flag can be set to false
6252 + * when the open-loop voltage adjustments have been
6253 + * specified such that they include the maximum possible
6254 + * aging adjustment. This flag is only used if
6255 + * aging_allowed == true.
6256 + * @aging_corner: The corner that should be configured for this regulator
6257 + * when an aging measurement is performed.
6258 + * @aging_max_adjust_volt: The maximum aging voltage margin in microvolts that
6259 + * may be added to the target quotients of this regulator.
6260 + * A value of 0 may be specified if this regulator does not
6261 + * require any aging adjustment.
6262 + * @allow_core_count_adj: Core count adjustments are allowed for this regulator.
6263 + * @allow_temp_adj: Temperature based adjustments are allowed for this
6264 + * regulator.
6265 + * @max_core_count: Maximum number of cores considered for core count
6266 + * adjustment logic.
6267 + * @allow_boost: Voltage boost allowed for this regulator.
6268 + *
6269 + * This structure contains both configuration and runtime state data. The
6270 + * elements current_corner, last_closed_loop_corner, aggregated, debug_corner,
6271 + * and vreg_enabled are state variables.
6272 + */
6273 +struct cpr3_regulator {
6274 + struct device_node *of_node;
6275 + struct cpr3_thread *thread;
6276 + const char *name;
6277 + struct regulator_desc rdesc;
6278 + struct regulator_dev *rdev;
6279 + struct regulator *mem_acc_regulator;
6280 + struct cpr3_corner *corner;
6281 + int corner_count;
6282 + struct cprh_corner_band *corner_band;
6283 + struct cpr4_reg_data *cpr4_regulator_data;
6284 + struct cpr3_reg_data *cpr3_regulator_data;
6285 + u32 corner_band_count;
6286 +
6287 + void *platform_fuses;
6288 + int speed_bin_fuse;
6289 + int speed_bins_supported;
6290 + int cpr_rev_fuse;
6291 + int part_type;
6292 + int part_type_supported;
6293 + int fuse_combo;
6294 + int fuse_combos_supported;
6295 + int fuse_corner_count;
6296 + int *fuse_corner_map;
6297 + int fuse_combo_corner_sum;
6298 + int fuse_combo_offset;
6299 + int speed_bin_corner_sum;
6300 + int speed_bin_offset;
6301 + int fuse_combo_corner_band_sum;
6302 + int fuse_combo_corner_band_offset;
6303 + int speed_bin_corner_band_sum;
6304 + int speed_bin_corner_band_offset;
6305 + u32 pd_bypass_mask;
6306 + int dynamic_floor_corner;
6307 + bool uses_dynamic_floor;
6308 +
6309 + int current_corner;
6310 + int last_closed_loop_corner;
6311 + bool aggregated;
6312 + int debug_corner;
6313 + bool vreg_enabled;
6314 +
6315 + bool aging_allowed;
6316 + bool aging_allow_open_loop_adj;
6317 + int aging_corner;
6318 + int aging_max_adjust_volt;
6319 +
6320 + bool allow_core_count_adj;
6321 + bool allow_temp_adj;
6322 + int max_core_count;
6323 + bool allow_boost;
6324 +};
6325 +
6326 +/**
6327 + * struct cpr3_thread - CPR3 hardware thread data structure
6328 + * @thread_id: Hardware thread ID
6329 + * @of_node: Device node associated with the device tree child node
6330 + * of this CPR3 thread
6331 + * @ctrl: Pointer to the CPR3 controller which manages this thread
6332 + * @vreg: Array of CPR3 regulators handled by the CPR3 thread
6333 + * @vreg_count: Number of elements in the vreg array
6334 + * @aggr_corner: CPR corner containing the in process aggregated voltage
6335 + * and target quotient configurations which will be applied
6336 + * @last_closed_loop_aggr_corner: CPR corner containing the most recent
6337 + * configurations which were written into hardware
6338 + * registers when operating in closed loop mode (i.e. with
6339 + * CPR enabled)
6340 + * @consecutive_up: The number of consecutive CPR step up events needed to
6341 + * to trigger an up interrupt
6342 + * @consecutive_down: The number of consecutive CPR step down events needed to
6343 + * to trigger a down interrupt
6344 + * @up_threshold: The number CPR error steps required to generate an up
6345 + * event
6346 + * @down_threshold: The number CPR error steps required to generate a down
6347 + * event
6348 + *
6349 + * This structure contains both configuration and runtime state data. The
6350 + * elements aggr_corner and last_closed_loop_aggr_corner are state variables.
6351 + */
6352 +struct cpr3_thread {
6353 + u32 thread_id;
6354 + struct device_node *of_node;
6355 + struct cpr3_controller *ctrl;
6356 + struct cpr3_regulator *vreg;
6357 + int vreg_count;
6358 + struct cpr3_corner aggr_corner;
6359 + struct cpr3_corner last_closed_loop_aggr_corner;
6360 +
6361 + u32 consecutive_up;
6362 + u32 consecutive_down;
6363 + u32 up_threshold;
6364 + u32 down_threshold;
6365 +};
6366 +
6367 +/* Per CPR controller data */
6368 +/**
6369 + * enum cpr3_mem_acc_corners - Constants which define the number of mem-acc
6370 + * regulator corners available in the mem-acc corner map array.
6371 + * %CPR3_MEM_ACC_LOW_CORNER: Index in mem-acc corner map array mapping to the
6372 + * mem-acc regulator corner
6373 + * to be used for low voltage vdd supply
6374 + * %CPR3_MEM_ACC_HIGH_CORNER: Index in mem-acc corner map array mapping to the
6375 + * mem-acc regulator corner to be used for high
6376 + * voltage vdd supply
6377 + * %CPR3_MEM_ACC_CORNERS: Number of elements in the mem-acc corner map
6378 + * array
6379 + */
6380 +enum cpr3_mem_acc_corners {
6381 + CPR3_MEM_ACC_LOW_CORNER = 0,
6382 + CPR3_MEM_ACC_HIGH_CORNER = 1,
6383 + CPR3_MEM_ACC_CORNERS = 2,
6384 +};
6385 +
6386 +/**
6387 + * enum cpr3_count_mode - CPR3 controller count mode which defines the
6388 + * method that CPR sensor data is acquired
6389 + * %CPR3_COUNT_MODE_ALL_AT_ONCE_MIN: Capture all CPR sensor readings
6390 + * simultaneously and report the minimum
6391 + * value seen in successive measurements
6392 + * %CPR3_COUNT_MODE_ALL_AT_ONCE_MAX: Capture all CPR sensor readings
6393 + * simultaneously and report the maximum
6394 + * value seen in successive measurements
6395 + * %CPR3_COUNT_MODE_STAGGERED: Read one sensor at a time in a
6396 + * sequential fashion
6397 + * %CPR3_COUNT_MODE_ALL_AT_ONCE_AGE: Capture all CPR aging sensor readings
6398 + * simultaneously.
6399 + */
6400 +enum cpr3_count_mode {
6401 + CPR3_COUNT_MODE_ALL_AT_ONCE_MIN = 0,
6402 + CPR3_COUNT_MODE_ALL_AT_ONCE_MAX = 1,
6403 + CPR3_COUNT_MODE_STAGGERED = 2,
6404 + CPR3_COUNT_MODE_ALL_AT_ONCE_AGE = 3,
6405 +};
6406 +
6407 +/**
6408 + * enum cpr_controller_type - supported CPR controller hardware types
6409 + * %CPR_CTRL_TYPE_CPR3: HW has CPR3 controller
6410 + * %CPR_CTRL_TYPE_CPR4: HW has CPR4 controller
6411 + */
6412 +enum cpr_controller_type {
6413 + CPR_CTRL_TYPE_CPR3,
6414 + CPR_CTRL_TYPE_CPR4,
6415 +};
6416 +
6417 +/**
6418 + * cpr_setting - supported CPR global settings
6419 + * %CPR_DEFAULT: default mode from dts will be used
6420 + * %CPR_DISABLED: ceiling voltage will be used for all the corners
6421 + * %CPR_OPEN_LOOP_EN: CPR will work in OL
6422 + * %CPR_CLOSED_LOOP_EN: CPR will work in CL, if supported
6423 + */
6424 +enum cpr_setting {
6425 + CPR_DEFAULT = 0,
6426 + CPR_DISABLED = 1,
6427 + CPR_OPEN_LOOP_EN = 2,
6428 + CPR_CLOSED_LOOP_EN = 3,
6429 +};
6430 +
6431 +/**
6432 + * struct cpr3_aging_sensor_info - CPR3 aging sensor information
6433 + * @sensor_id The index of the CPR3 sensor to be used in the aging
6434 + * measurement.
6435 + * @ro_scale The CPR ring oscillator (RO) scaling factor for the
6436 + * aging sensor with units of QUOT/V.
6437 + * @init_quot_diff: The fused quotient difference between aged and un-aged
6438 + * paths that was measured at manufacturing time.
6439 + * @measured_quot_diff: The quotient difference measured at runtime.
6440 + * @bypass_mask: Bit mask of the CPR sensors that must be bypassed during
6441 + * the aging measurement for this sensor
6442 + *
6443 + * This structure contains both configuration and runtime state data. The
6444 + * element measured_quot_diff is a state variable.
6445 + */
6446 +struct cpr3_aging_sensor_info {
6447 + u32 sensor_id;
6448 + u32 ro_scale;
6449 + int init_quot_diff;
6450 + int measured_quot_diff;
6451 + u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32];
6452 +};
6453 +
6454 +/**
6455 + * struct cpr3_reg_info - Register information data structure
6456 + * @name: Register name
6457 + * @addr: Register physical address
6458 + * @value: Register content
6459 + * @virt_addr: Register virtual address
6460 + *
6461 + * This data structure is used to dump some critical register contents
6462 + * when the device crashes due to a kernel panic.
6463 + */
6464 +struct cpr3_reg_info {
6465 + const char *name;
6466 + u32 addr;
6467 + u32 value;
6468 + void __iomem *virt_addr;
6469 +};
6470 +
6471 +/**
6472 + * struct cpr3_panic_regs_info - Data structure to dump critical register
6473 + * contents.
6474 + * @reg_count: Number of elements in the regs array
6475 + * @regs: Array of critical registers information
6476 + *
6477 + * This data structure is used to dump critical register contents when
6478 + * the device crashes due to a kernel panic.
6479 + */
6480 +struct cpr3_panic_regs_info {
6481 + int reg_count;
6482 + struct cpr3_reg_info *regs;
6483 +};
6484 +
6485 +/**
6486 + * struct cpr3_controller - CPR3 controller data structure
6487 + * @dev: Device pointer for the CPR3 controller device
6488 + * @name: Unique name for the CPR3 controller
6489 + * @ctrl_id: Controller ID corresponding to the VDD supply number
6490 + * that this CPR3 controller manages.
6491 + * @cpr_ctrl_base: Virtual address of the CPR3 controller base register
6492 + * @fuse_base: Virtual address of fuse row 0
6493 + * @aging_possible_reg: Virtual address of an optional platform-specific
6494 + * register that must be ready to determine if it is
6495 + * possible to perform an aging measurement.
6496 + * @list: list head used in a global cpr3-regulator list so that
6497 + * cpr3-regulator structs can be found easily in RAM dumps
6498 + * @thread: Array of CPR3 threads managed by the CPR3 controller
6499 + * @thread_count: Number of elements in the thread array
6500 + * @sensor_owner: Array of thread IDs indicating which thread owns a given
6501 + * CPR sensor
6502 + * @sensor_count: The number of CPR sensors found on the CPR loop managed
6503 + * by this CPR controller. Must be equal to the number of
6504 + * elements in the sensor_owner array
6505 + * @soc_revision: Revision number of the SoC. This may be unused by
6506 + * platforms that do not have different behavior for
6507 + * different SoC revisions.
6508 + * @lock: Mutex lock used to ensure mutual exclusion between
6509 + * all of the threads associated with the controller
6510 + * @vdd_regulator: Pointer to the VDD supply regulator which this CPR3
6511 + * controller manages
6512 + * @system_regulator: Pointer to the optional system-supply regulator upon
6513 + * which the VDD supply regulator depends.
6514 + * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used
6515 + * to manage memory circuitry settings based upon the
6516 + * VDD supply output voltage.
6517 + * @vdd_limit_regulator: Pointer to the VDD supply limit regulator which is used
6518 + * for hardware closed-loop in order specify ceiling and
6519 + * floor voltage limits (platform specific)
6520 + * @system_supply_max_volt: Voltage in microvolts which corresponds to the
6521 + * absolute ceiling voltage of the system-supply
6522 + * @mem_acc_threshold_volt: mem-acc threshold voltage in microvolts
6523 + * @mem_acc_corner_map: mem-acc regulator corners mapping to low and high
6524 + * voltage mem-acc settings for the memories powered by
6525 + * this CPR3 controller and its associated CPR3 regulators
6526 + * @mem_acc_crossover_volt: Voltage in microvolts corresponding to the voltage
6527 + * that the VDD supply must be set to while a MEM ACC
6528 + * switch is in progress. This element must be initialized
6529 + * for CPRh controllers when a MEM ACC threshold voltage is
6530 + * defined.
6531 + * @core_clk: Pointer to the CPR3 controller core clock
6532 + * @iface_clk: Pointer to the CPR3 interface clock (platform specific)
6533 + * @bus_clk: Pointer to the CPR3 bus clock (platform specific)
6534 + * @irq: CPR interrupt number
6535 + * @irq_affinity_mask: The cpumask for the CPUs which the CPR interrupt should
6536 + * have affinity for
6537 + * @cpu_hotplug_notifier: CPU hotplug notifier used to reset IRQ affinity when a
6538 + * CPU is brought back online
6539 + * @ceiling_irq: Interrupt number for the interrupt that is triggered
6540 + * when hardware closed-loop attempts to exceed the ceiling
6541 + * voltage
6542 + * @apm: Handle to the array power mux (APM)
6543 + * @apm_threshold_volt: Voltage in microvolts which defines the threshold
6544 + * voltage to determine the APM supply selection for
6545 + * each corner
6546 + * @apm_crossover_volt: Voltage in microvolts corresponding to the voltage that
6547 + * the VDD supply must be set to while an APM switch is in
6548 + * progress. This element must be initialized for CPRh
6549 + * controllers when an APM threshold voltage is defined
6550 + * @apm_adj_volt: Minimum difference between APM threshold voltage and
6551 + * open-loop voltage which allows the APM threshold voltage
6552 + * to be used as a ceiling
6553 + * @apm_high_supply: APM supply to configure if VDD voltage is greater than
6554 + * or equal to the APM threshold voltage
6555 + * @apm_low_supply: APM supply to configure if the VDD voltage is less than
6556 + * the APM threshold voltage
6557 + * @base_volt: Minimum voltage in microvolts supported by the VDD
6558 + * supply managed by this CPR controller
6559 + * @corner_switch_delay_time: The delay time in nanoseconds used by the CPR
6560 + * controller to wait for voltage settling before
6561 + * acknowledging the OSM block after corner changes
6562 + * @cpr_clock_rate: CPR reference clock frequency in Hz.
6563 + * @sensor_time: The time in nanoseconds that each sensor takes to
6564 + * perform a measurement.
6565 + * @loop_time: The time in nanoseconds between consecutive CPR
6566 + * measurements.
6567 + * @up_down_delay_time: The time to delay in nanoseconds between consecutive CPR
6568 + * measurements when the last measurement recommended
6569 + * increasing or decreasing the vdd-supply voltage.
6570 + * (platform specific)
6571 + * @idle_clocks: Number of CPR reference clock ticks that the CPR
6572 + * controller waits in transitional states.
6573 + * @step_quot_init_min: The default minimum CPR step quotient value. The step
6574 + * quotient is the number of additional ring oscillator
6575 + * ticks observed when increasing one step in vdd-supply
6576 + * output voltage.
6577 + * @step_quot_init_max: The default maximum CPR step quotient value.
6578 + * @step_volt: Step size in microvolts between available set points
6579 + * of the VDD supply
6580 + * @down_error_step_limit: CPR4 hardware closed-loop down error step limit which
6581 + * defines the maximum number of VDD supply regulator steps
6582 + * that the voltage may be reduced as the result of a
6583 + * single CPR measurement.
6584 + * @up_error_step_limit: CPR4 hardware closed-loop up error step limit which
6585 + * defines the maximum number of VDD supply regulator steps
6586 + * that the voltage may be increased as the result of a
6587 + * single CPR measurement.
6588 + * @count_mode: CPR controller count mode
6589 + * @count_repeat: Number of times to perform consecutive sensor
6590 + * measurements when using all-at-once count modes.
6591 + * @proc_clock_throttle: Defines the processor clock frequency throttling
6592 + * register value to use. This can be used to reduce the
6593 + * clock frequency when a power domain exits a low power
6594 + * mode until CPR settles at a new voltage.
6595 + * (platform specific)
6596 + * @cpr_allowed_hw: Boolean which indicates if closed-loop CPR operation is
6597 + * permitted for a given chip based upon hardware fuse
6598 + * values
6599 + * @cpr_allowed_sw: Boolean which indicates if closed-loop CPR operation is
6600 + * permitted based upon software policies
6601 + * @supports_hw_closed_loop: Boolean which indicates if this CPR3/4 controller
6602 + * physically supports hardware closed-loop CPR operation
6603 + * @use_hw_closed_loop: Boolean which indicates that this controller will be
6604 + * using hardware closed-loop operation in place of
6605 + * software closed-loop operation.
6606 + * @ctrl_type: CPR controller type
6607 + * @saw_use_unit_mV: Boolean which indicates the unit used in SAW PVC
6608 + * interface is mV.
6609 + * @aggr_corner: CPR corner containing the most recently aggregated
6610 + * voltage configurations which are being used currently
6611 + * @cpr_enabled: Boolean which indicates that the CPR controller is
6612 + * enabled and operating in closed-loop mode. CPR clocks
6613 + * have been prepared and enabled whenever this flag is
6614 + * true.
6615 + * @last_corner_was_closed_loop: Boolean indicating if the last known corners
6616 + * were updated during closed loop operation.
6617 + * @cpr_suspended: Boolean which indicates that CPR has been temporarily
6618 + * disabled while enterring system suspend.
6619 + * @debugfs: Pointer to the debugfs directory of this CPR3 controller
6620 + * @aging_ref_volt: Reference voltage in microvolts to configure when
6621 + * performing CPR aging measurements.
6622 + * @aging_vdd_mode: vdd-supply regulator mode to configure before performing
6623 + * a CPR aging measurement. It should be one of
6624 + * REGULATOR_MODE_*.
6625 + * @aging_complete_vdd_mode: vdd-supply regulator mode to configure after
6626 + * performing a CPR aging measurement. It should be one of
6627 + * REGULATOR_MODE_*.
6628 + * @aging_ref_adjust_volt: The reference aging voltage margin in microvolts that
6629 + * should be added to the target quotients of the
6630 + * regulators managed by this controller after derating.
6631 + * @aging_required: Flag which indicates that a CPR aging measurement still
6632 + * needs to be performed for this CPR3 controller.
6633 + * @aging_succeeded: Flag which indicates that a CPR aging measurement has
6634 + * completed successfully.
6635 + * @aging_failed: Flag which indicates that a CPR aging measurement has
6636 + * failed to complete successfully.
6637 + * @aging_sensor: Array of CPR3 aging sensors which are used to perform
6638 + * aging measurements at a runtime.
6639 + * @aging_sensor_count: Number of elements in the aging_sensor array
6640 + * @aging_possible_mask: Optional bitmask used to mask off the
6641 + * aging_possible_reg register.
6642 + * @aging_possible_val: Optional value that the masked aging_possible_reg
6643 + * register must have in order for a CPR aging measurement
6644 + * to be possible.
6645 + * @step_quot_fixed: Fixed step quotient value used for target quotient
6646 + * adjustment if use_dynamic_step_quot is not set.
6647 + * This parameter is only relevant for CPR4 controllers
6648 + * when using the per-online-core or per-temperature
6649 + * adjustments.
6650 + * @initial_temp_band: Temperature band used for calculation of base-line
6651 + * target quotients (fused).
6652 + * @use_dynamic_step_quot: Boolean value which indicates that margin adjustment
6653 + * of target quotient will be based on the step quotient
6654 + * calculated dynamically in hardware for each RO.
6655 + * @allow_core_count_adj: Core count adjustments are allowed for this controller
6656 + * @allow_temp_adj: Temperature based adjustments are allowed for
6657 + * this controller
6658 + * @allow_boost: Voltage boost allowed for this controller.
6659 + * @temp_band_count: Number of temperature bands used for temperature based
6660 + * adjustment logic
6661 + * @temp_points: Array of temperature points in decidegrees Celsius used
6662 + * to specify the ranges for selected temperature bands.
6663 + * The array must have (temp_band_count - 1) elements
6664 + * allocated.
6665 + * @temp_sensor_id_start: Start ID of temperature sensors used for temperature
6666 + * based adjustments.
6667 + * @temp_sensor_id_end: End ID of temperature sensors used for temperature
6668 + * based adjustments.
6669 + * @voltage_settling_time: The time in nanoseconds that it takes for the
6670 + * VDD supply voltage to settle after being increased or
6671 + * decreased by step_volt microvolts which is used when
6672 + * SDELTA voltage margin adjustments are applied.
6673 + * @cpr_global_setting: Global setting for this CPR controller
6674 + * @panic_regs_info: Array of panic registers information which provides the
6675 + * list of registers to dump when the device crashes.
6676 + * @panic_notifier: Notifier block registered to global panic notifier list.
6677 + *
6678 + * This structure contains both configuration and runtime state data. The
6679 + * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled,
6680 + * last_corner_was_closed_loop, cpr_suspended, aging_ref_adjust_volt,
6681 + * aging_required, aging_succeeded, and aging_failed are state variables.
6682 + *
6683 + * The apm* elements do not need to be initialized if the VDD supply managed by
6684 + * the CPR3 controller does not utilize an APM.
6685 + *
6686 + * The elements step_quot_fixed, initial_temp_band, allow_core_count_adj,
6687 + * allow_temp_adj and temp* need to be initialized for CPR4 controllers which
6688 + * are using per-online-core or per-temperature adjustments.
6689 + */
6690 +struct cpr3_controller {
6691 + struct device *dev;
6692 + const char *name;
6693 + int ctrl_id;
6694 + void __iomem *cpr_ctrl_base;
6695 + void __iomem *fuse_base;
6696 + void __iomem *aging_possible_reg;
6697 + struct list_head list;
6698 + struct cpr3_thread *thread;
6699 + int thread_count;
6700 + u8 *sensor_owner;
6701 + int sensor_count;
6702 + int soc_revision;
6703 + struct mutex lock;
6704 + struct regulator *vdd_regulator;
6705 + struct regulator *system_regulator;
6706 + struct regulator *mem_acc_regulator;
6707 + struct regulator *vdd_limit_regulator;
6708 + int system_supply_max_volt;
6709 + int mem_acc_threshold_volt;
6710 + int mem_acc_corner_map[CPR3_MEM_ACC_CORNERS];
6711 + int mem_acc_crossover_volt;
6712 + struct clk *core_clk;
6713 + struct clk *iface_clk;
6714 + struct clk *bus_clk;
6715 + int irq;
6716 + struct cpumask irq_affinity_mask;
6717 + struct notifier_block cpu_hotplug_notifier;
6718 + int ceiling_irq;
6719 + struct msm_apm_ctrl_dev *apm;
6720 + int apm_threshold_volt;
6721 + int apm_crossover_volt;
6722 + int apm_adj_volt;
6723 + enum msm_apm_supply apm_high_supply;
6724 + enum msm_apm_supply apm_low_supply;
6725 + int base_volt;
6726 + u32 corner_switch_delay_time;
6727 + u32 cpr_clock_rate;
6728 + u32 sensor_time;
6729 + u32 loop_time;
6730 + u32 up_down_delay_time;
6731 + u32 idle_clocks;
6732 + u32 step_quot_init_min;
6733 + u32 step_quot_init_max;
6734 + int step_volt;
6735 + u32 down_error_step_limit;
6736 + u32 up_error_step_limit;
6737 + enum cpr3_count_mode count_mode;
6738 + u32 count_repeat;
6739 + u32 proc_clock_throttle;
6740 + bool cpr_allowed_hw;
6741 + bool cpr_allowed_sw;
6742 + bool supports_hw_closed_loop;
6743 + bool use_hw_closed_loop;
6744 + enum cpr_controller_type ctrl_type;
6745 + bool saw_use_unit_mV;
6746 + struct cpr3_corner aggr_corner;
6747 + bool cpr_enabled;
6748 + bool last_corner_was_closed_loop;
6749 + bool cpr_suspended;
6750 + struct dentry *debugfs;
6751 +
6752 + int aging_ref_volt;
6753 + unsigned int aging_vdd_mode;
6754 + unsigned int aging_complete_vdd_mode;
6755 + int aging_ref_adjust_volt;
6756 + bool aging_required;
6757 + bool aging_succeeded;
6758 + bool aging_failed;
6759 + struct cpr3_aging_sensor_info *aging_sensor;
6760 + int aging_sensor_count;
6761 + u32 cur_sensor_state;
6762 + u32 aging_possible_mask;
6763 + u32 aging_possible_val;
6764 +
6765 + u32 step_quot_fixed;
6766 + u32 initial_temp_band;
6767 + bool use_dynamic_step_quot;
6768 + bool allow_core_count_adj;
6769 + bool allow_temp_adj;
6770 + bool allow_boost;
6771 + int temp_band_count;
6772 + int *temp_points;
6773 + u32 temp_sensor_id_start;
6774 + u32 temp_sensor_id_end;
6775 + u32 voltage_settling_time;
6776 + enum cpr_setting cpr_global_setting;
6777 + struct cpr3_panic_regs_info *panic_regs_info;
6778 + struct notifier_block panic_notifier;
6779 +};
6780 +
6781 +/* Used for rounding voltages to the closest physically available set point. */
6782 +#define CPR3_ROUND(n, d) (DIV_ROUND_UP(n, d) * (d))
6783 +
6784 +#define cpr3_err(cpr3_thread, message, ...) \
6785 + pr_err("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
6786 +#define cpr3_info(cpr3_thread, message, ...) \
6787 + pr_info("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
6788 +#define cpr3_debug(cpr3_thread, message, ...) \
6789 + pr_debug("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
6790 +
6791 +/*
6792 + * Offset subtracted from voltage corner values passed in from the regulator
6793 + * framework in order to get internal voltage corner values. This is needed
6794 + * since the regulator framework treats 0 as an error value at regulator
6795 + * registration time.
6796 + */
6797 +#define CPR3_CORNER_OFFSET 1
6798 +
6799 +#ifdef CONFIG_REGULATOR_CPR3
6800 +
6801 +int cpr3_regulator_register(struct platform_device *pdev,
6802 + struct cpr3_controller *ctrl);
6803 +int cpr3_open_loop_regulator_register(struct platform_device *pdev,
6804 + struct cpr3_controller *ctrl);
6805 +int cpr3_regulator_unregister(struct cpr3_controller *ctrl);
6806 +int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl);
6807 +int cpr3_regulator_suspend(struct cpr3_controller *ctrl);
6808 +int cpr3_regulator_resume(struct cpr3_controller *ctrl);
6809 +
6810 +int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id,
6811 + u32 max_thread_id);
6812 +int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
6813 + struct platform_device *pdev);
6814 +int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
6815 + struct platform_device *pdev, u8 start, u8 end);
6816 +int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
6817 + const struct cpr3_fuse_param *param, u64 *param_value);
6818 +int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse,
6819 + int fuse_len);
6820 +u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x);
6821 +int cpr3_parse_array_property(struct cpr3_regulator *vreg,
6822 + const char *prop_name, int tuple_size, u32 *out);
6823 +int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
6824 + const char *prop_name, int tuple_size, u32 *out);
6825 +int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg,
6826 + const char *prop_name, int tuple_size, u32 *out);
6827 +int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg);
6828 +int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname,
6829 + u32 *out_value, u32 value_min, u32 value_max);
6830 +int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname,
6831 + u32 *out_value, u32 value_min, u32 value_max);
6832 +int cpr3_parse_common_thread_data(struct cpr3_thread *thread);
6833 +int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl);
6834 +int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl);
6835 +int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg);
6836 +void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg);
6837 +int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg);
6838 +void cpr3_print_quots(struct cpr3_regulator *vreg);
6839 +int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt);
6840 +int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
6841 + int *fuse_volt);
6842 +int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
6843 + int *fuse_volt);
6844 +int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg);
6845 +int cpr3_quot_adjustment(int ro_scale, int volt_adjust);
6846 +int cpr3_voltage_adjustment(int ro_scale, int quot_adjust);
6847 +int cpr3_parse_closed_loop_voltage_adjustments(struct cpr3_regulator *vreg,
6848 + u64 *ro_sel, int *volt_adjust,
6849 + int *volt_adjust_fuse, int *ro_scale);
6850 +int cpr4_parse_core_count_temp_voltage_adj(struct cpr3_regulator *vreg,
6851 + bool use_corner_band);
6852 +int cpr3_apm_init(struct cpr3_controller *ctrl);
6853 +int cpr3_mem_acc_init(struct cpr3_regulator *vreg);
6854 +void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg);
6855 +void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg);
6856 +int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
6857 + int *fuse_volt_adjust);
6858 +int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
6859 + bool is_cold);
6860 +int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp);
6861 +bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg);
6862 +
6863 +#else
6864 +
6865 +static inline int cpr3_regulator_register(struct platform_device *pdev,
6866 + struct cpr3_controller *ctrl)
6867 +{
6868 + return -ENXIO;
6869 +}
6870 +
6871 +static inline int
6872 +cpr3_open_loop_regulator_register(struct platform_device *pdev,
6873 + struct cpr3_controller *ctrl);
6874 +{
6875 + return -ENXIO;
6876 +}
6877 +
6878 +static inline int cpr3_regulator_unregister(struct cpr3_controller *ctrl)
6879 +{
6880 + return -ENXIO;
6881 +}
6882 +
6883 +static inline int
6884 +cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl)
6885 +{
6886 + return -ENXIO;
6887 +}
6888 +
6889 +static inline int cpr3_regulator_suspend(struct cpr3_controller *ctrl)
6890 +{
6891 + return -ENXIO;
6892 +}
6893 +
6894 +static inline int cpr3_regulator_resume(struct cpr3_controller *ctrl)
6895 +{
6896 + return -ENXIO;
6897 +}
6898 +
6899 +static inline int cpr3_get_thread_name(struct cpr3_thread *thread,
6900 + struct device_node *thread_node)
6901 +{
6902 + return -EPERM;
6903 +}
6904 +
6905 +static inline int cpr3_allocate_threads(struct cpr3_controller *ctrl,
6906 + u32 min_thread_id, u32 max_thread_id)
6907 +{
6908 + return -EPERM;
6909 +}
6910 +
6911 +static inline int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
6912 + struct platform_device *pdev)
6913 +{
6914 + return -ENXIO;
6915 +}
6916 +
6917 +static inline int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
6918 + struct platform_device *pdev, u8 start, u8 end)
6919 +{
6920 + return 0;
6921 +}
6922 +
6923 +static inline int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
6924 + const struct cpr3_fuse_param *param, u64 *param_value)
6925 +{
6926 + return -EPERM;
6927 +}
6928 +
6929 +static inline int cpr3_convert_open_loop_voltage_fuse(int ref_volt,
6930 + int step_volt, u32 fuse, int fuse_len)
6931 +{
6932 + return -EPERM;
6933 +}
6934 +
6935 +static inline u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x)
6936 +{
6937 + return 0;
6938 +}
6939 +
6940 +static inline int cpr3_parse_array_property(struct cpr3_regulator *vreg,
6941 + const char *prop_name, int tuple_size, u32 *out)
6942 +{
6943 + return -EPERM;
6944 +}
6945 +
6946 +static inline int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
6947 + const char *prop_name, int tuple_size, u32 *out)
6948 +{
6949 + return -EPERM;
6950 +}
6951 +
6952 +static inline int cpr3_parse_corner_band_array_property(
6953 + struct cpr3_regulator *vreg, const char *prop_name,
6954 + int tuple_size, u32 *out)
6955 +{
6956 + return -EPERM;
6957 +}
6958 +
6959 +static inline int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
6960 +{
6961 + return -EPERM;
6962 +}
6963 +
6964 +static inline int cpr3_parse_thread_u32(struct cpr3_thread *thread,
6965 + const char *propname, u32 *out_value, u32 value_min,
6966 + u32 value_max)
6967 +{
6968 + return -EPERM;
6969 +}
6970 +
6971 +static inline int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl,
6972 + const char *propname, u32 *out_value, u32 value_min,
6973 + u32 value_max)
6974 +{
6975 + return -EPERM;
6976 +}
6977 +
6978 +static inline int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
6979 +{
6980 + return -EPERM;
6981 +}
6982 +
6983 +static inline int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
6984 +{
6985 + return -EPERM;
6986 +}
6987 +
6988 +static inline int
6989 +cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl)
6990 +{
6991 + return -EPERM;
6992 +}
6993 +
6994 +static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg)
6995 +{
6996 + return -EPERM;
6997 +}
6998 +
6999 +static inline void cpr3_open_loop_voltage_as_ceiling(
7000 + struct cpr3_regulator *vreg)
7001 +{
7002 + return;
7003 +}
7004 +
7005 +static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg)
7006 +{
7007 + return -EPERM;
7008 +}
7009 +
7010 +static inline void cpr3_print_quots(struct cpr3_regulator *vreg)
7011 +{
7012 + return;
7013 +}
7014 +
7015 +static inline int
7016 +cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt)
7017 +{
7018 + return -EPERM;
7019 +}
7020 +
7021 +static inline int
7022 +cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
7023 + int *fuse_volt)
7024 +{
7025 + return -EPERM;
7026 +}
7027 +
7028 +static inline int cpr3_adjust_fused_open_loop_voltages(
7029 + struct cpr3_regulator *vreg, int *fuse_volt)
7030 +{
7031 + return -EPERM;
7032 +}
7033 +
7034 +static inline int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
7035 +{
7036 + return -EPERM;
7037 +}
7038 +
7039 +static inline int cpr3_quot_adjustment(int ro_scale, int volt_adjust)
7040 +{
7041 + return 0;
7042 +}
7043 +
7044 +static inline int cpr3_voltage_adjustment(int ro_scale, int quot_adjust)
7045 +{
7046 + return 0;
7047 +}
7048 +
7049 +static inline int cpr3_parse_closed_loop_voltage_adjustments(
7050 + struct cpr3_regulator *vreg, u64 *ro_sel,
7051 + int *volt_adjust, int *volt_adjust_fuse, int *ro_scale)
7052 +{
7053 + return 0;
7054 +}
7055 +
7056 +static inline int cpr4_parse_core_count_temp_voltage_adj(
7057 + struct cpr3_regulator *vreg, bool use_corner_band)
7058 +{
7059 + return 0;
7060 +}
7061 +
7062 +static inline int cpr3_apm_init(struct cpr3_controller *ctrl)
7063 +{
7064 + return 0;
7065 +}
7066 +
7067 +static inline int cpr3_mem_acc_init(struct cpr3_regulator *vreg)
7068 +{
7069 + return 0;
7070 +}
7071 +
7072 +static inline void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg)
7073 +{
7074 +}
7075 +
7076 +static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
7077 +{
7078 +}
7079 +
7080 +static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
7081 + int *fuse_volt_adjust)
7082 +{
7083 + return 0;
7084 +}
7085 +
7086 +static inline int
7087 +cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
7088 + bool is_cold)
7089 +{
7090 + return 0;
7091 +}
7092 +
7093 +static inline bool
7094 +cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg)
7095 +{
7096 + return false;
7097 +}
7098 +
7099 +static inline int
7100 +cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp)
7101 +{
7102 + return 0;
7103 +}
7104 +#endif /* CONFIG_REGULATOR_CPR3 */
7105 +
7106 +#endif /* __REGULATOR_CPR_REGULATOR_H__ */
7107 --- /dev/null
7108 +++ b/drivers/regulator/cpr3-util.c
7109 @@ -0,0 +1,2750 @@
7110 +/*
7111 + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
7112 + *
7113 + * This program is free software; you can redistribute it and/or modify
7114 + * it under the terms of the GNU General Public License version 2 and
7115 + * only version 2 as published by the Free Software Foundation.
7116 + *
7117 + * This program is distributed in the hope that it will be useful,
7118 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7119 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7120 + * GNU General Public License for more details.
7121 + */
7122 +
7123 +/*
7124 + * This file contains utility functions to be used by platform specific CPR3
7125 + * regulator drivers.
7126 + */
7127 +
7128 +#define pr_fmt(fmt) "%s: " fmt, __func__
7129 +
7130 +#include <linux/cpumask.h>
7131 +#include <linux/device.h>
7132 +#include <linux/io.h>
7133 +#include <linux/kernel.h>
7134 +#include <linux/of.h>
7135 +#include <linux/platform_device.h>
7136 +#include <linux/slab.h>
7137 +#include <linux/types.h>
7138 +
7139 +#include <soc/qcom/socinfo.h>
7140 +
7141 +#include "cpr3-regulator.h"
7142 +
7143 +#define BYTES_PER_FUSE_ROW 8
7144 +#define MAX_FUSE_ROW_BIT 63
7145 +
7146 +#define CPR3_CONSECUTIVE_UP_DOWN_MIN 0
7147 +#define CPR3_CONSECUTIVE_UP_DOWN_MAX 15
7148 +#define CPR3_UP_DOWN_THRESHOLD_MIN 0
7149 +#define CPR3_UP_DOWN_THRESHOLD_MAX 31
7150 +#define CPR3_STEP_QUOT_MIN 0
7151 +#define CPR3_STEP_QUOT_MAX 63
7152 +#define CPR3_IDLE_CLOCKS_MIN 0
7153 +#define CPR3_IDLE_CLOCKS_MAX 31
7154 +
7155 +/* This constant has units of uV/mV so 1000 corresponds to 100%. */
7156 +#define CPR3_AGING_DERATE_UNITY 1000
7157 +
7158 +/**
7159 + * cpr3_allocate_regulators() - allocate and initialize CPR3 regulators for a
7160 + * given thread based upon device tree data
7161 + * @thread: Pointer to the CPR3 thread
7162 + *
7163 + * This function allocates the thread->vreg array based upon the number of
7164 + * device tree regulator subnodes. It also initializes generic elements of each
7165 + * regulator struct such as name, of_node, and thread.
7166 + *
7167 + * Return: 0 on success, errno on failure
7168 + */
7169 +static int cpr3_allocate_regulators(struct cpr3_thread *thread)
7170 +{
7171 + struct device_node *node;
7172 + int i, rc;
7173 +
7174 + thread->vreg_count = 0;
7175 +
7176 + for_each_available_child_of_node(thread->of_node, node) {
7177 + thread->vreg_count++;
7178 + }
7179 +
7180 + thread->vreg = devm_kcalloc(thread->ctrl->dev, thread->vreg_count,
7181 + sizeof(*thread->vreg), GFP_KERNEL);
7182 + if (!thread->vreg)
7183 + return -ENOMEM;
7184 +
7185 + i = 0;
7186 + for_each_available_child_of_node(thread->of_node, node) {
7187 + thread->vreg[i].of_node = node;
7188 + thread->vreg[i].thread = thread;
7189 +
7190 + rc = of_property_read_string(node, "regulator-name",
7191 + &thread->vreg[i].name);
7192 + if (rc) {
7193 + dev_err(thread->ctrl->dev, "could not find regulator name, rc=%d\n",
7194 + rc);
7195 + return rc;
7196 + }
7197 +
7198 + i++;
7199 + }
7200 +
7201 + return 0;
7202 +}
7203 +
7204 +/**
7205 + * cpr3_allocate_threads() - allocate and initialize CPR3 threads for a given
7206 + * controller based upon device tree data
7207 + * @ctrl: Pointer to the CPR3 controller
7208 + * @min_thread_id: Minimum allowed hardware thread ID for this controller
7209 + * @max_thread_id: Maximum allowed hardware thread ID for this controller
7210 + *
7211 + * This function allocates the ctrl->thread array based upon the number of
7212 + * device tree thread subnodes. It also initializes generic elements of each
7213 + * thread struct such as thread_id, of_node, ctrl, and vreg array.
7214 + *
7215 + * Return: 0 on success, errno on failure
7216 + */
7217 +int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id,
7218 + u32 max_thread_id)
7219 +{
7220 + struct device *dev = ctrl->dev;
7221 + struct device_node *thread_node;
7222 + int i, j, rc;
7223 +
7224 + ctrl->thread_count = 0;
7225 +
7226 + for_each_available_child_of_node(dev->of_node, thread_node) {
7227 + ctrl->thread_count++;
7228 + }
7229 +
7230 + ctrl->thread = devm_kcalloc(dev, ctrl->thread_count,
7231 + sizeof(*ctrl->thread), GFP_KERNEL);
7232 + if (!ctrl->thread)
7233 + return -ENOMEM;
7234 +
7235 + i = 0;
7236 + for_each_available_child_of_node(dev->of_node, thread_node) {
7237 + ctrl->thread[i].of_node = thread_node;
7238 + ctrl->thread[i].ctrl = ctrl;
7239 +
7240 + rc = of_property_read_u32(thread_node, "qcom,cpr-thread-id",
7241 + &ctrl->thread[i].thread_id);
7242 + if (rc) {
7243 + dev_err(dev, "could not read DT property qcom,cpr-thread-id, rc=%d\n",
7244 + rc);
7245 + return rc;
7246 + }
7247 +
7248 + if (ctrl->thread[i].thread_id < min_thread_id ||
7249 + ctrl->thread[i].thread_id > max_thread_id) {
7250 + dev_err(dev, "invalid thread id = %u; not within [%u, %u]\n",
7251 + ctrl->thread[i].thread_id, min_thread_id,
7252 + max_thread_id);
7253 + return -EINVAL;
7254 + }
7255 +
7256 + /* Verify that the thread ID is unique for all child nodes. */
7257 + for (j = 0; j < i; j++) {
7258 + if (ctrl->thread[j].thread_id
7259 + == ctrl->thread[i].thread_id) {
7260 + dev_err(dev, "duplicate thread id = %u found\n",
7261 + ctrl->thread[i].thread_id);
7262 + return -EINVAL;
7263 + }
7264 + }
7265 +
7266 + rc = cpr3_allocate_regulators(&ctrl->thread[i]);
7267 + if (rc)
7268 + return rc;
7269 +
7270 + i++;
7271 + }
7272 +
7273 + return 0;
7274 +}
7275 +
7276 +/**
7277 + * cpr3_map_fuse_base() - ioremap the base address of the fuse region
7278 + * @ctrl: Pointer to the CPR3 controller
7279 + * @pdev: Platform device pointer for the CPR3 controller
7280 + *
7281 + * Return: 0 on success, errno on failure
7282 + */
7283 +int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
7284 + struct platform_device *pdev)
7285 +{
7286 + struct resource *res;
7287 +
7288 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse_base");
7289 + if (!res || !res->start) {
7290 + dev_err(&pdev->dev, "fuse base address is missing\n");
7291 + return -ENXIO;
7292 + }
7293 +
7294 + ctrl->fuse_base = devm_ioremap(&pdev->dev, res->start,
7295 + resource_size(res));
7296 +
7297 + return 0;
7298 +}
7299 +
7300 +/**
7301 + * cpr3_read_tcsr_setting - reads the CPR setting bits from TCSR register
7302 + * @ctrl: Pointer to the CPR3 controller
7303 + * @pdev: Platform device pointer for the CPR3 controller
7304 + * @start: start bit in TCSR register
7305 + * @end: end bit in TCSR register
7306 + *
7307 + * Return: 0 on success, errno on failure
7308 + */
7309 +int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
7310 + struct platform_device *pdev, u8 start, u8 end)
7311 +{
7312 + struct resource *res;
7313 + void __iomem *tcsr_reg;
7314 + u32 val;
7315 +
7316 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
7317 + "cpr_tcsr_reg");
7318 + if (!res || !res->start)
7319 + return 0;
7320 +
7321 + tcsr_reg = ioremap(res->start, resource_size(res));
7322 + if (!tcsr_reg) {
7323 + dev_err(&pdev->dev, "tcsr ioremap failed\n");
7324 + return 0;
7325 + }
7326 +
7327 + val = readl_relaxed(tcsr_reg);
7328 + val &= GENMASK(end, start);
7329 + val >>= start;
7330 +
7331 + switch (val) {
7332 + case 1:
7333 + ctrl->cpr_global_setting = CPR_DISABLED;
7334 + break;
7335 + case 2:
7336 + ctrl->cpr_global_setting = CPR_OPEN_LOOP_EN;
7337 + break;
7338 + case 3:
7339 + ctrl->cpr_global_setting = CPR_CLOSED_LOOP_EN;
7340 + break;
7341 + default:
7342 + ctrl->cpr_global_setting = CPR_DEFAULT;
7343 + }
7344 +
7345 + iounmap(tcsr_reg);
7346 +
7347 + return 0;
7348 +}
7349 +
7350 +/**
7351 + * cpr3_read_fuse_param() - reads a CPR3 fuse parameter out of eFuses
7352 + * @fuse_base_addr: Virtual memory address of the eFuse base address
7353 + * @param: Null terminated array of fuse param segments to read
7354 + * from
7355 + * @param_value: Output with value read from the eFuses
7356 + *
7357 + * This function reads from each of the parameter segments listed in the param
7358 + * array and concatenates their values together. Reading stops when an element
7359 + * is reached which has all 0 struct values. The total number of bits specified
7360 + * for the fuse parameter across all segments must be less than or equal to 64.
7361 + *
7362 + * Return: 0 on success, errno on failure
7363 + */
7364 +int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
7365 + const struct cpr3_fuse_param *param, u64 *param_value)
7366 +{
7367 + u64 fuse_val, val;
7368 + int bits;
7369 + int bits_total = 0;
7370 +
7371 + *param_value = 0;
7372 +
7373 + while (param->row || param->bit_start || param->bit_end) {
7374 + if (param->bit_start > param->bit_end
7375 + || param->bit_end > MAX_FUSE_ROW_BIT) {
7376 + pr_err("Invalid fuse parameter segment: row=%u, start=%u, end=%u\n",
7377 + param->row, param->bit_start, param->bit_end);
7378 + return -EINVAL;
7379 + }
7380 +
7381 + bits = param->bit_end - param->bit_start + 1;
7382 + if (bits_total + bits > 64) {
7383 + pr_err("Invalid fuse parameter segments; total bits = %d\n",
7384 + bits_total + bits);
7385 + return -EINVAL;
7386 + }
7387 +
7388 + fuse_val = readq_relaxed(fuse_base_addr
7389 + + param->row * BYTES_PER_FUSE_ROW);
7390 + val = (fuse_val >> param->bit_start) & ((1ULL << bits) - 1);
7391 + *param_value |= val << bits_total;
7392 + bits_total += bits;
7393 +
7394 + param++;
7395 + }
7396 +
7397 + return 0;
7398 +}
7399 +
7400 +/**
7401 + * cpr3_convert_open_loop_voltage_fuse() - converts an open loop voltage fuse
7402 + * value into an absolute voltage with units of microvolts
7403 + * @ref_volt: Reference voltage in microvolts
7404 + * @step_volt: The step size in microvolts of the fuse LSB
7405 + * @fuse: Open loop voltage fuse value
7406 + * @fuse_len: The bit length of the fuse value
7407 + *
7408 + * The MSB of the fuse parameter corresponds to a sign bit. If it is set, then
7409 + * the lower bits correspond to the number of steps to go down from the
7410 + * reference voltage. If it is not set, then the lower bits correspond to the
7411 + * number of steps to go up from the reference voltage.
7412 + */
7413 +int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse,
7414 + int fuse_len)
7415 +{
7416 + int sign, steps;
7417 +
7418 + sign = (fuse & (1 << (fuse_len - 1))) ? -1 : 1;
7419 + steps = fuse & ((1 << (fuse_len - 1)) - 1);
7420 +
7421 + return ref_volt + sign * steps * step_volt;
7422 +}
7423 +
7424 +/**
7425 + * cpr3_interpolate() - performs linear interpolation
7426 + * @x1 Lower known x value
7427 + * @y1 Lower known y value
7428 + * @x2 Upper known x value
7429 + * @y2 Upper known y value
7430 + * @x Intermediate x value
7431 + *
7432 + * Returns y where (x, y) falls on the line between (x1, y1) and (x2, y2).
7433 + * It is required that x1 < x2, y1 <= y2, and x1 <= x <= x2. If these
7434 + * conditions are not met, then y2 will be returned.
7435 + */
7436 +u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x)
7437 +{
7438 + u64 temp;
7439 +
7440 + if (x1 >= x2 || y1 > y2 || x1 > x || x > x2)
7441 + return y2;
7442 +
7443 + temp = (x2 - x) * (y2 - y1);
7444 + do_div(temp, (u32)(x2 - x1));
7445 +
7446 + return y2 - temp;
7447 +}
7448 +
7449 +/**
7450 + * cpr3_parse_array_property() - fill an array from a portion of the values
7451 + * specified for a device tree property
7452 + * @vreg: Pointer to the CPR3 regulator
7453 + * @prop_name: The name of the device tree property to read from
7454 + * @tuple_size: The number of elements in each tuple
7455 + * @out: Output data array which must be of size tuple_size
7456 + *
7457 + * cpr3_parse_common_corner_data() must be called for vreg before this function
7458 + * is called so that fuse combo and speed bin size elements are initialized.
7459 + *
7460 + * Three formats are supported for the device tree property:
7461 + * 1. Length == tuple_size
7462 + * (reading begins at index 0)
7463 + * 2. Length == tuple_size * vreg->fuse_combos_supported
7464 + * (reading begins at index tuple_size * vreg->fuse_combo)
7465 + * 3. Length == tuple_size * vreg->speed_bins_supported
7466 + * (reading begins at index tuple_size * vreg->speed_bin_fuse)
7467 + *
7468 + * All other property lengths are treated as errors.
7469 + *
7470 + * Return: 0 on success, errno on failure
7471 + */
7472 +int cpr3_parse_array_property(struct cpr3_regulator *vreg,
7473 + const char *prop_name, int tuple_size, u32 *out)
7474 +{
7475 + struct device_node *node = vreg->of_node;
7476 + int len = 0;
7477 + int i, offset, rc;
7478 +
7479 + if (!of_find_property(node, prop_name, &len)) {
7480 + cpr3_err(vreg, "property %s is missing\n", prop_name);
7481 + return -EINVAL;
7482 + }
7483 +
7484 + if (len == tuple_size * sizeof(u32)) {
7485 + offset = 0;
7486 + } else if (len == tuple_size * vreg->fuse_combos_supported
7487 + * sizeof(u32)) {
7488 + offset = tuple_size * vreg->fuse_combo;
7489 + } else if (vreg->speed_bins_supported > 0 &&
7490 + len == tuple_size * vreg->speed_bins_supported * sizeof(u32)) {
7491 + offset = tuple_size * vreg->speed_bin_fuse;
7492 + } else {
7493 + if (vreg->speed_bins_supported > 0)
7494 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
7495 + prop_name, len,
7496 + tuple_size * sizeof(u32),
7497 + tuple_size * vreg->speed_bins_supported
7498 + * sizeof(u32),
7499 + tuple_size * vreg->fuse_combos_supported
7500 + * sizeof(u32));
7501 + else
7502 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
7503 + prop_name, len,
7504 + tuple_size * sizeof(u32),
7505 + tuple_size * vreg->fuse_combos_supported
7506 + * sizeof(u32));
7507 + return -EINVAL;
7508 + }
7509 +
7510 + for (i = 0; i < tuple_size; i++) {
7511 + rc = of_property_read_u32_index(node, prop_name, offset + i,
7512 + &out[i]);
7513 + if (rc) {
7514 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
7515 + prop_name, rc);
7516 + return rc;
7517 + }
7518 + }
7519 +
7520 + return 0;
7521 +}
7522 +
7523 +/**
7524 + * cpr3_parse_corner_array_property() - fill a per-corner array from a portion
7525 + * of the values specified for a device tree property
7526 + * @vreg: Pointer to the CPR3 regulator
7527 + * @prop_name: The name of the device tree property to read from
7528 + * @tuple_size: The number of elements in each per-corner tuple
7529 + * @out: Output data array which must be of size:
7530 + * tuple_size * vreg->corner_count
7531 + *
7532 + * cpr3_parse_common_corner_data() must be called for vreg before this function
7533 + * is called so that fuse combo and speed bin size elements are initialized.
7534 + *
7535 + * Three formats are supported for the device tree property:
7536 + * 1. Length == tuple_size * vreg->corner_count
7537 + * (reading begins at index 0)
7538 + * 2. Length == tuple_size * vreg->fuse_combo_corner_sum
7539 + * (reading begins at index tuple_size * vreg->fuse_combo_offset)
7540 + * 3. Length == tuple_size * vreg->speed_bin_corner_sum
7541 + * (reading begins at index tuple_size * vreg->speed_bin_offset)
7542 + *
7543 + * All other property lengths are treated as errors.
7544 + *
7545 + * Return: 0 on success, errno on failure
7546 + */
7547 +int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
7548 + const char *prop_name, int tuple_size, u32 *out)
7549 +{
7550 + struct device_node *node = vreg->of_node;
7551 + int len = 0;
7552 + int i, offset, rc;
7553 +
7554 + if (!of_find_property(node, prop_name, &len)) {
7555 + cpr3_err(vreg, "property %s is missing\n", prop_name);
7556 + return -EINVAL;
7557 + }
7558 +
7559 + if (len == tuple_size * vreg->corner_count * sizeof(u32)) {
7560 + offset = 0;
7561 + } else if (len == tuple_size * vreg->fuse_combo_corner_sum
7562 + * sizeof(u32)) {
7563 + offset = tuple_size * vreg->fuse_combo_offset;
7564 + } else if (vreg->speed_bin_corner_sum > 0 &&
7565 + len == tuple_size * vreg->speed_bin_corner_sum * sizeof(u32)) {
7566 + offset = tuple_size * vreg->speed_bin_offset;
7567 + } else {
7568 + if (vreg->speed_bin_corner_sum > 0)
7569 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
7570 + prop_name, len,
7571 + tuple_size * vreg->corner_count * sizeof(u32),
7572 + tuple_size * vreg->speed_bin_corner_sum
7573 + * sizeof(u32),
7574 + tuple_size * vreg->fuse_combo_corner_sum
7575 + * sizeof(u32));
7576 + else
7577 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
7578 + prop_name, len,
7579 + tuple_size * vreg->corner_count * sizeof(u32),
7580 + tuple_size * vreg->fuse_combo_corner_sum
7581 + * sizeof(u32));
7582 + return -EINVAL;
7583 + }
7584 +
7585 + for (i = 0; i < tuple_size * vreg->corner_count; i++) {
7586 + rc = of_property_read_u32_index(node, prop_name, offset + i,
7587 + &out[i]);
7588 + if (rc) {
7589 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
7590 + prop_name, rc);
7591 + return rc;
7592 + }
7593 + }
7594 +
7595 + return 0;
7596 +}
7597 +
7598 +/**
7599 + * cpr3_parse_corner_band_array_property() - fill a per-corner band array
7600 + * from a portion of the values specified for a device tree
7601 + * property
7602 + * @vreg: Pointer to the CPR3 regulator
7603 + * @prop_name: The name of the device tree property to read from
7604 + * @tuple_size: The number of elements in each per-corner band tuple
7605 + * @out: Output data array which must be of size:
7606 + * tuple_size * vreg->corner_band_count
7607 + *
7608 + * cpr3_parse_common_corner_data() must be called for vreg before this function
7609 + * is called so that fuse combo and speed bin size elements are initialized.
7610 + * In addition, corner band fuse combo and speed bin sum and offset elements
7611 + * must be initialized prior to executing this function.
7612 + *
7613 + * Three formats are supported for the device tree property:
7614 + * 1. Length == tuple_size * vreg->corner_band_count
7615 + * (reading begins at index 0)
7616 + * 2. Length == tuple_size * vreg->fuse_combo_corner_band_sum
7617 + * (reading begins at index tuple_size *
7618 + * vreg->fuse_combo_corner_band_offset)
7619 + * 3. Length == tuple_size * vreg->speed_bin_corner_band_sum
7620 + * (reading begins at index tuple_size *
7621 + * vreg->speed_bin_corner_band_offset)
7622 + *
7623 + * All other property lengths are treated as errors.
7624 + *
7625 + * Return: 0 on success, errno on failure
7626 + */
7627 +int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg,
7628 + const char *prop_name, int tuple_size, u32 *out)
7629 +{
7630 + struct device_node *node = vreg->of_node;
7631 + int len = 0;
7632 + int i, offset, rc;
7633 +
7634 + if (!of_find_property(node, prop_name, &len)) {
7635 + cpr3_err(vreg, "property %s is missing\n", prop_name);
7636 + return -EINVAL;
7637 + }
7638 +
7639 + if (len == tuple_size * vreg->corner_band_count * sizeof(u32)) {
7640 + offset = 0;
7641 + } else if (len == tuple_size * vreg->fuse_combo_corner_band_sum
7642 + * sizeof(u32)) {
7643 + offset = tuple_size * vreg->fuse_combo_corner_band_offset;
7644 + } else if (vreg->speed_bin_corner_band_sum > 0 &&
7645 + len == tuple_size * vreg->speed_bin_corner_band_sum *
7646 + sizeof(u32)) {
7647 + offset = tuple_size * vreg->speed_bin_corner_band_offset;
7648 + } else {
7649 + if (vreg->speed_bin_corner_band_sum > 0)
7650 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
7651 + prop_name, len,
7652 + tuple_size * vreg->corner_band_count *
7653 + sizeof(u32),
7654 + tuple_size * vreg->speed_bin_corner_band_sum
7655 + * sizeof(u32),
7656 + tuple_size * vreg->fuse_combo_corner_band_sum
7657 + * sizeof(u32));
7658 + else
7659 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
7660 + prop_name, len,
7661 + tuple_size * vreg->corner_band_count *
7662 + sizeof(u32),
7663 + tuple_size * vreg->fuse_combo_corner_band_sum
7664 + * sizeof(u32));
7665 + return -EINVAL;
7666 + }
7667 +
7668 + for (i = 0; i < tuple_size * vreg->corner_band_count; i++) {
7669 + rc = of_property_read_u32_index(node, prop_name, offset + i,
7670 + &out[i]);
7671 + if (rc) {
7672 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
7673 + prop_name, rc);
7674 + return rc;
7675 + }
7676 + }
7677 +
7678 + return 0;
7679 +}
7680 +
7681 +/**
7682 + * cpr3_parse_common_corner_data() - parse common CPR3 properties relating to
7683 + * the corners supported by a CPR3 regulator from device tree
7684 + * @vreg: Pointer to the CPR3 regulator
7685 + *
7686 + * This function reads, validates, and utilizes the following device tree
7687 + * properties: qcom,cpr-fuse-corners, qcom,cpr-fuse-combos, qcom,cpr-speed-bins,
7688 + * qcom,cpr-speed-bin-corners, qcom,cpr-corners, qcom,cpr-voltage-ceiling,
7689 + * qcom,cpr-voltage-floor, qcom,corner-frequencies,
7690 + * and qcom,cpr-corner-fmax-map.
7691 + *
7692 + * It initializes these CPR3 regulator elements: corner, corner_count,
7693 + * fuse_combos_supported, fuse_corner_map, and speed_bins_supported. It
7694 + * initializes these elements for each corner: ceiling_volt, floor_volt,
7695 + * proc_freq, and cpr_fuse_corner.
7696 + *
7697 + * It requires that the following CPR3 regulator elements be initialized before
7698 + * being called: fuse_corner_count, fuse_combo, and speed_bin_fuse.
7699 + *
7700 + * Return: 0 on success, errno on failure
7701 + */
7702 +int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
7703 +{
7704 + struct device_node *node = vreg->of_node;
7705 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
7706 + u32 max_fuse_combos, fuse_corners, aging_allowed = 0;
7707 + u32 max_speed_bins = 0;
7708 + u32 *combo_corners;
7709 + u32 *speed_bin_corners;
7710 + u32 *temp;
7711 + int i, j, rc;
7712 +
7713 + rc = of_property_read_u32(node, "qcom,cpr-fuse-corners", &fuse_corners);
7714 + if (rc) {
7715 + cpr3_err(vreg, "error reading property qcom,cpr-fuse-corners, rc=%d\n",
7716 + rc);
7717 + return rc;
7718 + }
7719 +
7720 + if (vreg->fuse_corner_count != fuse_corners) {
7721 + cpr3_err(vreg, "device tree config supports %d fuse corners but the hardware has %d fuse corners\n",
7722 + fuse_corners, vreg->fuse_corner_count);
7723 + return -EINVAL;
7724 + }
7725 +
7726 + rc = of_property_read_u32(node, "qcom,cpr-fuse-combos",
7727 + &max_fuse_combos);
7728 + if (rc) {
7729 + cpr3_err(vreg, "error reading property qcom,cpr-fuse-combos, rc=%d\n",
7730 + rc);
7731 + return rc;
7732 + }
7733 +
7734 + /*
7735 + * Sanity check against arbitrarily large value to avoid excessive
7736 + * memory allocation.
7737 + */
7738 + if (max_fuse_combos > 100 || max_fuse_combos == 0) {
7739 + cpr3_err(vreg, "qcom,cpr-fuse-combos is invalid: %u\n",
7740 + max_fuse_combos);
7741 + return -EINVAL;
7742 + }
7743 +
7744 + if (vreg->fuse_combo >= max_fuse_combos) {
7745 + cpr3_err(vreg, "device tree config supports fuse combos 0-%u but the hardware has combo %d\n",
7746 + max_fuse_combos - 1, vreg->fuse_combo);
7747 + BUG_ON(1);
7748 + return -EINVAL;
7749 + }
7750 +
7751 + vreg->fuse_combos_supported = max_fuse_combos;
7752 +
7753 + of_property_read_u32(node, "qcom,cpr-speed-bins", &max_speed_bins);
7754 +
7755 + /*
7756 + * Sanity check against arbitrarily large value to avoid excessive
7757 + * memory allocation.
7758 + */
7759 + if (max_speed_bins > 100) {
7760 + cpr3_err(vreg, "qcom,cpr-speed-bins is invalid: %u\n",
7761 + max_speed_bins);
7762 + return -EINVAL;
7763 + }
7764 +
7765 + if (max_speed_bins && vreg->speed_bin_fuse >= max_speed_bins) {
7766 + cpr3_err(vreg, "device tree config supports speed bins 0-%u but the hardware has speed bin %d\n",
7767 + max_speed_bins - 1, vreg->speed_bin_fuse);
7768 + BUG();
7769 + return -EINVAL;
7770 + }
7771 +
7772 + vreg->speed_bins_supported = max_speed_bins;
7773 +
7774 + combo_corners = kcalloc(vreg->fuse_combos_supported,
7775 + sizeof(*combo_corners), GFP_KERNEL);
7776 + if (!combo_corners)
7777 + return -ENOMEM;
7778 +
7779 + rc = of_property_read_u32_array(node, "qcom,cpr-corners", combo_corners,
7780 + vreg->fuse_combos_supported);
7781 + if (rc == -EOVERFLOW) {
7782 + /* Single value case */
7783 + rc = of_property_read_u32(node, "qcom,cpr-corners",
7784 + combo_corners);
7785 + for (i = 1; i < vreg->fuse_combos_supported; i++)
7786 + combo_corners[i] = combo_corners[0];
7787 + }
7788 + if (rc) {
7789 + cpr3_err(vreg, "error reading property qcom,cpr-corners, rc=%d\n",
7790 + rc);
7791 + kfree(combo_corners);
7792 + return rc;
7793 + }
7794 +
7795 + vreg->fuse_combo_offset = 0;
7796 + vreg->fuse_combo_corner_sum = 0;
7797 + for (i = 0; i < vreg->fuse_combos_supported; i++) {
7798 + vreg->fuse_combo_corner_sum += combo_corners[i];
7799 + if (i < vreg->fuse_combo)
7800 + vreg->fuse_combo_offset += combo_corners[i];
7801 + }
7802 +
7803 + vreg->corner_count = combo_corners[vreg->fuse_combo];
7804 +
7805 + kfree(combo_corners);
7806 +
7807 + vreg->speed_bin_offset = 0;
7808 + vreg->speed_bin_corner_sum = 0;
7809 + if (vreg->speed_bins_supported > 0) {
7810 + speed_bin_corners = kcalloc(vreg->speed_bins_supported,
7811 + sizeof(*speed_bin_corners), GFP_KERNEL);
7812 + if (!speed_bin_corners)
7813 + return -ENOMEM;
7814 +
7815 + rc = of_property_read_u32_array(node,
7816 + "qcom,cpr-speed-bin-corners", speed_bin_corners,
7817 + vreg->speed_bins_supported);
7818 + if (rc) {
7819 + cpr3_err(vreg, "error reading property qcom,cpr-speed-bin-corners, rc=%d\n",
7820 + rc);
7821 + kfree(speed_bin_corners);
7822 + return rc;
7823 + }
7824 +
7825 + for (i = 0; i < vreg->speed_bins_supported; i++) {
7826 + vreg->speed_bin_corner_sum += speed_bin_corners[i];
7827 + if (i < vreg->speed_bin_fuse)
7828 + vreg->speed_bin_offset += speed_bin_corners[i];
7829 + }
7830 +
7831 + if (speed_bin_corners[vreg->speed_bin_fuse]
7832 + != vreg->corner_count) {
7833 + cpr3_err(vreg, "qcom,cpr-corners and qcom,cpr-speed-bin-corners conflict on number of corners: %d vs %u\n",
7834 + vreg->corner_count,
7835 + speed_bin_corners[vreg->speed_bin_fuse]);
7836 + kfree(speed_bin_corners);
7837 + return -EINVAL;
7838 + }
7839 +
7840 + kfree(speed_bin_corners);
7841 + }
7842 +
7843 + vreg->corner = devm_kcalloc(ctrl->dev, vreg->corner_count,
7844 + sizeof(*vreg->corner), GFP_KERNEL);
7845 + temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
7846 + if (!vreg->corner || !temp)
7847 + return -ENOMEM;
7848 +
7849 + rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-ceiling",
7850 + 1, temp);
7851 + if (rc)
7852 + goto free_temp;
7853 + for (i = 0; i < vreg->corner_count; i++) {
7854 + vreg->corner[i].ceiling_volt
7855 + = CPR3_ROUND(temp[i], ctrl->step_volt);
7856 + vreg->corner[i].abs_ceiling_volt = vreg->corner[i].ceiling_volt;
7857 + }
7858 +
7859 + rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-floor",
7860 + 1, temp);
7861 + if (rc)
7862 + goto free_temp;
7863 + for (i = 0; i < vreg->corner_count; i++)
7864 + vreg->corner[i].floor_volt
7865 + = CPR3_ROUND(temp[i], ctrl->step_volt);
7866 +
7867 + /* Validate ceiling and floor values */
7868 + for (i = 0; i < vreg->corner_count; i++) {
7869 + if (vreg->corner[i].floor_volt
7870 + > vreg->corner[i].ceiling_volt) {
7871 + cpr3_err(vreg, "CPR floor[%d]=%d > ceiling[%d]=%d uV\n",
7872 + i, vreg->corner[i].floor_volt,
7873 + i, vreg->corner[i].ceiling_volt);
7874 + rc = -EINVAL;
7875 + goto free_temp;
7876 + }
7877 + }
7878 +
7879 + /* Load optional system-supply voltages */
7880 + if (of_find_property(vreg->of_node, "qcom,system-voltage", NULL)) {
7881 + rc = cpr3_parse_corner_array_property(vreg,
7882 + "qcom,system-voltage", 1, temp);
7883 + if (rc)
7884 + goto free_temp;
7885 + for (i = 0; i < vreg->corner_count; i++)
7886 + vreg->corner[i].system_volt = temp[i];
7887 + }
7888 +
7889 + rc = cpr3_parse_corner_array_property(vreg, "qcom,corner-frequencies",
7890 + 1, temp);
7891 + if (rc)
7892 + goto free_temp;
7893 + for (i = 0; i < vreg->corner_count; i++)
7894 + vreg->corner[i].proc_freq = temp[i];
7895 +
7896 + /* Validate frequencies */
7897 + for (i = 1; i < vreg->corner_count; i++) {
7898 + if (vreg->corner[i].proc_freq
7899 + < vreg->corner[i - 1].proc_freq) {
7900 + cpr3_err(vreg, "invalid frequency: freq[%d]=%u < freq[%d]=%u\n",
7901 + i, vreg->corner[i].proc_freq, i - 1,
7902 + vreg->corner[i - 1].proc_freq);
7903 + rc = -EINVAL;
7904 + goto free_temp;
7905 + }
7906 + }
7907 +
7908 + vreg->fuse_corner_map = devm_kcalloc(ctrl->dev, vreg->fuse_corner_count,
7909 + sizeof(*vreg->fuse_corner_map), GFP_KERNEL);
7910 + if (!vreg->fuse_corner_map) {
7911 + rc = -ENOMEM;
7912 + goto free_temp;
7913 + }
7914 +
7915 + rc = cpr3_parse_array_property(vreg, "qcom,cpr-corner-fmax-map",
7916 + vreg->fuse_corner_count, temp);
7917 + if (rc)
7918 + goto free_temp;
7919 + for (i = 0; i < vreg->fuse_corner_count; i++) {
7920 + vreg->fuse_corner_map[i] = temp[i] - CPR3_CORNER_OFFSET;
7921 + if (temp[i] < CPR3_CORNER_OFFSET
7922 + || temp[i] > vreg->corner_count + CPR3_CORNER_OFFSET) {
7923 + cpr3_err(vreg, "invalid corner value specified in qcom,cpr-corner-fmax-map: %u\n",
7924 + temp[i]);
7925 + rc = -EINVAL;
7926 + goto free_temp;
7927 + } else if (i > 0 && temp[i - 1] >= temp[i]) {
7928 + cpr3_err(vreg, "invalid corner %u less than or equal to previous corner %u\n",
7929 + temp[i], temp[i - 1]);
7930 + rc = -EINVAL;
7931 + goto free_temp;
7932 + }
7933 + }
7934 + if (temp[vreg->fuse_corner_count - 1] != vreg->corner_count)
7935 + cpr3_debug(vreg, "Note: highest Fmax corner %u in qcom,cpr-corner-fmax-map does not match highest supported corner %d\n",
7936 + temp[vreg->fuse_corner_count - 1],
7937 + vreg->corner_count);
7938 +
7939 + for (i = 0; i < vreg->corner_count; i++) {
7940 + for (j = 0; j < vreg->fuse_corner_count; j++) {
7941 + if (i + CPR3_CORNER_OFFSET <= temp[j]) {
7942 + vreg->corner[i].cpr_fuse_corner = j;
7943 + break;
7944 + }
7945 + }
7946 + if (j == vreg->fuse_corner_count) {
7947 + /*
7948 + * Handle the case where the highest fuse corner maps
7949 + * to a corner below the highest corner.
7950 + */
7951 + vreg->corner[i].cpr_fuse_corner
7952 + = vreg->fuse_corner_count - 1;
7953 + }
7954 + }
7955 +
7956 + if (of_find_property(vreg->of_node,
7957 + "qcom,allow-aging-voltage-adjustment", NULL)) {
7958 + rc = cpr3_parse_array_property(vreg,
7959 + "qcom,allow-aging-voltage-adjustment",
7960 + 1, &aging_allowed);
7961 + if (rc)
7962 + goto free_temp;
7963 +
7964 + vreg->aging_allowed = aging_allowed;
7965 + }
7966 +
7967 + if (of_find_property(vreg->of_node,
7968 + "qcom,allow-aging-open-loop-voltage-adjustment", NULL)) {
7969 + rc = cpr3_parse_array_property(vreg,
7970 + "qcom,allow-aging-open-loop-voltage-adjustment",
7971 + 1, &aging_allowed);
7972 + if (rc)
7973 + goto free_temp;
7974 +
7975 + vreg->aging_allow_open_loop_adj = aging_allowed;
7976 + }
7977 +
7978 + if (vreg->aging_allowed) {
7979 + if (ctrl->aging_ref_volt <= 0) {
7980 + cpr3_err(ctrl, "qcom,cpr-aging-ref-voltage must be specified\n");
7981 + rc = -EINVAL;
7982 + goto free_temp;
7983 + }
7984 +
7985 + rc = cpr3_parse_array_property(vreg,
7986 + "qcom,cpr-aging-max-voltage-adjustment",
7987 + 1, &vreg->aging_max_adjust_volt);
7988 + if (rc)
7989 + goto free_temp;
7990 +
7991 + rc = cpr3_parse_array_property(vreg,
7992 + "qcom,cpr-aging-ref-corner", 1, &vreg->aging_corner);
7993 + if (rc) {
7994 + goto free_temp;
7995 + } else if (vreg->aging_corner < CPR3_CORNER_OFFSET
7996 + || vreg->aging_corner > vreg->corner_count - 1
7997 + + CPR3_CORNER_OFFSET) {
7998 + cpr3_err(vreg, "aging reference corner=%d not in range [%d, %d]\n",
7999 + vreg->aging_corner, CPR3_CORNER_OFFSET,
8000 + vreg->corner_count - 1 + CPR3_CORNER_OFFSET);
8001 + rc = -EINVAL;
8002 + goto free_temp;
8003 + }
8004 + vreg->aging_corner -= CPR3_CORNER_OFFSET;
8005 +
8006 + if (of_find_property(vreg->of_node, "qcom,cpr-aging-derate",
8007 + NULL)) {
8008 + rc = cpr3_parse_corner_array_property(vreg,
8009 + "qcom,cpr-aging-derate", 1, temp);
8010 + if (rc)
8011 + goto free_temp;
8012 +
8013 + for (i = 0; i < vreg->corner_count; i++)
8014 + vreg->corner[i].aging_derate = temp[i];
8015 + } else {
8016 + for (i = 0; i < vreg->corner_count; i++)
8017 + vreg->corner[i].aging_derate
8018 + = CPR3_AGING_DERATE_UNITY;
8019 + }
8020 + }
8021 +
8022 +free_temp:
8023 + kfree(temp);
8024 + return rc;
8025 +}
8026 +
8027 +/**
8028 + * cpr3_parse_thread_u32() - parse the specified property from the CPR3 thread's
8029 + * device tree node and verify that it is within the allowed limits
8030 + * @thread: Pointer to the CPR3 thread
8031 + * @propname: The name of the device tree property to read
8032 + * @out_value: The output pointer to fill with the value read
8033 + * @value_min: The minimum allowed property value
8034 + * @value_max: The maximum allowed property value
8035 + *
8036 + * This function prints a verbose error message if the property is missing or
8037 + * has a value which is not within the specified range.
8038 + *
8039 + * Return: 0 on success, errno on failure
8040 + */
8041 +int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname,
8042 + u32 *out_value, u32 value_min, u32 value_max)
8043 +{
8044 + int rc;
8045 +
8046 + rc = of_property_read_u32(thread->of_node, propname, out_value);
8047 + if (rc) {
8048 + cpr3_err(thread->ctrl, "thread %u error reading property %s, rc=%d\n",
8049 + thread->thread_id, propname, rc);
8050 + return rc;
8051 + }
8052 +
8053 + if (*out_value < value_min || *out_value > value_max) {
8054 + cpr3_err(thread->ctrl, "thread %u %s=%u is invalid; allowed range: [%u, %u]\n",
8055 + thread->thread_id, propname, *out_value, value_min,
8056 + value_max);
8057 + return -EINVAL;
8058 + }
8059 +
8060 + return 0;
8061 +}
8062 +
8063 +/**
8064 + * cpr3_parse_ctrl_u32() - parse the specified property from the CPR3
8065 + * controller's device tree node and verify that it is within the
8066 + * allowed limits
8067 + * @ctrl: Pointer to the CPR3 controller
8068 + * @propname: The name of the device tree property to read
8069 + * @out_value: The output pointer to fill with the value read
8070 + * @value_min: The minimum allowed property value
8071 + * @value_max: The maximum allowed property value
8072 + *
8073 + * This function prints a verbose error message if the property is missing or
8074 + * has a value which is not within the specified range.
8075 + *
8076 + * Return: 0 on success, errno on failure
8077 + */
8078 +int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname,
8079 + u32 *out_value, u32 value_min, u32 value_max)
8080 +{
8081 + int rc;
8082 +
8083 + rc = of_property_read_u32(ctrl->dev->of_node, propname, out_value);
8084 + if (rc) {
8085 + cpr3_err(ctrl, "error reading property %s, rc=%d\n",
8086 + propname, rc);
8087 + return rc;
8088 + }
8089 +
8090 + if (*out_value < value_min || *out_value > value_max) {
8091 + cpr3_err(ctrl, "%s=%u is invalid; allowed range: [%u, %u]\n",
8092 + propname, *out_value, value_min, value_max);
8093 + return -EINVAL;
8094 + }
8095 +
8096 + return 0;
8097 +}
8098 +
8099 +/**
8100 + * cpr3_parse_common_thread_data() - parse common CPR3 thread properties from
8101 + * device tree
8102 + * @thread: Pointer to the CPR3 thread
8103 + *
8104 + * Return: 0 on success, errno on failure
8105 + */
8106 +int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
8107 +{
8108 + int rc;
8109 +
8110 + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-up",
8111 + &thread->consecutive_up, CPR3_CONSECUTIVE_UP_DOWN_MIN,
8112 + CPR3_CONSECUTIVE_UP_DOWN_MAX);
8113 + if (rc)
8114 + return rc;
8115 +
8116 + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-down",
8117 + &thread->consecutive_down, CPR3_CONSECUTIVE_UP_DOWN_MIN,
8118 + CPR3_CONSECUTIVE_UP_DOWN_MAX);
8119 + if (rc)
8120 + return rc;
8121 +
8122 + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-up-threshold",
8123 + &thread->up_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
8124 + CPR3_UP_DOWN_THRESHOLD_MAX);
8125 + if (rc)
8126 + return rc;
8127 +
8128 + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-down-threshold",
8129 + &thread->down_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
8130 + CPR3_UP_DOWN_THRESHOLD_MAX);
8131 + if (rc)
8132 + return rc;
8133 +
8134 + return rc;
8135 +}
8136 +
8137 +/**
8138 + * cpr3_parse_irq_affinity() - parse CPR IRQ affinity information
8139 + * @ctrl: Pointer to the CPR3 controller
8140 + *
8141 + * Return: 0 on success, errno on failure
8142 + */
8143 +static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl)
8144 +{
8145 + struct device_node *cpu_node;
8146 + int i, cpu;
8147 + int len = 0;
8148 +
8149 + if (!of_find_property(ctrl->dev->of_node, "qcom,cpr-interrupt-affinity",
8150 + &len)) {
8151 + /* No IRQ affinity required */
8152 + return 0;
8153 + }
8154 +
8155 + len /= sizeof(u32);
8156 +
8157 + for (i = 0; i < len; i++) {
8158 + cpu_node = of_parse_phandle(ctrl->dev->of_node,
8159 + "qcom,cpr-interrupt-affinity", i);
8160 + if (!cpu_node) {
8161 + cpr3_err(ctrl, "could not find CPU node %d\n", i);
8162 + return -EINVAL;
8163 + }
8164 +
8165 + for_each_possible_cpu(cpu) {
8166 + if (of_get_cpu_node(cpu, NULL) == cpu_node) {
8167 + cpumask_set_cpu(cpu, &ctrl->irq_affinity_mask);
8168 + break;
8169 + }
8170 + }
8171 + of_node_put(cpu_node);
8172 + }
8173 +
8174 + return 0;
8175 +}
8176 +
8177 +static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl)
8178 +{
8179 + struct device_node *node = ctrl->dev->of_node;
8180 + struct cpr3_panic_regs_info *panic_regs_info;
8181 + struct cpr3_reg_info *regs;
8182 + int i, reg_count, len, rc = 0;
8183 +
8184 + if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) {
8185 + /* panic register address list not specified */
8186 + return rc;
8187 + }
8188 +
8189 + reg_count = len / sizeof(u32);
8190 + if (!reg_count) {
8191 + cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n",
8192 + len);
8193 + return -EINVAL;
8194 + }
8195 +
8196 + if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) {
8197 + cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n");
8198 + return -EINVAL;
8199 + }
8200 +
8201 + len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list");
8202 + if (reg_count != len) {
8203 + cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n",
8204 + reg_count);
8205 + return -EINVAL;
8206 + }
8207 +
8208 + panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info),
8209 + GFP_KERNEL);
8210 + if (!panic_regs_info)
8211 + return -ENOMEM;
8212 +
8213 + regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL);
8214 + if (!regs)
8215 + return -ENOMEM;
8216 +
8217 + for (i = 0; i < reg_count; i++) {
8218 + rc = of_property_read_string_index(node,
8219 + "qcom,cpr-panic-reg-name-list", i,
8220 + &(regs[i].name));
8221 + if (rc) {
8222 + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n",
8223 + rc);
8224 + return rc;
8225 + }
8226 +
8227 + rc = of_property_read_u32_index(node,
8228 + "qcom,cpr-panic-reg-addr-list", i,
8229 + &(regs[i].addr));
8230 + if (rc) {
8231 + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n",
8232 + rc);
8233 + return rc;
8234 + }
8235 + regs[i].virt_addr = devm_ioremap(ctrl->dev, regs[i].addr, 0x4);
8236 + if (!regs[i].virt_addr) {
8237 + pr_err("Unable to map panic register addr 0x%08x\n",
8238 + regs[i].addr);
8239 + return -EINVAL;
8240 + }
8241 + regs[i].value = 0xFFFFFFFF;
8242 + }
8243 +
8244 + panic_regs_info->reg_count = reg_count;
8245 + panic_regs_info->regs = regs;
8246 + ctrl->panic_regs_info = panic_regs_info;
8247 +
8248 + return rc;
8249 +}
8250 +
8251 +/**
8252 + * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from
8253 + * device tree
8254 + * @ctrl: Pointer to the CPR3 controller
8255 + *
8256 + * Return: 0 on success, errno on failure
8257 + */
8258 +int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
8259 +{
8260 + int rc;
8261 +
8262 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-sensor-time",
8263 + &ctrl->sensor_time, 0, UINT_MAX);
8264 + if (rc)
8265 + return rc;
8266 +
8267 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-loop-time",
8268 + &ctrl->loop_time, 0, UINT_MAX);
8269 + if (rc)
8270 + return rc;
8271 +
8272 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-idle-cycles",
8273 + &ctrl->idle_clocks, CPR3_IDLE_CLOCKS_MIN,
8274 + CPR3_IDLE_CLOCKS_MAX);
8275 + if (rc)
8276 + return rc;
8277 +
8278 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-min",
8279 + &ctrl->step_quot_init_min, CPR3_STEP_QUOT_MIN,
8280 + CPR3_STEP_QUOT_MAX);
8281 + if (rc)
8282 + return rc;
8283 +
8284 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-max",
8285 + &ctrl->step_quot_init_max, CPR3_STEP_QUOT_MIN,
8286 + CPR3_STEP_QUOT_MAX);
8287 + if (rc)
8288 + return rc;
8289 +
8290 + rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step",
8291 + &ctrl->step_volt);
8292 + if (rc) {
8293 + cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n",
8294 + rc);
8295 + return rc;
8296 + }
8297 + if (ctrl->step_volt <= 0) {
8298 + cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n",
8299 + ctrl->step_volt);
8300 + return -EINVAL;
8301 + }
8302 +
8303 + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-count-mode",
8304 + &ctrl->count_mode, CPR3_COUNT_MODE_ALL_AT_ONCE_MIN,
8305 + CPR3_COUNT_MODE_STAGGERED);
8306 + if (rc)
8307 + return rc;
8308 +
8309 + /* Count repeat is optional */
8310 + ctrl->count_repeat = 0;
8311 + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-count-repeat",
8312 + &ctrl->count_repeat);
8313 +
8314 + ctrl->cpr_allowed_sw =
8315 + of_property_read_bool(ctrl->dev->of_node, "qcom,cpr-enable") ||
8316 + ctrl->cpr_global_setting == CPR_CLOSED_LOOP_EN;
8317 +
8318 + rc = cpr3_parse_irq_affinity(ctrl);
8319 + if (rc)
8320 + return rc;
8321 +
8322 + /* Aging reference voltage is optional */
8323 + ctrl->aging_ref_volt = 0;
8324 + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage",
8325 + &ctrl->aging_ref_volt);
8326 +
8327 + /* Aging possible bitmask is optional */
8328 + ctrl->aging_possible_mask = 0;
8329 + of_property_read_u32(ctrl->dev->of_node,
8330 + "qcom,cpr-aging-allowed-reg-mask",
8331 + &ctrl->aging_possible_mask);
8332 +
8333 + if (ctrl->aging_possible_mask) {
8334 + /*
8335 + * Aging possible register value required if bitmask is
8336 + * specified
8337 + */
8338 + rc = cpr3_parse_ctrl_u32(ctrl,
8339 + "qcom,cpr-aging-allowed-reg-value",
8340 + &ctrl->aging_possible_val, 0, UINT_MAX);
8341 + if (rc)
8342 + return rc;
8343 + }
8344 +
8345 + if (of_find_property(ctrl->dev->of_node, "clock-names", NULL)) {
8346 + ctrl->core_clk = devm_clk_get(ctrl->dev, "core_clk");
8347 + if (IS_ERR(ctrl->core_clk)) {
8348 + rc = PTR_ERR(ctrl->core_clk);
8349 + if (rc != -EPROBE_DEFER)
8350 + cpr3_err(ctrl, "unable request core clock, rc=%d\n",
8351 + rc);
8352 + return rc;
8353 + }
8354 + }
8355 +
8356 + rc = cpr3_panic_notifier_init(ctrl);
8357 + if (rc)
8358 + return rc;
8359 +
8360 + if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) {
8361 + ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd");
8362 + if (IS_ERR(ctrl->vdd_regulator)) {
8363 + rc = PTR_ERR(ctrl->vdd_regulator);
8364 + if (rc != -EPROBE_DEFER)
8365 + cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n",
8366 + rc);
8367 + return rc;
8368 + }
8369 + } else {
8370 + cpr3_err(ctrl, "vdd supply is not defined\n");
8371 + return -ENODEV;
8372 + }
8373 +
8374 + ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev,
8375 + "system");
8376 + if (IS_ERR(ctrl->system_regulator)) {
8377 + rc = PTR_ERR(ctrl->system_regulator);
8378 + if (rc != -EPROBE_DEFER) {
8379 + rc = 0;
8380 + ctrl->system_regulator = NULL;
8381 + } else {
8382 + return rc;
8383 + }
8384 + }
8385 +
8386 + ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev,
8387 + "mem-acc");
8388 + if (IS_ERR(ctrl->mem_acc_regulator)) {
8389 + rc = PTR_ERR(ctrl->mem_acc_regulator);
8390 + if (rc != -EPROBE_DEFER) {
8391 + rc = 0;
8392 + ctrl->mem_acc_regulator = NULL;
8393 + } else {
8394 + return rc;
8395 + }
8396 + }
8397 +
8398 + return rc;
8399 +}
8400 +
8401 +/**
8402 + * cpr3_parse_open_loop_common_ctrl_data() - parse common open loop CPR3
8403 + * controller properties from device tree
8404 + * @ctrl: Pointer to the CPR3 controller
8405 + *
8406 + * Return: 0 on success, errno on failure
8407 + */
8408 +int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl)
8409 +{
8410 + int rc;
8411 +
8412 + rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step",
8413 + &ctrl->step_volt);
8414 + if (rc) {
8415 + cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n",
8416 + rc);
8417 + return rc;
8418 + }
8419 +
8420 + if (ctrl->step_volt <= 0) {
8421 + cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n",
8422 + ctrl->step_volt);
8423 + return -EINVAL;
8424 + }
8425 +
8426 + if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) {
8427 + ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd");
8428 + if (IS_ERR(ctrl->vdd_regulator)) {
8429 + rc = PTR_ERR(ctrl->vdd_regulator);
8430 + if (rc != -EPROBE_DEFER)
8431 + cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n",
8432 + rc);
8433 + return rc;
8434 + }
8435 + } else {
8436 + cpr3_err(ctrl, "vdd supply is not defined\n");
8437 + return -ENODEV;
8438 + }
8439 +
8440 + ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev,
8441 + "system");
8442 + if (IS_ERR(ctrl->system_regulator)) {
8443 + rc = PTR_ERR(ctrl->system_regulator);
8444 + if (rc != -EPROBE_DEFER) {
8445 + rc = 0;
8446 + ctrl->system_regulator = NULL;
8447 + } else {
8448 + return rc;
8449 + }
8450 + } else {
8451 + rc = regulator_enable(ctrl->system_regulator);
8452 + }
8453 +
8454 + ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev,
8455 + "mem-acc");
8456 + if (IS_ERR(ctrl->mem_acc_regulator)) {
8457 + rc = PTR_ERR(ctrl->mem_acc_regulator);
8458 + if (rc != -EPROBE_DEFER) {
8459 + rc = 0;
8460 + ctrl->mem_acc_regulator = NULL;
8461 + } else {
8462 + return rc;
8463 + }
8464 + }
8465 +
8466 + return rc;
8467 +}
8468 +
8469 +/**
8470 + * cpr3_limit_open_loop_voltages() - modify the open-loop voltage of each corner
8471 + * so that it fits within the floor to ceiling
8472 + * voltage range of the corner
8473 + * @vreg: Pointer to the CPR3 regulator
8474 + *
8475 + * This function clips the open-loop voltage for each corner so that it is
8476 + * limited to the floor to ceiling range. It also rounds each open-loop voltage
8477 + * so that it corresponds to a set point available to the underlying regulator.
8478 + *
8479 + * Return: 0 on success, errno on failure
8480 + */
8481 +int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg)
8482 +{
8483 + int i, volt;
8484 +
8485 + cpr3_debug(vreg, "open-loop voltages after trimming and rounding:\n");
8486 + for (i = 0; i < vreg->corner_count; i++) {
8487 + volt = CPR3_ROUND(vreg->corner[i].open_loop_volt,
8488 + vreg->thread->ctrl->step_volt);
8489 + if (volt < vreg->corner[i].floor_volt)
8490 + volt = vreg->corner[i].floor_volt;
8491 + else if (volt > vreg->corner[i].ceiling_volt)
8492 + volt = vreg->corner[i].ceiling_volt;
8493 + vreg->corner[i].open_loop_volt = volt;
8494 + cpr3_debug(vreg, "corner[%2d]: open-loop=%d uV\n", i, volt);
8495 + }
8496 +
8497 + return 0;
8498 +}
8499 +
8500 +/**
8501 + * cpr3_open_loop_voltage_as_ceiling() - configures the ceiling voltage for each
8502 + * corner to equal the open-loop voltage if the relevant device
8503 + * tree property is found for the CPR3 regulator
8504 + * @vreg: Pointer to the CPR3 regulator
8505 + *
8506 + * This function assumes that the the open-loop voltage for each corner has
8507 + * already been rounded to the nearest allowed set point and that it falls
8508 + * within the floor to ceiling range.
8509 + *
8510 + * Return: none
8511 + */
8512 +void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg)
8513 +{
8514 + int i;
8515 +
8516 + if (!of_property_read_bool(vreg->of_node,
8517 + "qcom,cpr-scaled-open-loop-voltage-as-ceiling"))
8518 + return;
8519 +
8520 + for (i = 0; i < vreg->corner_count; i++)
8521 + vreg->corner[i].ceiling_volt
8522 + = vreg->corner[i].open_loop_volt;
8523 +}
8524 +
8525 +/**
8526 + * cpr3_limit_floor_voltages() - raise the floor voltage of each corner so that
8527 + * the optional maximum floor to ceiling voltage range specified in
8528 + * device tree is satisfied
8529 + * @vreg: Pointer to the CPR3 regulator
8530 + *
8531 + * This function also ensures that the open-loop voltage for each corner falls
8532 + * within the final floor to ceiling voltage range and that floor voltages
8533 + * increase monotonically.
8534 + *
8535 + * Return: 0 on success, errno on failure
8536 + */
8537 +int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg)
8538 +{
8539 + char *prop = "qcom,cpr-floor-to-ceiling-max-range";
8540 + int i, floor_new;
8541 + u32 *floor_range;
8542 + int rc = 0;
8543 +
8544 + if (!of_find_property(vreg->of_node, prop, NULL))
8545 + goto enforce_monotonicity;
8546 +
8547 + floor_range = kcalloc(vreg->corner_count, sizeof(*floor_range),
8548 + GFP_KERNEL);
8549 + if (!floor_range)
8550 + return -ENOMEM;
8551 +
8552 + rc = cpr3_parse_corner_array_property(vreg, prop, 1, floor_range);
8553 + if (rc)
8554 + goto free_floor_adjust;
8555 +
8556 + for (i = 0; i < vreg->corner_count; i++) {
8557 + if ((s32)floor_range[i] >= 0) {
8558 + floor_new = CPR3_ROUND(vreg->corner[i].ceiling_volt
8559 + - floor_range[i],
8560 + vreg->thread->ctrl->step_volt);
8561 +
8562 + vreg->corner[i].floor_volt = max(floor_new,
8563 + vreg->corner[i].floor_volt);
8564 + if (vreg->corner[i].open_loop_volt
8565 + < vreg->corner[i].floor_volt)
8566 + vreg->corner[i].open_loop_volt
8567 + = vreg->corner[i].floor_volt;
8568 + }
8569 + }
8570 +
8571 +free_floor_adjust:
8572 + kfree(floor_range);
8573 +
8574 +enforce_monotonicity:
8575 + /* Ensure that floor voltages increase monotonically. */
8576 + for (i = 1; i < vreg->corner_count; i++) {
8577 + if (vreg->corner[i].floor_volt
8578 + < vreg->corner[i - 1].floor_volt) {
8579 + cpr3_debug(vreg, "corner %d floor voltage=%d uV < corner %d voltage=%d uV; overriding: corner %d voltage=%d\n",
8580 + i, vreg->corner[i].floor_volt,
8581 + i - 1, vreg->corner[i - 1].floor_volt,
8582 + i, vreg->corner[i - 1].floor_volt);
8583 + vreg->corner[i].floor_volt
8584 + = vreg->corner[i - 1].floor_volt;
8585 +
8586 + if (vreg->corner[i].open_loop_volt
8587 + < vreg->corner[i].floor_volt)
8588 + vreg->corner[i].open_loop_volt
8589 + = vreg->corner[i].floor_volt;
8590 + if (vreg->corner[i].ceiling_volt
8591 + < vreg->corner[i].floor_volt)
8592 + vreg->corner[i].ceiling_volt
8593 + = vreg->corner[i].floor_volt;
8594 + }
8595 + }
8596 +
8597 + return rc;
8598 +}
8599 +
8600 +/**
8601 + * cpr3_print_quots() - print CPR target quotients into the kernel log for
8602 + * debugging purposes
8603 + * @vreg: Pointer to the CPR3 regulator
8604 + *
8605 + * Return: none
8606 + */
8607 +void cpr3_print_quots(struct cpr3_regulator *vreg)
8608 +{
8609 + int i, j, pos;
8610 + size_t buflen;
8611 + char *buf;
8612 +
8613 + buflen = sizeof(*buf) * CPR3_RO_COUNT * (MAX_CHARS_PER_INT + 2);
8614 + buf = kzalloc(buflen, GFP_KERNEL);
8615 + if (!buf)
8616 + return;
8617 +
8618 + for (i = 0; i < vreg->corner_count; i++) {
8619 + for (j = 0, pos = 0; j < CPR3_RO_COUNT; j++)
8620 + pos += scnprintf(buf + pos, buflen - pos, " %u",
8621 + vreg->corner[i].target_quot[j]);
8622 + cpr3_debug(vreg, "target quots[%2d]:%s\n", i, buf);
8623 + }
8624 +
8625 + kfree(buf);
8626 +}
8627 +
8628 +/**
8629 + * cpr3_determine_part_type() - determine the part type (SS/TT/FF).
8630 + *
8631 + * qcom,cpr-part-types prop tells the number of part types for which correction
8632 + * voltages are different. Another prop qcom,cpr-parts-voltage will contain the
8633 + * open loop fuse voltage which will be compared with this part voltage
8634 + * and accordingly part type will de determined.
8635 + *
8636 + * if qcom,cpr-part-types has value n, then qcom,cpr-parts-voltage will be
8637 + * array of n - 1 elements which will contain the voltage in increasing order.
8638 + * This function compares the fused volatge with all these voltage and returns
8639 + * the first index for which the fused volatge is greater.
8640 + *
8641 + * @vreg: Pointer to the CPR3 regulator
8642 + * @fuse_volt: fused open loop voltage which will be compared with
8643 + * qcom,cpr-parts-voltage array
8644 + *
8645 + * Return: 0 on success, errno on failure
8646 + */
8647 +int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt)
8648 +{
8649 + int i, rc, len;
8650 + u32 volt;
8651 + int soc_version_major;
8652 + char prop_name[100];
8653 + const char prop_name_def[] = "qcom,cpr-parts-voltage";
8654 + const char prop_name_v2[] = "qcom,cpr-parts-voltage-v2";
8655 +
8656 + soc_version_major = read_ipq_soc_version_major();
8657 + BUG_ON(soc_version_major <= 0);
8658 +
8659 + if (of_property_read_u32(vreg->of_node, "qcom,cpr-part-types",
8660 + &vreg->part_type_supported))
8661 + return 0;
8662 +
8663 + if (soc_version_major > 1)
8664 + strlcpy(prop_name, prop_name_v2, sizeof(prop_name_v2));
8665 + else
8666 + strlcpy(prop_name, prop_name_def, sizeof(prop_name_def));
8667 +
8668 + if (!of_find_property(vreg->of_node, prop_name, &len)) {
8669 + cpr3_err(vreg, "property %s is missing\n", prop_name);
8670 + return -EINVAL;
8671 + }
8672 +
8673 + if (len != (vreg->part_type_supported - 1) * sizeof(u32)) {
8674 + cpr3_err(vreg, "wrong len in qcom,cpr-parts-voltage\n");
8675 + return -EINVAL;
8676 + }
8677 +
8678 + for (i = 0; i < vreg->part_type_supported - 1; i++) {
8679 + rc = of_property_read_u32_index(vreg->of_node,
8680 + prop_name, i, &volt);
8681 + if (rc) {
8682 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
8683 + prop_name, rc);
8684 + return rc;
8685 + }
8686 +
8687 + if (fuse_volt < volt)
8688 + break;
8689 + }
8690 +
8691 + vreg->part_type = i;
8692 + return 0;
8693 +}
8694 +
8695 +int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
8696 + int *fuse_volt)
8697 +{
8698 + int i, rc, prev_volt;
8699 + int *volt_adjust;
8700 + char prop_str[75];
8701 + int soc_version_major = read_ipq_soc_version_major();
8702 +
8703 + BUG_ON(soc_version_major <= 0);
8704 +
8705 + if (vreg->part_type_supported) {
8706 + if (soc_version_major > 1)
8707 + snprintf(prop_str, sizeof(prop_str),
8708 + "qcom,cpr-cold-temp-voltage-adjustment-v2-%d",
8709 + vreg->part_type);
8710 + else
8711 + snprintf(prop_str, sizeof(prop_str),
8712 + "qcom,cpr-cold-temp-voltage-adjustment-%d",
8713 + vreg->part_type);
8714 + } else {
8715 + strlcpy(prop_str, "qcom,cpr-cold-temp-voltage-adjustment",
8716 + sizeof(prop_str));
8717 + }
8718 +
8719 + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
8720 + /* No adjustment required. */
8721 + cpr3_info(vreg, "No cold temperature adjustment required.\n");
8722 + return 0;
8723 + }
8724 +
8725 + volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust),
8726 + GFP_KERNEL);
8727 + if (!volt_adjust)
8728 + return -ENOMEM;
8729 +
8730 + rc = cpr3_parse_array_property(vreg, prop_str,
8731 + vreg->fuse_corner_count, volt_adjust);
8732 + if (rc) {
8733 + cpr3_err(vreg, "could not load cold temp voltage adjustments, rc=%d\n",
8734 + rc);
8735 + goto done;
8736 + }
8737 +
8738 + for (i = 0; i < vreg->fuse_corner_count; i++) {
8739 + if (volt_adjust[i]) {
8740 + prev_volt = fuse_volt[i];
8741 + fuse_volt[i] += volt_adjust[i];
8742 + cpr3_debug(vreg,
8743 + "adjusted fuse corner %d open-loop voltage: %d -> %d uV\n",
8744 + i, prev_volt, fuse_volt[i]);
8745 + }
8746 + }
8747 +
8748 +done:
8749 + kfree(volt_adjust);
8750 + return rc;
8751 +}
8752 +
8753 +/**
8754 + * cpr3_can_adjust_cold_temp() - Is cold temperature adjustment available
8755 + *
8756 + * @vreg: Pointer to the CPR3 regulator
8757 + *
8758 + * This function checks the cold temperature threshold is available
8759 + *
8760 + * Return: true on cold temperature threshold is available, else false
8761 + */
8762 +bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg)
8763 +{
8764 + char prop_str[75];
8765 + int soc_version_major = read_ipq_soc_version_major();
8766 +
8767 + BUG_ON(soc_version_major <= 0);
8768 +
8769 + if (soc_version_major > 1)
8770 + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2",
8771 + sizeof(prop_str));
8772 + else
8773 + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold",
8774 + sizeof(prop_str));
8775 +
8776 + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
8777 + /* No adjustment required. */
8778 + return false;
8779 + } else
8780 + return true;
8781 +}
8782 +
8783 +/**
8784 + * cpr3_get_cold_temp_threshold() - get cold temperature threshold
8785 + *
8786 + * @vreg: Pointer to the CPR3 regulator
8787 + * @cold_temp: cold temperature read.
8788 + *
8789 + * This function reads the cold temperature threshold below which
8790 + * cold temperature adjustment margins will be applied.
8791 + *
8792 + * Return: 0 on success, errno on failure
8793 + */
8794 +int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp)
8795 +{
8796 + int rc;
8797 + u32 temp;
8798 + char req_prop_str[75], prop_str[75];
8799 + int soc_version_major = read_ipq_soc_version_major();
8800 +
8801 + BUG_ON(soc_version_major <= 0);
8802 +
8803 + if (vreg->part_type_supported) {
8804 + if (soc_version_major > 1)
8805 + snprintf(req_prop_str, sizeof(req_prop_str),
8806 + "qcom,cpr-cold-temp-voltage-adjustment-v2-%d",
8807 + vreg->part_type);
8808 + else
8809 + snprintf(req_prop_str, sizeof(req_prop_str),
8810 + "qcom,cpr-cold-temp-voltage-adjustment-%d",
8811 + vreg->part_type);
8812 + } else {
8813 + strlcpy(req_prop_str, "qcom,cpr-cold-temp-voltage-adjustment",
8814 + sizeof(req_prop_str));
8815 + }
8816 +
8817 + if (soc_version_major > 1)
8818 + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2",
8819 + sizeof(prop_str));
8820 + else
8821 + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold",
8822 + sizeof(prop_str));
8823 +
8824 + if (!of_find_property(vreg->of_node, req_prop_str, NULL)) {
8825 + /* No adjustment required. */
8826 + cpr3_info(vreg, "Cold temperature adjustment not required.\n");
8827 + return 0;
8828 + }
8829 +
8830 + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
8831 + /* No adjustment required. */
8832 + cpr3_err(vreg, "Missing %s required for %s\n",
8833 + prop_str, req_prop_str);
8834 + return -EINVAL;
8835 + }
8836 +
8837 + rc = of_property_read_u32(vreg->of_node, prop_str, &temp);
8838 + if (rc) {
8839 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
8840 + prop_str, rc);
8841 + return rc;
8842 + }
8843 +
8844 + *cold_temp = temp;
8845 + return 0;
8846 +}
8847 +
8848 +/**
8849 + * cpr3_adjust_fused_open_loop_voltages() - adjust the fused open-loop voltages
8850 + * for each fuse corner according to device tree values
8851 + * @vreg: Pointer to the CPR3 regulator
8852 + * @fuse_volt: Pointer to an array of the fused open-loop voltage
8853 + * values
8854 + *
8855 + * Voltage values in fuse_volt are modified in place.
8856 + *
8857 + * Return: 0 on success, errno on failure
8858 + */
8859 +int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
8860 + int *fuse_volt)
8861 +{
8862 + int i, rc, prev_volt;
8863 + int *volt_adjust;
8864 + char prop_str[75];
8865 + int soc_version_major = read_ipq_soc_version_major();
8866 +
8867 + BUG_ON(soc_version_major <= 0);
8868 +
8869 + if (vreg->part_type_supported) {
8870 + if (soc_version_major > 1)
8871 + snprintf(prop_str, sizeof(prop_str),
8872 + "qcom,cpr-open-loop-voltage-fuse-adjustment-v2-%d",
8873 + vreg->part_type);
8874 + else
8875 + snprintf(prop_str, sizeof(prop_str),
8876 + "qcom,cpr-open-loop-voltage-fuse-adjustment-%d",
8877 + vreg->part_type);
8878 + } else {
8879 + strlcpy(prop_str, "qcom,cpr-open-loop-voltage-fuse-adjustment",
8880 + sizeof(prop_str));
8881 + }
8882 +
8883 + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
8884 + /* No adjustment required. */
8885 + return 0;
8886 + }
8887 +
8888 + volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust),
8889 + GFP_KERNEL);
8890 + if (!volt_adjust)
8891 + return -ENOMEM;
8892 +
8893 + rc = cpr3_parse_array_property(vreg,
8894 + prop_str, vreg->fuse_corner_count, volt_adjust);
8895 + if (rc) {
8896 + cpr3_err(vreg, "could not load open-loop fused voltage adjustments, rc=%d\n",
8897 + rc);
8898 + goto done;
8899 + }
8900 +
8901 + for (i = 0; i < vreg->fuse_corner_count; i++) {
8902 + if (volt_adjust[i]) {
8903 + prev_volt = fuse_volt[i];
8904 + fuse_volt[i] += volt_adjust[i];
8905 + cpr3_debug(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n",
8906 + i, prev_volt, fuse_volt[i]);
8907 + }
8908 + }
8909 +
8910 +done:
8911 + kfree(volt_adjust);
8912 + return rc;
8913 +}
8914 +
8915 +/**
8916 + * cpr3_adjust_open_loop_voltages() - adjust the open-loop voltages for each
8917 + * corner according to device tree values
8918 + * @vreg: Pointer to the CPR3 regulator
8919 + *
8920 + * Return: 0 on success, errno on failure
8921 + */
8922 +int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
8923 +{
8924 + int i, rc, prev_volt, min_volt;
8925 + int *volt_adjust, *volt_diff;
8926 +
8927 + if (!of_find_property(vreg->of_node,
8928 + "qcom,cpr-open-loop-voltage-adjustment", NULL)) {
8929 + /* No adjustment required. */
8930 + return 0;
8931 + }
8932 +
8933 + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
8934 + GFP_KERNEL);
8935 + volt_diff = kcalloc(vreg->corner_count, sizeof(*volt_diff), GFP_KERNEL);
8936 + if (!volt_adjust || !volt_diff) {
8937 + rc = -ENOMEM;
8938 + goto done;
8939 + }
8940 +
8941 + rc = cpr3_parse_corner_array_property(vreg,
8942 + "qcom,cpr-open-loop-voltage-adjustment", 1, volt_adjust);
8943 + if (rc) {
8944 + cpr3_err(vreg, "could not load open-loop voltage adjustments, rc=%d\n",
8945 + rc);
8946 + goto done;
8947 + }
8948 +
8949 + for (i = 0; i < vreg->corner_count; i++) {
8950 + if (volt_adjust[i]) {
8951 + prev_volt = vreg->corner[i].open_loop_volt;
8952 + vreg->corner[i].open_loop_volt += volt_adjust[i];
8953 + cpr3_debug(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n",
8954 + i, prev_volt, vreg->corner[i].open_loop_volt);
8955 + }
8956 + }
8957 +
8958 + if (of_find_property(vreg->of_node,
8959 + "qcom,cpr-open-loop-voltage-min-diff", NULL)) {
8960 + rc = cpr3_parse_corner_array_property(vreg,
8961 + "qcom,cpr-open-loop-voltage-min-diff", 1, volt_diff);
8962 + if (rc) {
8963 + cpr3_err(vreg, "could not load minimum open-loop voltage differences, rc=%d\n",
8964 + rc);
8965 + goto done;
8966 + }
8967 + }
8968 +
8969 + /*
8970 + * Ensure that open-loop voltages increase monotonically with respect
8971 + * to configurable minimum allowed differences.
8972 + */
8973 + for (i = 1; i < vreg->corner_count; i++) {
8974 + min_volt = vreg->corner[i - 1].open_loop_volt + volt_diff[i];
8975 + if (vreg->corner[i].open_loop_volt < min_volt) {
8976 + 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",
8977 + i, vreg->corner[i].open_loop_volt,
8978 + i - 1, vreg->corner[i - 1].open_loop_volt,
8979 + volt_diff[i], i, min_volt);
8980 + vreg->corner[i].open_loop_volt = min_volt;
8981 + }
8982 + }
8983 +
8984 +done:
8985 + kfree(volt_diff);
8986 + kfree(volt_adjust);
8987 + return rc;
8988 +}
8989 +
8990 +/**
8991 + * cpr3_quot_adjustment() - returns the quotient adjustment value resulting from
8992 + * the specified voltage adjustment and RO scaling factor
8993 + * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
8994 + * of QUOT/V
8995 + * @volt_adjust: The amount to adjust the voltage by in units of
8996 + * microvolts. This value may be positive or negative.
8997 + */
8998 +int cpr3_quot_adjustment(int ro_scale, int volt_adjust)
8999 +{
9000 + unsigned long long temp;
9001 + int quot_adjust;
9002 + int sign = 1;
9003 +
9004 + if (ro_scale < 0) {
9005 + sign = -sign;
9006 + ro_scale = -ro_scale;
9007 + }
9008 +
9009 + if (volt_adjust < 0) {
9010 + sign = -sign;
9011 + volt_adjust = -volt_adjust;
9012 + }
9013 +
9014 + temp = (unsigned long long)ro_scale * (unsigned long long)volt_adjust;
9015 + do_div(temp, 1000000);
9016 +
9017 + quot_adjust = temp;
9018 + quot_adjust *= sign;
9019 +
9020 + return quot_adjust;
9021 +}
9022 +
9023 +/**
9024 + * cpr3_voltage_adjustment() - returns the voltage adjustment value resulting
9025 + * from the specified quotient adjustment and RO scaling factor
9026 + * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
9027 + * of QUOT/V
9028 + * @quot_adjust: The amount to adjust the quotient by in units of
9029 + * QUOT. This value may be positive or negative.
9030 + */
9031 +int cpr3_voltage_adjustment(int ro_scale, int quot_adjust)
9032 +{
9033 + unsigned long long temp;
9034 + int volt_adjust;
9035 + int sign = 1;
9036 +
9037 + if (ro_scale < 0) {
9038 + sign = -sign;
9039 + ro_scale = -ro_scale;
9040 + }
9041 +
9042 + if (quot_adjust < 0) {
9043 + sign = -sign;
9044 + quot_adjust = -quot_adjust;
9045 + }
9046 +
9047 + if (ro_scale == 0)
9048 + return 0;
9049 +
9050 + temp = (unsigned long long)quot_adjust * 1000000;
9051 + do_div(temp, ro_scale);
9052 +
9053 + volt_adjust = temp;
9054 + volt_adjust *= sign;
9055 +
9056 + return volt_adjust;
9057 +}
9058 +
9059 +/**
9060 + * cpr3_parse_closed_loop_voltage_adjustments() - load per-fuse-corner and
9061 + * per-corner closed-loop adjustment values from device tree
9062 + * @vreg: Pointer to the CPR3 regulator
9063 + * @ro_sel: Array of ring oscillator values selected for each
9064 + * fuse corner
9065 + * @volt_adjust: Pointer to array which will be filled with the
9066 + * per-corner closed-loop adjustment voltages
9067 + * @volt_adjust_fuse: Pointer to array which will be filled with the
9068 + * per-fuse-corner closed-loop adjustment voltages
9069 + * @ro_scale: Pointer to array which will be filled with the
9070 + * per-fuse-corner RO scaling factor values with units of
9071 + * QUOT/V
9072 + *
9073 + * Return: 0 on success, errno on failure
9074 + */
9075 +int cpr3_parse_closed_loop_voltage_adjustments(
9076 + struct cpr3_regulator *vreg, u64 *ro_sel,
9077 + int *volt_adjust, int *volt_adjust_fuse, int *ro_scale)
9078 +{
9079 + int i, rc;
9080 + u32 *ro_all_scale;
9081 +
9082 + char volt_adj[] = "qcom,cpr-closed-loop-voltage-adjustment";
9083 + char volt_fuse_adj[] = "qcom,cpr-closed-loop-voltage-fuse-adjustment";
9084 + char ro_scaling[] = "qcom,cpr-ro-scaling-factor";
9085 +
9086 + if (!of_find_property(vreg->of_node, volt_adj, NULL)
9087 + && !of_find_property(vreg->of_node, volt_fuse_adj, NULL)
9088 + && !vreg->aging_allowed) {
9089 + /* No adjustment required. */
9090 + return 0;
9091 + } else if (!of_find_property(vreg->of_node, ro_scaling, NULL)) {
9092 + cpr3_err(vreg, "Missing %s required for closed-loop voltage adjustment.\n",
9093 + ro_scaling);
9094 + return -EINVAL;
9095 + }
9096 +
9097 + ro_all_scale = kcalloc(vreg->fuse_corner_count * CPR3_RO_COUNT,
9098 + sizeof(*ro_all_scale), GFP_KERNEL);
9099 + if (!ro_all_scale)
9100 + return -ENOMEM;
9101 +
9102 + rc = cpr3_parse_array_property(vreg, ro_scaling,
9103 + vreg->fuse_corner_count * CPR3_RO_COUNT, ro_all_scale);
9104 + if (rc) {
9105 + cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
9106 + rc);
9107 + goto done;
9108 + }
9109 +
9110 + for (i = 0; i < vreg->fuse_corner_count; i++)
9111 + ro_scale[i] = ro_all_scale[i * CPR3_RO_COUNT + ro_sel[i]];
9112 +
9113 + for (i = 0; i < vreg->corner_count; i++)
9114 + memcpy(vreg->corner[i].ro_scale,
9115 + &ro_all_scale[vreg->corner[i].cpr_fuse_corner * CPR3_RO_COUNT],
9116 + sizeof(*ro_all_scale) * CPR3_RO_COUNT);
9117 +
9118 + if (of_find_property(vreg->of_node, volt_fuse_adj, NULL)) {
9119 + rc = cpr3_parse_array_property(vreg, volt_fuse_adj,
9120 + vreg->fuse_corner_count, volt_adjust_fuse);
9121 + if (rc) {
9122 + cpr3_err(vreg, "could not load closed-loop fused voltage adjustments, rc=%d\n",
9123 + rc);
9124 + goto done;
9125 + }
9126 + }
9127 +
9128 + if (of_find_property(vreg->of_node, volt_adj, NULL)) {
9129 + rc = cpr3_parse_corner_array_property(vreg, volt_adj,
9130 + 1, volt_adjust);
9131 + if (rc) {
9132 + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
9133 + rc);
9134 + goto done;
9135 + }
9136 + }
9137 +
9138 +done:
9139 + kfree(ro_all_scale);
9140 + return rc;
9141 +}
9142 +
9143 +/**
9144 + * cpr3_apm_init() - initialize APM data for a CPR3 controller
9145 + * @ctrl: Pointer to the CPR3 controller
9146 + *
9147 + * This function loads memory array power mux (APM) data from device tree
9148 + * if it is present and requests a handle to the appropriate APM controller
9149 + * device.
9150 + *
9151 + * Return: 0 on success, errno on failure
9152 + */
9153 +int cpr3_apm_init(struct cpr3_controller *ctrl)
9154 +{
9155 + struct device_node *node = ctrl->dev->of_node;
9156 + int rc;
9157 +
9158 + if (!of_find_property(node, "qcom,apm-ctrl", NULL)) {
9159 + /* No APM used */
9160 + return 0;
9161 + }
9162 +
9163 + ctrl->apm = msm_apm_ctrl_dev_get(ctrl->dev);
9164 + if (IS_ERR(ctrl->apm)) {
9165 + rc = PTR_ERR(ctrl->apm);
9166 + if (rc != -EPROBE_DEFER)
9167 + cpr3_err(ctrl, "APM get failed, rc=%d\n", rc);
9168 + return rc;
9169 + }
9170 +
9171 + rc = of_property_read_u32(node, "qcom,apm-threshold-voltage",
9172 + &ctrl->apm_threshold_volt);
9173 + if (rc) {
9174 + cpr3_err(ctrl, "error reading qcom,apm-threshold-voltage, rc=%d\n",
9175 + rc);
9176 + return rc;
9177 + }
9178 + ctrl->apm_threshold_volt
9179 + = CPR3_ROUND(ctrl->apm_threshold_volt, ctrl->step_volt);
9180 +
9181 + /* No error check since this is an optional property. */
9182 + of_property_read_u32(node, "qcom,apm-hysteresis-voltage",
9183 + &ctrl->apm_adj_volt);
9184 + ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
9185 +
9186 + ctrl->apm_high_supply = MSM_APM_SUPPLY_APCC;
9187 + ctrl->apm_low_supply = MSM_APM_SUPPLY_MX;
9188 +
9189 + return 0;
9190 +}
9191 +
9192 +/**
9193 + * cpr3_mem_acc_init() - initialize mem-acc regulator data for
9194 + * a CPR3 regulator
9195 + * @ctrl: Pointer to the CPR3 controller
9196 + *
9197 + * Return: 0 on success, errno on failure
9198 + */
9199 +int cpr3_mem_acc_init(struct cpr3_regulator *vreg)
9200 +{
9201 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
9202 + u32 *temp;
9203 + int i, rc;
9204 +
9205 + if (!ctrl->mem_acc_regulator) {
9206 + cpr3_info(ctrl, "not using memory accelerator regulator\n");
9207 + return 0;
9208 + }
9209 +
9210 + temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
9211 + if (!temp)
9212 + return -ENOMEM;
9213 +
9214 + rc = cpr3_parse_corner_array_property(vreg, "qcom,mem-acc-voltage",
9215 + 1, temp);
9216 + if (rc) {
9217 + cpr3_err(ctrl, "could not load mem-acc corners, rc=%d\n", rc);
9218 + } else {
9219 + for (i = 0; i < vreg->corner_count; i++)
9220 + vreg->corner[i].mem_acc_volt = temp[i];
9221 + }
9222 +
9223 + kfree(temp);
9224 + return rc;
9225 +}
9226 +
9227 +/**
9228 + * cpr4_load_core_and_temp_adj() - parse amount of voltage adjustment for
9229 + * per-online-core and per-temperature voltage adjustment for a
9230 + * given corner or corner band from device tree.
9231 + * @vreg: Pointer to the CPR3 regulator
9232 + * @num: Corner number or corner band number
9233 + * @use_corner_band: Boolean indicating if the CPR3 regulator supports
9234 + * adjustments per corner band
9235 + *
9236 + * Return: 0 on success, errno on failure
9237 + */
9238 +static int cpr4_load_core_and_temp_adj(struct cpr3_regulator *vreg,
9239 + int num, bool use_corner_band)
9240 +{
9241 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
9242 + struct cpr4_sdelta *sdelta;
9243 + int sdelta_size, i, j, pos, rc = 0;
9244 + char str[75];
9245 + size_t buflen;
9246 + char *buf;
9247 +
9248 + sdelta = use_corner_band ? vreg->corner_band[num].sdelta :
9249 + vreg->corner[num].sdelta;
9250 +
9251 + if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj) {
9252 + /* corner doesn't need sdelta table */
9253 + sdelta->max_core_count = 0;
9254 + sdelta->temp_band_count = 0;
9255 + return rc;
9256 + }
9257 +
9258 + sdelta_size = sdelta->max_core_count * sdelta->temp_band_count;
9259 + if (use_corner_band)
9260 + snprintf(str, sizeof(str),
9261 + "corner_band=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n",
9262 + num, sdelta->max_core_count,
9263 + sdelta->temp_band_count, sdelta_size);
9264 + else
9265 + snprintf(str, sizeof(str),
9266 + "corner=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n",
9267 + num, sdelta->max_core_count,
9268 + sdelta->temp_band_count, sdelta_size);
9269 +
9270 + cpr3_debug(vreg, "%s", str);
9271 +
9272 + sdelta->table = devm_kcalloc(ctrl->dev, sdelta_size,
9273 + sizeof(*sdelta->table), GFP_KERNEL);
9274 + if (!sdelta->table)
9275 + return -ENOMEM;
9276 +
9277 + if (use_corner_band)
9278 + snprintf(str, sizeof(str),
9279 + "qcom,cpr-corner-band%d-temp-core-voltage-adjustment",
9280 + num + CPR3_CORNER_OFFSET);
9281 + else
9282 + snprintf(str, sizeof(str),
9283 + "qcom,cpr-corner%d-temp-core-voltage-adjustment",
9284 + num + CPR3_CORNER_OFFSET);
9285 +
9286 + rc = cpr3_parse_array_property(vreg, str, sdelta_size,
9287 + sdelta->table);
9288 + if (rc) {
9289 + cpr3_err(vreg, "could not load %s, rc=%d\n", str, rc);
9290 + return rc;
9291 + }
9292 +
9293 + /*
9294 + * Convert sdelta margins from uV to PMIC steps and apply negation to
9295 + * follow the SDELTA register semantics.
9296 + */
9297 + for (i = 0; i < sdelta_size; i++)
9298 + sdelta->table[i] = -(sdelta->table[i] / ctrl->step_volt);
9299 +
9300 + buflen = sizeof(*buf) * sdelta_size * (MAX_CHARS_PER_INT + 2);
9301 + buf = kzalloc(buflen, GFP_KERNEL);
9302 + if (!buf)
9303 + return rc;
9304 +
9305 + for (i = 0; i < sdelta->max_core_count; i++) {
9306 + for (j = 0, pos = 0; j < sdelta->temp_band_count; j++)
9307 + pos += scnprintf(buf + pos, buflen - pos, " %u",
9308 + sdelta->table[i * sdelta->temp_band_count + j]);
9309 + cpr3_debug(vreg, "sdelta[%d]:%s\n", i, buf);
9310 + }
9311 +
9312 + kfree(buf);
9313 + return rc;
9314 +}
9315 +
9316 +/**
9317 + * cpr4_parse_core_count_temp_voltage_adj() - parse configuration data for
9318 + * per-online-core and per-temperature voltage adjustment for
9319 + * a CPR3 regulator from device tree.
9320 + * @vreg: Pointer to the CPR3 regulator
9321 + * @use_corner_band: Boolean indicating if the CPR3 regulator supports
9322 + * adjustments per corner band
9323 + *
9324 + * This function supports parsing of per-online-core and per-temperature
9325 + * adjustments per corner or per corner band. CPR controllers which support
9326 + * corner bands apply the same adjustments to all corners within a corner band.
9327 + *
9328 + * Return: 0 on success, errno on failure
9329 + */
9330 +int cpr4_parse_core_count_temp_voltage_adj(
9331 + struct cpr3_regulator *vreg, bool use_corner_band)
9332 +{
9333 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
9334 + struct device_node *node = vreg->of_node;
9335 + struct cpr3_corner *corner;
9336 + struct cpr4_sdelta *sdelta;
9337 + int i, sdelta_table_count, rc = 0;
9338 + int *allow_core_count_adj = NULL, *allow_temp_adj = NULL;
9339 + char prop_str[75];
9340 +
9341 + if (of_find_property(node, use_corner_band ?
9342 + "qcom,corner-band-allow-temp-adjustment"
9343 + : "qcom,corner-allow-temp-adjustment", NULL)) {
9344 + if (!ctrl->allow_temp_adj) {
9345 + cpr3_err(ctrl, "Temperature adjustment configurations missing\n");
9346 + return -EINVAL;
9347 + }
9348 +
9349 + vreg->allow_temp_adj = true;
9350 + }
9351 +
9352 + if (of_find_property(node, use_corner_band ?
9353 + "qcom,corner-band-allow-core-count-adjustment"
9354 + : "qcom,corner-allow-core-count-adjustment",
9355 + NULL)) {
9356 + rc = of_property_read_u32(node, "qcom,max-core-count",
9357 + &vreg->max_core_count);
9358 + if (rc) {
9359 + cpr3_err(vreg, "error reading qcom,max-core-count, rc=%d\n",
9360 + rc);
9361 + return -EINVAL;
9362 + }
9363 +
9364 + vreg->allow_core_count_adj = true;
9365 + ctrl->allow_core_count_adj = true;
9366 + }
9367 +
9368 + if (!vreg->allow_temp_adj && !vreg->allow_core_count_adj) {
9369 + /*
9370 + * Both per-online-core and temperature based adjustments are
9371 + * disabled for this regulator.
9372 + */
9373 + return 0;
9374 + } else if (!vreg->allow_core_count_adj) {
9375 + /*
9376 + * Only per-temperature voltage adjusments are allowed.
9377 + * Keep max core count value as 1 to allocate SDELTA.
9378 + */
9379 + vreg->max_core_count = 1;
9380 + }
9381 +
9382 + if (vreg->allow_core_count_adj) {
9383 + allow_core_count_adj = kcalloc(vreg->corner_count,
9384 + sizeof(*allow_core_count_adj),
9385 + GFP_KERNEL);
9386 + if (!allow_core_count_adj)
9387 + return -ENOMEM;
9388 +
9389 + snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ?
9390 + "qcom,corner-band-allow-core-count-adjustment" :
9391 + "qcom,corner-allow-core-count-adjustment");
9392 +
9393 + rc = use_corner_band ?
9394 + cpr3_parse_corner_band_array_property(vreg, prop_str,
9395 + 1, allow_core_count_adj) :
9396 + cpr3_parse_corner_array_property(vreg, prop_str,
9397 + 1, allow_core_count_adj);
9398 + if (rc) {
9399 + cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
9400 + rc);
9401 + goto done;
9402 + }
9403 + }
9404 +
9405 + if (vreg->allow_temp_adj) {
9406 + allow_temp_adj = kcalloc(vreg->corner_count,
9407 + sizeof(*allow_temp_adj), GFP_KERNEL);
9408 + if (!allow_temp_adj) {
9409 + rc = -ENOMEM;
9410 + goto done;
9411 + }
9412 +
9413 + snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ?
9414 + "qcom,corner-band-allow-temp-adjustment" :
9415 + "qcom,corner-allow-temp-adjustment");
9416 +
9417 + rc = use_corner_band ?
9418 + cpr3_parse_corner_band_array_property(vreg, prop_str,
9419 + 1, allow_temp_adj) :
9420 + cpr3_parse_corner_array_property(vreg, prop_str,
9421 + 1, allow_temp_adj);
9422 + if (rc) {
9423 + cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
9424 + rc);
9425 + goto done;
9426 + }
9427 + }
9428 +
9429 + sdelta_table_count = use_corner_band ? vreg->corner_band_count :
9430 + vreg->corner_count;
9431 +
9432 + for (i = 0; i < sdelta_table_count; i++) {
9433 + sdelta = devm_kzalloc(ctrl->dev, sizeof(*corner->sdelta),
9434 + GFP_KERNEL);
9435 + if (!sdelta) {
9436 + rc = -ENOMEM;
9437 + goto done;
9438 + }
9439 +
9440 + if (allow_core_count_adj)
9441 + sdelta->allow_core_count_adj = allow_core_count_adj[i];
9442 + if (allow_temp_adj)
9443 + sdelta->allow_temp_adj = allow_temp_adj[i];
9444 + sdelta->max_core_count = vreg->max_core_count;
9445 + sdelta->temp_band_count = ctrl->temp_band_count;
9446 +
9447 + if (use_corner_band)
9448 + vreg->corner_band[i].sdelta = sdelta;
9449 + else
9450 + vreg->corner[i].sdelta = sdelta;
9451 +
9452 + rc = cpr4_load_core_and_temp_adj(vreg, i, use_corner_band);
9453 + if (rc) {
9454 + cpr3_err(vreg, "corner/band %d core and temp adjustment loading failed, rc=%d\n",
9455 + i, rc);
9456 + goto done;
9457 + }
9458 + }
9459 +
9460 +done:
9461 + kfree(allow_core_count_adj);
9462 + kfree(allow_temp_adj);
9463 +
9464 + return rc;
9465 +}
9466 +
9467 +/**
9468 + * cprh_adjust_voltages_for_apm() - adjust per-corner floor and ceiling voltages
9469 + * so that they do not overlap the APM threshold voltage.
9470 + * @vreg: Pointer to the CPR3 regulator
9471 + *
9472 + * The memory array power mux (APM) must be configured for a specific supply
9473 + * based upon where the VDD voltage lies with respect to the APM threshold
9474 + * voltage. When using CPR hardware closed-loop, the voltage may vary anywhere
9475 + * between the floor and ceiling voltage without software notification.
9476 + * Therefore, it is required that the floor to ceiling range for every corner
9477 + * not intersect the APM threshold voltage. This function adjusts the floor to
9478 + * ceiling range for each corner which violates this requirement.
9479 + *
9480 + * The following algorithm is applied:
9481 + * if floor < threshold <= ceiling:
9482 + * if open_loop >= threshold, then floor = threshold - adj
9483 + * else ceiling = threshold - step
9484 + * where:
9485 + * adj = APM hysteresis voltage established to minimize the number of
9486 + * corners with artificially increased floor voltages
9487 + * step = voltage in microvolts of a single step of the VDD supply
9488 + *
9489 + * The open-loop voltage is also bounded by the new floor or ceiling value as
9490 + * needed.
9491 + *
9492 + * Return: none
9493 + */
9494 +void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg)
9495 +{
9496 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
9497 + struct cpr3_corner *corner;
9498 + int i, adj, threshold, prev_ceiling, prev_floor, prev_open_loop;
9499 +
9500 + if (!ctrl->apm_threshold_volt) {
9501 + /* APM not being used. */
9502 + return;
9503 + }
9504 +
9505 + ctrl->apm_threshold_volt = CPR3_ROUND(ctrl->apm_threshold_volt,
9506 + ctrl->step_volt);
9507 + ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
9508 +
9509 + threshold = ctrl->apm_threshold_volt;
9510 + adj = ctrl->apm_adj_volt;
9511 +
9512 + for (i = 0; i < vreg->corner_count; i++) {
9513 + corner = &vreg->corner[i];
9514 +
9515 + if (threshold <= corner->floor_volt
9516 + || threshold > corner->ceiling_volt)
9517 + continue;
9518 +
9519 + prev_floor = corner->floor_volt;
9520 + prev_ceiling = corner->ceiling_volt;
9521 + prev_open_loop = corner->open_loop_volt;
9522 +
9523 + if (corner->open_loop_volt >= threshold) {
9524 + corner->floor_volt = max(corner->floor_volt,
9525 + threshold - adj);
9526 + if (corner->open_loop_volt < corner->floor_volt)
9527 + corner->open_loop_volt = corner->floor_volt;
9528 + } else {
9529 + corner->ceiling_volt = threshold - ctrl->step_volt;
9530 + }
9531 +
9532 + if (corner->floor_volt != prev_floor
9533 + || corner->ceiling_volt != prev_ceiling
9534 + || corner->open_loop_volt != prev_open_loop)
9535 + 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",
9536 + threshold, adj, i, prev_floor, prev_ceiling,
9537 + prev_open_loop, corner->floor_volt,
9538 + corner->ceiling_volt, corner->open_loop_volt);
9539 + }
9540 +}
9541 +
9542 +/**
9543 + * cprh_adjust_voltages_for_mem_acc() - adjust per-corner floor and ceiling
9544 + * voltages so that they do not intersect the MEM ACC threshold
9545 + * voltage
9546 + * @vreg: Pointer to the CPR3 regulator
9547 + *
9548 + * The following algorithm is applied:
9549 + * if floor < threshold <= ceiling:
9550 + * if open_loop >= threshold, then floor = threshold
9551 + * else ceiling = threshold - step
9552 + * where:
9553 + * step = voltage in microvolts of a single step of the VDD supply
9554 + *
9555 + * The open-loop voltage is also bounded by the new floor or ceiling value as
9556 + * needed.
9557 + *
9558 + * Return: none
9559 + */
9560 +void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
9561 +{
9562 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
9563 + struct cpr3_corner *corner;
9564 + int i, threshold, prev_ceiling, prev_floor, prev_open_loop;
9565 +
9566 + if (!ctrl->mem_acc_threshold_volt) {
9567 + /* MEM ACC not being used. */
9568 + return;
9569 + }
9570 +
9571 + ctrl->mem_acc_threshold_volt = CPR3_ROUND(ctrl->mem_acc_threshold_volt,
9572 + ctrl->step_volt);
9573 +
9574 + threshold = ctrl->mem_acc_threshold_volt;
9575 +
9576 + for (i = 0; i < vreg->corner_count; i++) {
9577 + corner = &vreg->corner[i];
9578 +
9579 + if (threshold <= corner->floor_volt
9580 + || threshold > corner->ceiling_volt)
9581 + continue;
9582 +
9583 + prev_floor = corner->floor_volt;
9584 + prev_ceiling = corner->ceiling_volt;
9585 + prev_open_loop = corner->open_loop_volt;
9586 +
9587 + if (corner->open_loop_volt >= threshold) {
9588 + corner->floor_volt = max(corner->floor_volt, threshold);
9589 + if (corner->open_loop_volt < corner->floor_volt)
9590 + corner->open_loop_volt = corner->floor_volt;
9591 + } else {
9592 + corner->ceiling_volt = threshold - ctrl->step_volt;
9593 + }
9594 +
9595 + if (corner->floor_volt != prev_floor
9596 + || corner->ceiling_volt != prev_ceiling
9597 + || corner->open_loop_volt != prev_open_loop)
9598 + 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",
9599 + threshold, i, prev_floor, prev_ceiling,
9600 + prev_open_loop, corner->floor_volt,
9601 + corner->ceiling_volt, corner->open_loop_volt);
9602 + }
9603 +}
9604 +
9605 +/**
9606 + * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage
9607 + * adjustments by the amounts that are needed for this
9608 + * fuse combo
9609 + * @vreg: Pointer to the CPR3 regulator
9610 + * @volt_adjust: Array of closed-loop voltage adjustment values of length
9611 + * vreg->corner_count which is further adjusted based upon
9612 + * offset voltage fuse values.
9613 + * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
9614 + * vreg->fuse_corner_count.
9615 + *
9616 + * Return: 0 on success, errno on failure
9617 + */
9618 +static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg,
9619 + int *volt_adjust, int *fuse_volt_adjust)
9620 +{
9621 + u32 *corner_map;
9622 + int rc = 0, i;
9623 +
9624 + if (!of_find_property(vreg->of_node,
9625 + "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
9626 + /* No closed-loop offset required. */
9627 + return 0;
9628 + }
9629 +
9630 + corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
9631 + GFP_KERNEL);
9632 + if (!corner_map)
9633 + return -ENOMEM;
9634 +
9635 + rc = cpr3_parse_corner_array_property(vreg,
9636 + "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
9637 + 1, corner_map);
9638 + if (rc)
9639 + goto done;
9640 +
9641 + for (i = 0; i < vreg->corner_count; i++) {
9642 + if (corner_map[i] == 0) {
9643 + continue;
9644 + } else if (corner_map[i] > vreg->fuse_corner_count) {
9645 + cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
9646 + i, corner_map[i]);
9647 + rc = -EINVAL;
9648 + goto done;
9649 + }
9650 +
9651 + volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1];
9652 + }
9653 +
9654 +done:
9655 + kfree(corner_map);
9656 + return rc;
9657 +}
9658 +
9659 +/**
9660 + * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients
9661 + * increase monotonically from lower to higher corners
9662 + * @vreg: Pointer to the CPR3 regulator
9663 + *
9664 + * Return: 0 on success, errno on failure
9665 + */
9666 +static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg)
9667 +{
9668 + int i, j;
9669 +
9670 + for (i = 1; i < vreg->corner_count; i++) {
9671 + for (j = 0; j < CPR3_RO_COUNT; j++) {
9672 + if (vreg->corner[i].target_quot[j]
9673 + && vreg->corner[i].target_quot[j]
9674 + < vreg->corner[i - 1].target_quot[j]) {
9675 + 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",
9676 + i, j,
9677 + vreg->corner[i].target_quot[j],
9678 + i - 1, j,
9679 + vreg->corner[i - 1].target_quot[j],
9680 + i, j,
9681 + vreg->corner[i - 1].target_quot[j]);
9682 + vreg->corner[i].target_quot[j]
9683 + = vreg->corner[i - 1].target_quot[j];
9684 + }
9685 + }
9686 + }
9687 +}
9688 +
9689 +/**
9690 + * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients
9691 + * decrease monotonically from higher to lower corners
9692 + * @vreg: Pointer to the CPR3 regulator
9693 + *
9694 + * Return: 0 on success, errno on failure
9695 + */
9696 +static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg)
9697 +{
9698 + int i, j;
9699 +
9700 + for (i = vreg->corner_count - 2; i >= 0; i--) {
9701 + for (j = 0; j < CPR3_RO_COUNT; j++) {
9702 + if (vreg->corner[i + 1].target_quot[j]
9703 + && vreg->corner[i].target_quot[j]
9704 + > vreg->corner[i + 1].target_quot[j]) {
9705 + 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",
9706 + i, j,
9707 + vreg->corner[i].target_quot[j],
9708 + i + 1, j,
9709 + vreg->corner[i + 1].target_quot[j],
9710 + i, j,
9711 + vreg->corner[i + 1].target_quot[j]);
9712 + vreg->corner[i].target_quot[j]
9713 + = vreg->corner[i + 1].target_quot[j];
9714 + }
9715 + }
9716 + }
9717 +}
9718 +
9719 +/**
9720 + * _cpr3_adjust_target_quotients() - adjust the target quotients for each
9721 + * corner of the regulator according to input adjustment and
9722 + * scaling arrays
9723 + * @vreg: Pointer to the CPR3 regulator
9724 + * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
9725 + * with units of microvolts. The array must have
9726 + * vreg->corner_count number of elements.
9727 + * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
9728 + * The array must have an inner dimension of CPR3_RO_COUNT
9729 + * and an outer dimension of vreg->corner_count
9730 + * @label: Null terminated string providing a label for the type
9731 + * of adjustment.
9732 + *
9733 + * Return: true if any corners received a positive voltage adjustment (> 0),
9734 + * else false
9735 + */
9736 +static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
9737 + const int *volt_adjust, const int *ro_scale, const char *label)
9738 +{
9739 + int i, j, quot_adjust;
9740 + bool is_increasing = false;
9741 + u32 prev_quot;
9742 +
9743 + for (i = 0; i < vreg->corner_count; i++) {
9744 + for (j = 0; j < CPR3_RO_COUNT; j++) {
9745 + if (vreg->corner[i].target_quot[j]) {
9746 + quot_adjust = cpr3_quot_adjustment(
9747 + ro_scale[i * CPR3_RO_COUNT + j],
9748 + volt_adjust[i]);
9749 + if (quot_adjust) {
9750 + prev_quot = vreg->corner[i].
9751 + target_quot[j];
9752 + vreg->corner[i].target_quot[j]
9753 + += quot_adjust;
9754 + cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
9755 + i, j, label, prev_quot,
9756 + vreg->corner[i].target_quot[j],
9757 + volt_adjust[i]);
9758 + }
9759 + }
9760 + }
9761 + if (volt_adjust[i] > 0)
9762 + is_increasing = true;
9763 + }
9764 +
9765 + return is_increasing;
9766 +}
9767 +
9768 +/**
9769 + * cpr3_adjust_target_quotients() - adjust the target quotients for each
9770 + * corner according to device tree values and fuse values
9771 + * @vreg: Pointer to the CPR3 regulator
9772 + * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
9773 + * vreg->fuse_corner_count. This parameter could be null
9774 + * pointer when no fused adjustments are needed.
9775 + *
9776 + * Return: 0 on success, errno on failure
9777 + */
9778 +int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
9779 + int *fuse_volt_adjust)
9780 +{
9781 + int i, rc;
9782 + int *volt_adjust, *ro_scale;
9783 + bool explicit_adjustment, fused_adjustment, is_increasing;
9784 +
9785 + explicit_adjustment = of_find_property(vreg->of_node,
9786 + "qcom,cpr-closed-loop-voltage-adjustment", NULL);
9787 + fused_adjustment = of_find_property(vreg->of_node,
9788 + "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
9789 +
9790 + if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
9791 + /* No adjustment required. */
9792 + return 0;
9793 + } else if (!of_find_property(vreg->of_node,
9794 + "qcom,cpr-ro-scaling-factor", NULL)) {
9795 + cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
9796 + return -EINVAL;
9797 + }
9798 +
9799 + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
9800 + GFP_KERNEL);
9801 + ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
9802 + sizeof(*ro_scale), GFP_KERNEL);
9803 + if (!volt_adjust || !ro_scale) {
9804 + rc = -ENOMEM;
9805 + goto done;
9806 + }
9807 +
9808 + rc = cpr3_parse_corner_array_property(vreg,
9809 + "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
9810 + if (rc) {
9811 + cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
9812 + rc);
9813 + goto done;
9814 + }
9815 +
9816 + for (i = 0; i < vreg->corner_count; i++)
9817 + memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
9818 + sizeof(*ro_scale) * CPR3_RO_COUNT);
9819 +
9820 + if (explicit_adjustment) {
9821 + rc = cpr3_parse_corner_array_property(vreg,
9822 + "qcom,cpr-closed-loop-voltage-adjustment",
9823 + 1, volt_adjust);
9824 + if (rc) {
9825 + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
9826 + rc);
9827 + goto done;
9828 + }
9829 +
9830 + _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale,
9831 + "from DT");
9832 + cpr3_enforce_inc_quotient_monotonicity(vreg);
9833 + }
9834 +
9835 + if (fused_adjustment && fuse_volt_adjust) {
9836 + memset(volt_adjust, 0,
9837 + sizeof(*volt_adjust) * vreg->corner_count);
9838 +
9839 + rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust,
9840 + fuse_volt_adjust);
9841 + if (rc) {
9842 + cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
9843 + rc);
9844 + goto done;
9845 + }
9846 +
9847 + is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust,
9848 + ro_scale, "from fuse");
9849 + if (is_increasing)
9850 + cpr3_enforce_inc_quotient_monotonicity(vreg);
9851 + else
9852 + cpr3_enforce_dec_quotient_monotonicity(vreg);
9853 + }
9854 +
9855 +done:
9856 + kfree(volt_adjust);
9857 + kfree(ro_scale);
9858 + return rc;
9859 +}
9860 --- /dev/null
9861 +++ b/drivers/regulator/cpr4-apss-regulator.c
9862 @@ -0,0 +1,1819 @@
9863 +/*
9864 + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
9865 + *
9866 + * This program is free software; you can redistribute it and/or modify
9867 + * it under the terms of the GNU General Public License version 2 and
9868 + * only version 2 as published by the Free Software Foundation.
9869 + *
9870 + * This program is distributed in the hope that it will be useful,
9871 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9872 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9873 + * GNU General Public License for more details.
9874 + */
9875 +
9876 +#define pr_fmt(fmt) "%s: " fmt, __func__
9877 +
9878 +#include <linux/bitops.h>
9879 +#include <linux/debugfs.h>
9880 +#include <linux/err.h>
9881 +#include <linux/init.h>
9882 +#include <linux/interrupt.h>
9883 +#include <linux/io.h>
9884 +#include <linux/kernel.h>
9885 +#include <linux/list.h>
9886 +#include <linux/module.h>
9887 +#include <linux/of.h>
9888 +#include <linux/of_device.h>
9889 +#include <linux/platform_device.h>
9890 +#include <linux/pm_opp.h>
9891 +#include <linux/slab.h>
9892 +#include <linux/string.h>
9893 +#include <linux/uaccess.h>
9894 +#include <linux/regulator/driver.h>
9895 +#include <linux/regulator/machine.h>
9896 +#include <linux/regulator/of_regulator.h>
9897 +
9898 +#include "cpr3-regulator.h"
9899 +
9900 +#define IPQ807x_APSS_FUSE_CORNERS 4
9901 +#define IPQ817x_APPS_FUSE_CORNERS 2
9902 +#define IPQ6018_APSS_FUSE_CORNERS 4
9903 +#define IPQ9574_APSS_FUSE_CORNERS 4
9904 +
9905 +u32 g_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS;
9906 +
9907 +/**
9908 + * struct cpr4_ipq807x_apss_fuses - APSS specific fuse data for IPQ807x
9909 + * @ro_sel: Ring oscillator select fuse parameter value for each
9910 + * fuse corner
9911 + * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value
9912 + * for each fuse corner (raw, not converted to a voltage)
9913 + * @target_quot: CPR target quotient fuse parameter value for each fuse
9914 + * corner
9915 + * @quot_offset: CPR target quotient offset fuse parameter value for each
9916 + * fuse corner (raw, not unpacked) used for target quotient
9917 + * interpolation
9918 + * @speed_bin: Application processor speed bin fuse parameter value for
9919 + * the given chip
9920 + * @cpr_fusing_rev: CPR fusing revision fuse parameter value
9921 + * @boost_cfg: CPR boost configuration fuse parameter value
9922 + * @boost_voltage: CPR boost voltage fuse parameter value (raw, not
9923 + * converted to a voltage)
9924 + *
9925 + * This struct holds the values for all of the fuses read from memory.
9926 + */
9927 +struct cpr4_ipq807x_apss_fuses {
9928 + u64 ro_sel[IPQ807x_APSS_FUSE_CORNERS];
9929 + u64 init_voltage[IPQ807x_APSS_FUSE_CORNERS];
9930 + u64 target_quot[IPQ807x_APSS_FUSE_CORNERS];
9931 + u64 quot_offset[IPQ807x_APSS_FUSE_CORNERS];
9932 + u64 speed_bin;
9933 + u64 cpr_fusing_rev;
9934 + u64 boost_cfg;
9935 + u64 boost_voltage;
9936 + u64 misc;
9937 +};
9938 +
9939 +/*
9940 + * fuse combo = fusing revision + 8 * (speed bin)
9941 + * where: fusing revision = 0 - 7 and speed bin = 0 - 7
9942 + */
9943 +#define CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT 64
9944 +
9945 +/*
9946 + * Constants which define the name of each fuse corner.
9947 + */
9948 +enum cpr4_ipq807x_apss_fuse_corner {
9949 + CPR4_IPQ807x_APSS_FUSE_CORNER_SVS = 0,
9950 + CPR4_IPQ807x_APSS_FUSE_CORNER_NOM = 1,
9951 + CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO = 2,
9952 + CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO = 3,
9953 +};
9954 +
9955 +static const char * const cpr4_ipq807x_apss_fuse_corner_name[] = {
9956 + [CPR4_IPQ807x_APSS_FUSE_CORNER_SVS] = "SVS",
9957 + [CPR4_IPQ807x_APSS_FUSE_CORNER_NOM] = "NOM",
9958 + [CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO] = "TURBO",
9959 + [CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO] = "STURBO",
9960 +};
9961 +
9962 +/*
9963 + * IPQ807x APSS fuse parameter locations:
9964 + *
9965 + * Structs are organized with the following dimensions:
9966 + * Outer: 0 to 3 for fuse corners from lowest to highest corner
9967 + * Inner: large enough to hold the longest set of parameter segments which
9968 + * fully defines a fuse parameter, +1 (for NULL termination).
9969 + * Each segment corresponds to a contiguous group of bits from a
9970 + * single fuse row. These segments are concatentated together in
9971 + * order to form the full fuse parameter value. The segments for
9972 + * a given parameter may correspond to different fuse rows.
9973 + */
9974 +static struct cpr3_fuse_param
9975 +ipq807x_apss_ro_sel_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
9976 + {{73, 8, 11}, {} },
9977 + {{73, 4, 7}, {} },
9978 + {{73, 0, 3}, {} },
9979 + {{73, 12, 15}, {} },
9980 +};
9981 +
9982 +static struct cpr3_fuse_param
9983 +ipq807x_apss_init_voltage_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
9984 + {{71, 18, 23}, {} },
9985 + {{71, 12, 17}, {} },
9986 + {{71, 6, 11}, {} },
9987 + {{71, 0, 5}, {} },
9988 +};
9989 +
9990 +static struct cpr3_fuse_param
9991 +ipq807x_apss_target_quot_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
9992 + {{72, 32, 43}, {} },
9993 + {{72, 20, 31}, {} },
9994 + {{72, 8, 19}, {} },
9995 + {{72, 44, 55}, {} },
9996 +};
9997 +
9998 +static struct cpr3_fuse_param
9999 +ipq807x_apss_quot_offset_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
10000 + {{} },
10001 + {{71, 46, 52}, {} },
10002 + {{71, 39, 45}, {} },
10003 + {{71, 32, 38}, {} },
10004 +};
10005 +
10006 +static struct cpr3_fuse_param ipq807x_cpr_fusing_rev_param[] = {
10007 + {71, 53, 55},
10008 + {},
10009 +};
10010 +
10011 +static struct cpr3_fuse_param ipq807x_apss_speed_bin_param[] = {
10012 + {36, 40, 42},
10013 + {},
10014 +};
10015 +
10016 +static struct cpr3_fuse_param ipq807x_cpr_boost_fuse_cfg_param[] = {
10017 + {36, 43, 45},
10018 + {},
10019 +};
10020 +
10021 +static struct cpr3_fuse_param ipq807x_apss_boost_fuse_volt_param[] = {
10022 + {71, 0, 5},
10023 + {},
10024 +};
10025 +
10026 +static struct cpr3_fuse_param ipq807x_misc_fuse_volt_adj_param[] = {
10027 + {36, 54, 54},
10028 + {},
10029 +};
10030 +
10031 +static struct cpr3_fuse_parameters ipq807x_fuse_params = {
10032 + .apss_ro_sel_param = ipq807x_apss_ro_sel_param,
10033 + .apss_init_voltage_param = ipq807x_apss_init_voltage_param,
10034 + .apss_target_quot_param = ipq807x_apss_target_quot_param,
10035 + .apss_quot_offset_param = ipq807x_apss_quot_offset_param,
10036 + .cpr_fusing_rev_param = ipq807x_cpr_fusing_rev_param,
10037 + .apss_speed_bin_param = ipq807x_apss_speed_bin_param,
10038 + .cpr_boost_fuse_cfg_param = ipq807x_cpr_boost_fuse_cfg_param,
10039 + .apss_boost_fuse_volt_param = ipq807x_apss_boost_fuse_volt_param,
10040 + .misc_fuse_volt_adj_param = ipq807x_misc_fuse_volt_adj_param
10041 +};
10042 +
10043 +/*
10044 + * The number of possible values for misc fuse is
10045 + * 2^(#bits defined for misc fuse)
10046 + */
10047 +#define IPQ807x_MISC_FUSE_VAL_COUNT BIT(1)
10048 +
10049 +/*
10050 + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
10051 + */
10052 +static int ipq807x_apss_fuse_ref_volt
10053 + [IPQ807x_APSS_FUSE_CORNERS] = {
10054 + 720000,
10055 + 864000,
10056 + 992000,
10057 + 1064000,
10058 +};
10059 +
10060 +#define IPQ807x_APSS_FUSE_STEP_VOLT 8000
10061 +#define IPQ807x_APSS_VOLTAGE_FUSE_SIZE 6
10062 +#define IPQ807x_APSS_QUOT_OFFSET_SCALE 5
10063 +
10064 +#define IPQ807x_APSS_CPR_SENSOR_COUNT 6
10065 +
10066 +#define IPQ807x_APSS_CPR_CLOCK_RATE 19200000
10067 +
10068 +#define IPQ807x_APSS_MAX_TEMP_POINTS 3
10069 +#define IPQ807x_APSS_TEMP_SENSOR_ID_START 4
10070 +#define IPQ807x_APSS_TEMP_SENSOR_ID_END 13
10071 +/*
10072 + * Boost voltage fuse reference and ceiling voltages in microvolts for
10073 + * IPQ807x.
10074 + */
10075 +#define IPQ807x_APSS_BOOST_FUSE_REF_VOLT 1140000
10076 +#define IPQ807x_APSS_BOOST_CEILING_VOLT 1140000
10077 +#define IPQ807x_APSS_BOOST_FLOOR_VOLT 900000
10078 +#define MAX_BOOST_CONFIG_FUSE_VALUE 8
10079 +
10080 +#define IPQ807x_APSS_CPR_SDELTA_CORE_COUNT 15
10081 +
10082 +#define IPQ807x_APSS_CPR_TCSR_START 8
10083 +#define IPQ807x_APSS_CPR_TCSR_END 9
10084 +
10085 +/*
10086 + * Array of integer values mapped to each of the boost config fuse values to
10087 + * indicate boost enable/disable status.
10088 + */
10089 +static bool boost_fuse[MAX_BOOST_CONFIG_FUSE_VALUE] = {0, 1, 1, 1, 1, 1, 1, 1};
10090 +
10091 +/*
10092 + * IPQ6018 (Few parameters are changed, remaining are same as IPQ807x)
10093 + */
10094 +#define IPQ6018_APSS_FUSE_STEP_VOLT 12500
10095 +#define IPQ6018_APSS_CPR_CLOCK_RATE 24000000
10096 +
10097 +static struct cpr3_fuse_param
10098 +ipq6018_apss_ro_sel_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
10099 + {{75, 8, 11}, {} },
10100 + {{75, 4, 7}, {} },
10101 + {{75, 0, 3}, {} },
10102 + {{75, 12, 15}, {} },
10103 +};
10104 +
10105 +static struct cpr3_fuse_param
10106 +ipq6018_apss_init_voltage_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
10107 + {{73, 18, 23}, {} },
10108 + {{73, 12, 17}, {} },
10109 + {{73, 6, 11}, {} },
10110 + {{73, 0, 5}, {} },
10111 +};
10112 +
10113 +static struct cpr3_fuse_param
10114 +ipq6018_apss_target_quot_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
10115 + {{74, 32, 43}, {} },
10116 + {{74, 20, 31}, {} },
10117 + {{74, 8, 19}, {} },
10118 + {{74, 44, 55}, {} },
10119 +};
10120 +
10121 +static struct cpr3_fuse_param
10122 +ipq6018_apss_quot_offset_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
10123 + {{} },
10124 + {{73, 48, 55}, {} },
10125 + {{73, 40, 47}, {} },
10126 + {{73, 32, 39}, {} },
10127 +};
10128 +
10129 +static struct cpr3_fuse_param ipq6018_cpr_fusing_rev_param[] = {
10130 + {75, 16, 18},
10131 + {},
10132 +};
10133 +
10134 +static struct cpr3_fuse_param ipq6018_apss_speed_bin_param[] = {
10135 + {36, 40, 42},
10136 + {},
10137 +};
10138 +
10139 +static struct cpr3_fuse_param ipq6018_cpr_boost_fuse_cfg_param[] = {
10140 + {36, 43, 45},
10141 + {},
10142 +};
10143 +
10144 +static struct cpr3_fuse_param ipq6018_apss_boost_fuse_volt_param[] = {
10145 + {73, 0, 5},
10146 + {},
10147 +};
10148 +
10149 +static struct cpr3_fuse_param ipq6018_misc_fuse_volt_adj_param[] = {
10150 + {36, 54, 54},
10151 + {},
10152 +};
10153 +
10154 +static struct cpr3_fuse_parameters ipq6018_fuse_params = {
10155 + .apss_ro_sel_param = ipq6018_apss_ro_sel_param,
10156 + .apss_init_voltage_param = ipq6018_apss_init_voltage_param,
10157 + .apss_target_quot_param = ipq6018_apss_target_quot_param,
10158 + .apss_quot_offset_param = ipq6018_apss_quot_offset_param,
10159 + .cpr_fusing_rev_param = ipq6018_cpr_fusing_rev_param,
10160 + .apss_speed_bin_param = ipq6018_apss_speed_bin_param,
10161 + .cpr_boost_fuse_cfg_param = ipq6018_cpr_boost_fuse_cfg_param,
10162 + .apss_boost_fuse_volt_param = ipq6018_apss_boost_fuse_volt_param,
10163 + .misc_fuse_volt_adj_param = ipq6018_misc_fuse_volt_adj_param
10164 +};
10165 +
10166 +
10167 +/*
10168 + * Boost voltage fuse reference and ceiling voltages in microvolts for
10169 + * IPQ6018.
10170 + */
10171 +#define IPQ6018_APSS_BOOST_FUSE_REF_VOLT 1140000
10172 +#define IPQ6018_APSS_BOOST_CEILING_VOLT 1140000
10173 +#define IPQ6018_APSS_BOOST_FLOOR_VOLT 900000
10174 +
10175 +/*
10176 + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
10177 + */
10178 +static int ipq6018_apss_fuse_ref_volt
10179 + [IPQ6018_APSS_FUSE_CORNERS] = {
10180 + 725000,
10181 + 862500,
10182 + 987500,
10183 + 1062500,
10184 +};
10185 +
10186 +/*
10187 + * IPQ6018 Memory ACC settings on TCSR
10188 + *
10189 + * Turbo_L1: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x10
10190 + * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x1
10191 + * Other modes: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x0
10192 + * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x0
10193 + *
10194 + */
10195 +#define IPQ6018_APSS_MEM_ACC_TCSR_COUNT 2
10196 +#define TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x1946178
10197 +#define TCSR_CUSTOM_VDDAPC0_ACC_1 0x1946124
10198 +
10199 +struct mem_acc_tcsr {
10200 + u32 phy_addr;
10201 + void __iomem *ioremap_addr;
10202 + u32 value;
10203 +};
10204 +
10205 +static struct mem_acc_tcsr ipq6018_mem_acc_tcsr[IPQ6018_APSS_MEM_ACC_TCSR_COUNT] = {
10206 + {TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0, NULL, 0x10},
10207 + {TCSR_CUSTOM_VDDAPC0_ACC_1, NULL, 0x1},
10208 +};
10209 +
10210 +/*
10211 + * IPQ9574 (Few parameters are changed, remaining are same as IPQ6018)
10212 + */
10213 +#define IPQ9574_APSS_FUSE_STEP_VOLT 10000
10214 +
10215 +static struct cpr3_fuse_param
10216 +ipq9574_apss_ro_sel_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
10217 + {{107, 4, 7}, {} },
10218 + {{107, 0, 3}, {} },
10219 + {{106, 4, 7}, {} },
10220 + {{106, 0, 3}, {} },
10221 +};
10222 +
10223 +static struct cpr3_fuse_param
10224 +ipq9574_apss_init_voltage_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
10225 + {{104, 24, 29}, {} },
10226 + {{104, 18, 23}, {} },
10227 + {{104, 12, 17}, {} },
10228 + {{104, 6, 11}, {} },
10229 +};
10230 +
10231 +static struct cpr3_fuse_param
10232 +ipq9574_apss_target_quot_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
10233 + {{106, 32, 43}, {} },
10234 + {{106, 20, 31}, {} },
10235 + {{106, 8, 19}, {} },
10236 + {{106, 44, 55}, {} },
10237 +};
10238 +
10239 +static struct cpr3_fuse_param
10240 +ipq9574_apss_quot_offset_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
10241 + {{} },
10242 + {{105, 48, 55}, {} },
10243 + {{105, 40, 47}, {} },
10244 + {{105, 32, 39}, {} },
10245 +};
10246 +
10247 +static struct cpr3_fuse_param ipq9574_cpr_fusing_rev_param[] = {
10248 + {107, 8, 10},
10249 + {},
10250 +};
10251 +
10252 +static struct cpr3_fuse_param ipq9574_apss_speed_bin_param[] = {
10253 + {0, 40, 42},
10254 + {},
10255 +};
10256 +
10257 +static struct cpr3_fuse_param ipq9574_cpr_boost_fuse_cfg_param[] = {
10258 + {0, 43, 45},
10259 + {},
10260 +};
10261 +
10262 +static struct cpr3_fuse_param ipq9574_apss_boost_fuse_volt_param[] = {
10263 + {104, 0, 5},
10264 + {},
10265 +};
10266 +
10267 +static struct cpr3_fuse_param ipq9574_misc_fuse_volt_adj_param[] = {
10268 + {0, 54, 54},
10269 + {},
10270 +};
10271 +
10272 +static struct cpr3_fuse_parameters ipq9574_fuse_params = {
10273 + .apss_ro_sel_param = ipq9574_apss_ro_sel_param,
10274 + .apss_init_voltage_param = ipq9574_apss_init_voltage_param,
10275 + .apss_target_quot_param = ipq9574_apss_target_quot_param,
10276 + .apss_quot_offset_param = ipq9574_apss_quot_offset_param,
10277 + .cpr_fusing_rev_param = ipq9574_cpr_fusing_rev_param,
10278 + .apss_speed_bin_param = ipq9574_apss_speed_bin_param,
10279 + .cpr_boost_fuse_cfg_param = ipq9574_cpr_boost_fuse_cfg_param,
10280 + .apss_boost_fuse_volt_param = ipq9574_apss_boost_fuse_volt_param,
10281 + .misc_fuse_volt_adj_param = ipq9574_misc_fuse_volt_adj_param
10282 +};
10283 +
10284 +/*
10285 + * Open loop voltage fuse reference voltages in microvolts for IPQ9574
10286 + */
10287 +static int ipq9574_apss_fuse_ref_volt
10288 + [IPQ9574_APSS_FUSE_CORNERS] = {
10289 + 725000,
10290 + 862500,
10291 + 987500,
10292 + 1062500,
10293 +};
10294 +
10295 +/**
10296 + * cpr4_ipq807x_apss_read_fuse_data() - load APSS specific fuse parameter values
10297 + * @vreg: Pointer to the CPR3 regulator
10298 + *
10299 + * This function allocates a cpr4_ipq807x_apss_fuses struct, fills it with
10300 + * values read out of hardware fuses, and finally copies common fuse values
10301 + * into the CPR3 regulator struct.
10302 + *
10303 + * Return: 0 on success, errno on failure
10304 + */
10305 +static int cpr4_ipq807x_apss_read_fuse_data(struct cpr3_regulator *vreg)
10306 +{
10307 + void __iomem *base = vreg->thread->ctrl->fuse_base;
10308 + struct cpr4_ipq807x_apss_fuses *fuse;
10309 + int i, rc;
10310 +
10311 + fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL);
10312 + if (!fuse)
10313 + return -ENOMEM;
10314 +
10315 + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->apss_speed_bin_param,
10316 + &fuse->speed_bin);
10317 + if (rc) {
10318 + cpr3_err(vreg, "Unable to read speed bin fuse, rc=%d\n", rc);
10319 + return rc;
10320 + }
10321 + cpr3_info(vreg, "speed bin = %llu\n", fuse->speed_bin);
10322 +
10323 + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_fusing_rev_param,
10324 + &fuse->cpr_fusing_rev);
10325 + if (rc) {
10326 + cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n",
10327 + rc);
10328 + return rc;
10329 + }
10330 + cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev);
10331 +
10332 + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->misc_fuse_volt_adj_param,
10333 + &fuse->misc);
10334 + if (rc) {
10335 + cpr3_err(vreg, "Unable to read misc voltage adjustment fuse, rc=%d\n",
10336 + rc);
10337 + return rc;
10338 + }
10339 + cpr3_info(vreg, "CPR misc fuse value = %llu\n", fuse->misc);
10340 + if (fuse->misc >= IPQ807x_MISC_FUSE_VAL_COUNT) {
10341 + cpr3_err(vreg, "CPR misc fuse value = %llu, should be < %lu\n",
10342 + fuse->misc, IPQ807x_MISC_FUSE_VAL_COUNT);
10343 + return -EINVAL;
10344 + }
10345 +
10346 + for (i = 0; i < g_valid_fuse_count; i++) {
10347 + rc = cpr3_read_fuse_param(base,
10348 + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_init_voltage_param[i],
10349 + &fuse->init_voltage[i]);
10350 + if (rc) {
10351 + cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n",
10352 + i, rc);
10353 + return rc;
10354 + }
10355 +
10356 + rc = cpr3_read_fuse_param(base,
10357 + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_target_quot_param[i],
10358 + &fuse->target_quot[i]);
10359 + if (rc) {
10360 + cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n",
10361 + i, rc);
10362 + return rc;
10363 + }
10364 +
10365 + rc = cpr3_read_fuse_param(base,
10366 + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_ro_sel_param[i],
10367 + &fuse->ro_sel[i]);
10368 + if (rc) {
10369 + cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n",
10370 + i, rc);
10371 + return rc;
10372 + }
10373 +
10374 + rc = cpr3_read_fuse_param(base,
10375 + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_quot_offset_param[i],
10376 + &fuse->quot_offset[i]);
10377 + if (rc) {
10378 + cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n",
10379 + i, rc);
10380 + return rc;
10381 + }
10382 + }
10383 +
10384 + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_boost_fuse_cfg_param,
10385 + &fuse->boost_cfg);
10386 + if (rc) {
10387 + cpr3_err(vreg, "Unable to read CPR boost config fuse, rc=%d\n",
10388 + rc);
10389 + return rc;
10390 + }
10391 + cpr3_info(vreg, "Voltage boost fuse config = %llu boost = %s\n",
10392 + fuse->boost_cfg, boost_fuse[fuse->boost_cfg]
10393 + ? "enable" : "disable");
10394 +
10395 + rc = cpr3_read_fuse_param(base,
10396 + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_boost_fuse_volt_param,
10397 + &fuse->boost_voltage);
10398 + if (rc) {
10399 + cpr3_err(vreg, "failed to read boost fuse voltage, rc=%d\n",
10400 + rc);
10401 + return rc;
10402 + }
10403 +
10404 + vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin;
10405 + if (vreg->fuse_combo >= CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT) {
10406 + cpr3_err(vreg, "invalid CPR fuse combo = %d found\n",
10407 + vreg->fuse_combo);
10408 + return -EINVAL;
10409 + }
10410 +
10411 + vreg->speed_bin_fuse = fuse->speed_bin;
10412 + vreg->cpr_rev_fuse = fuse->cpr_fusing_rev;
10413 + vreg->fuse_corner_count = g_valid_fuse_count;
10414 + vreg->platform_fuses = fuse;
10415 +
10416 + return 0;
10417 +}
10418 +
10419 +/**
10420 + * cpr4_apss_parse_corner_data() - parse APSS corner data from device tree
10421 + * properties of the CPR3 regulator's device node
10422 + * @vreg: Pointer to the CPR3 regulator
10423 + *
10424 + * Return: 0 on success, errno on failure
10425 + */
10426 +static int cpr4_apss_parse_corner_data(struct cpr3_regulator *vreg)
10427 +{
10428 + struct device_node *node = vreg->of_node;
10429 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
10430 + u32 *temp = NULL;
10431 + int i, rc;
10432 +
10433 + rc = cpr3_parse_common_corner_data(vreg);
10434 + if (rc) {
10435 + cpr3_err(vreg, "error reading corner data, rc=%d\n", rc);
10436 + return rc;
10437 + }
10438 +
10439 + /* If fuse has incorrect RO Select values and dtsi has "qcom,cpr-ro-sel"
10440 + * entry with RO select values other than zero, then dtsi values will
10441 + * be used.
10442 + */
10443 + if (of_find_property(node, "qcom,cpr-ro-sel", NULL)) {
10444 + temp = kcalloc(vreg->fuse_corner_count, sizeof(*temp),
10445 + GFP_KERNEL);
10446 + if (!temp)
10447 + return -ENOMEM;
10448 +
10449 + rc = cpr3_parse_array_property(vreg, "qcom,cpr-ro-sel",
10450 + vreg->fuse_corner_count, temp);
10451 + if (rc)
10452 + goto done;
10453 +
10454 + for (i = 0; i < vreg->fuse_corner_count; i++) {
10455 + if (temp[i] != 0)
10456 + fuse->ro_sel[i] = temp[i];
10457 + }
10458 + }
10459 +done:
10460 + kfree(temp);
10461 + return rc;
10462 +}
10463 +
10464 +/**
10465 + * cpr4_apss_parse_misc_fuse_voltage_adjustments() - fill an array from a
10466 + * portion of the voltage adjustments specified based on
10467 + * miscellaneous fuse bits.
10468 + * @vreg: Pointer to the CPR3 regulator
10469 + * @volt_adjust: Voltage adjustment output data array which must be
10470 + * of size vreg->corner_count
10471 + *
10472 + * cpr3_parse_common_corner_data() must be called for vreg before this function
10473 + * is called so that speed bin size elements are initialized.
10474 + *
10475 + * Two formats are supported for the device tree property:
10476 + * 1. Length == tuple_list_size * vreg->corner_count
10477 + * (reading begins at index 0)
10478 + * 2. Length == tuple_list_size * vreg->speed_bin_corner_sum
10479 + * (reading begins at index tuple_list_size * vreg->speed_bin_offset)
10480 + *
10481 + * Here, tuple_list_size is the number of possible values for misc fuse.
10482 + * All other property lengths are treated as errors.
10483 + *
10484 + * Return: 0 on success, errno on failure
10485 + */
10486 +static int cpr4_apss_parse_misc_fuse_voltage_adjustments(
10487 + struct cpr3_regulator *vreg, u32 *volt_adjust)
10488 +{
10489 + struct device_node *node = vreg->of_node;
10490 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
10491 + int tuple_list_size = IPQ807x_MISC_FUSE_VAL_COUNT;
10492 + int i, offset, rc, len = 0;
10493 + const char *prop_name = "qcom,cpr-misc-fuse-voltage-adjustment";
10494 +
10495 + if (!of_find_property(node, prop_name, &len)) {
10496 + cpr3_err(vreg, "property %s is missing\n", prop_name);
10497 + return -EINVAL;
10498 + }
10499 +
10500 + if (len == tuple_list_size * vreg->corner_count * sizeof(u32)) {
10501 + offset = 0;
10502 + } else if (vreg->speed_bin_corner_sum > 0 &&
10503 + len == tuple_list_size * vreg->speed_bin_corner_sum
10504 + * sizeof(u32)) {
10505 + offset = tuple_list_size * vreg->speed_bin_offset
10506 + + fuse->misc * vreg->corner_count;
10507 + } else {
10508 + if (vreg->speed_bin_corner_sum > 0)
10509 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
10510 + prop_name, len,
10511 + tuple_list_size * vreg->corner_count
10512 + * sizeof(u32),
10513 + tuple_list_size * vreg->speed_bin_corner_sum
10514 + * sizeof(u32));
10515 + else
10516 + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu\n",
10517 + prop_name, len,
10518 + tuple_list_size * vreg->corner_count
10519 + * sizeof(u32));
10520 + return -EINVAL;
10521 + }
10522 +
10523 + for (i = 0; i < vreg->corner_count; i++) {
10524 + rc = of_property_read_u32_index(node, prop_name, offset + i,
10525 + &volt_adjust[i]);
10526 + if (rc) {
10527 + cpr3_err(vreg, "error reading property %s, rc=%d\n",
10528 + prop_name, rc);
10529 + return rc;
10530 + }
10531 + }
10532 +
10533 + return 0;
10534 +}
10535 +
10536 +/**
10537 + * cpr4_ipq807x_apss_calculate_open_loop_voltages() - calculate the open-loop
10538 + * voltage for each corner of a CPR3 regulator
10539 + * @vreg: Pointer to the CPR3 regulator
10540 + *
10541 + * If open-loop voltage interpolation is allowed in device tree, then
10542 + * this function calculates the open-loop voltage for a given corner using
10543 + * linear interpolation. This interpolation is performed using the processor
10544 + * frequencies of the lower and higher Fmax corners along with their fused
10545 + * open-loop voltages.
10546 + *
10547 + * If open-loop voltage interpolation is not allowed, then this function uses
10548 + * the Fmax fused open-loop voltage for all of the corners associated with a
10549 + * given fuse corner.
10550 + *
10551 + * Return: 0 on success, errno on failure
10552 + */
10553 +static int cpr4_ipq807x_apss_calculate_open_loop_voltages(
10554 + struct cpr3_regulator *vreg)
10555 +{
10556 + struct device_node *node = vreg->of_node;
10557 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
10558 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
10559 + int i, j, rc = 0;
10560 + bool allow_interpolation;
10561 + u64 freq_low, volt_low, freq_high, volt_high;
10562 + int *fuse_volt, *misc_adj_volt;
10563 + int *fmax_corner;
10564 +
10565 + fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt),
10566 + GFP_KERNEL);
10567 + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
10568 + GFP_KERNEL);
10569 + if (!fuse_volt || !fmax_corner) {
10570 + rc = -ENOMEM;
10571 + goto done;
10572 + }
10573 +
10574 + for (i = 0; i < vreg->fuse_corner_count; i++) {
10575 + if (ctrl->cpr_global_setting == CPR_DISABLED)
10576 + fuse_volt[i] = vreg->cpr4_regulator_data->fuse_ref_volt[i];
10577 + else
10578 + fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(
10579 + vreg->cpr4_regulator_data->fuse_ref_volt[i],
10580 + vreg->cpr4_regulator_data->fuse_step_volt,
10581 + fuse->init_voltage[i],
10582 + IPQ807x_APSS_VOLTAGE_FUSE_SIZE);
10583 +
10584 + /* Log fused open-loop voltage values for debugging purposes. */
10585 + cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n",
10586 + cpr4_ipq807x_apss_fuse_corner_name[i],
10587 + fuse_volt[i]);
10588 + }
10589 +
10590 + rc = cpr3_determine_part_type(vreg,
10591 + fuse_volt[vreg->fuse_corner_count - 1]);
10592 + if (rc) {
10593 + cpr3_err(vreg, "fused part type detection failed failed, rc=%d\n",
10594 + rc);
10595 + goto done;
10596 + }
10597 +
10598 + rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt);
10599 + if (rc) {
10600 + cpr3_err(vreg, "fused open-loop voltage adjustment failed, rc=%d\n",
10601 + rc);
10602 + goto done;
10603 + }
10604 +
10605 + allow_interpolation = of_property_read_bool(node,
10606 + "qcom,allow-voltage-interpolation");
10607 +
10608 + for (i = 1; i < vreg->fuse_corner_count; i++) {
10609 + if (fuse_volt[i] < fuse_volt[i - 1]) {
10610 + cpr3_info(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
10611 + i, fuse_volt[i], i - 1, fuse_volt[i - 1],
10612 + i, fuse_volt[i - 1]);
10613 + fuse_volt[i] = fuse_volt[i - 1];
10614 + }
10615 + }
10616 +
10617 + if (!allow_interpolation) {
10618 + /* Use fused open-loop voltage for lower frequencies. */
10619 + for (i = 0; i < vreg->corner_count; i++)
10620 + vreg->corner[i].open_loop_volt
10621 + = fuse_volt[vreg->corner[i].cpr_fuse_corner];
10622 + goto done;
10623 + }
10624 +
10625 + /* Determine highest corner mapped to each fuse corner */
10626 + j = vreg->fuse_corner_count - 1;
10627 + for (i = vreg->corner_count - 1; i >= 0; i--) {
10628 + if (vreg->corner[i].cpr_fuse_corner == j) {
10629 + fmax_corner[j] = i;
10630 + j--;
10631 + }
10632 + }
10633 + if (j >= 0) {
10634 + cpr3_err(vreg, "invalid fuse corner mapping\n");
10635 + rc = -EINVAL;
10636 + goto done;
10637 + }
10638 +
10639 + /*
10640 + * Interpolation is not possible for corners mapped to the lowest fuse
10641 + * corner so use the fuse corner value directly.
10642 + */
10643 + for (i = 0; i <= fmax_corner[0]; i++)
10644 + vreg->corner[i].open_loop_volt = fuse_volt[0];
10645 +
10646 + /* Interpolate voltages for the higher fuse corners. */
10647 + for (i = 1; i < vreg->fuse_corner_count; i++) {
10648 + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
10649 + volt_low = fuse_volt[i - 1];
10650 + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
10651 + volt_high = fuse_volt[i];
10652 +
10653 + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
10654 + vreg->corner[j].open_loop_volt = cpr3_interpolate(
10655 + freq_low, volt_low, freq_high, volt_high,
10656 + vreg->corner[j].proc_freq);
10657 + }
10658 +
10659 +done:
10660 + if (rc == 0) {
10661 + cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n");
10662 + for (i = 0; i < vreg->corner_count; i++)
10663 + cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i,
10664 + vreg->corner[i].open_loop_volt);
10665 +
10666 + rc = cpr3_adjust_open_loop_voltages(vreg);
10667 + if (rc)
10668 + cpr3_err(vreg, "open-loop voltage adjustment failed, rc=%d\n",
10669 + rc);
10670 +
10671 + if (of_find_property(node,
10672 + "qcom,cpr-misc-fuse-voltage-adjustment",
10673 + NULL)) {
10674 + misc_adj_volt = kcalloc(vreg->corner_count,
10675 + sizeof(*misc_adj_volt), GFP_KERNEL);
10676 + if (!misc_adj_volt) {
10677 + rc = -ENOMEM;
10678 + goto _exit;
10679 + }
10680 +
10681 + rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
10682 + misc_adj_volt);
10683 + if (rc) {
10684 + cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
10685 + rc);
10686 + kfree(misc_adj_volt);
10687 + goto _exit;
10688 + }
10689 +
10690 + for (i = 0; i < vreg->corner_count; i++)
10691 + vreg->corner[i].open_loop_volt
10692 + += misc_adj_volt[i];
10693 + kfree(misc_adj_volt);
10694 + }
10695 + }
10696 +
10697 +_exit:
10698 + kfree(fuse_volt);
10699 + kfree(fmax_corner);
10700 + return rc;
10701 +}
10702 +
10703 +/**
10704 + * cpr4_ipq807x_apss_set_no_interpolation_quotients() - use the fused target
10705 + * quotient values for lower frequencies.
10706 + * @vreg: Pointer to the CPR3 regulator
10707 + * @volt_adjust: Pointer to array of per-corner closed-loop adjustment
10708 + * voltages
10709 + * @volt_adjust_fuse: Pointer to array of per-fuse-corner closed-loop
10710 + * adjustment voltages
10711 + * @ro_scale: Pointer to array of per-fuse-corner RO scaling factor
10712 + * values with units of QUOT/V
10713 + *
10714 + * Return: 0 on success, errno on failure
10715 + */
10716 +static int cpr4_ipq807x_apss_set_no_interpolation_quotients(
10717 + struct cpr3_regulator *vreg, int *volt_adjust,
10718 + int *volt_adjust_fuse, int *ro_scale)
10719 +{
10720 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
10721 + u32 quot, ro;
10722 + int quot_adjust;
10723 + int i, fuse_corner;
10724 +
10725 + for (i = 0; i < vreg->corner_count; i++) {
10726 + fuse_corner = vreg->corner[i].cpr_fuse_corner;
10727 + quot = fuse->target_quot[fuse_corner];
10728 + quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
10729 + volt_adjust_fuse[fuse_corner] +
10730 + volt_adjust[i]);
10731 + ro = fuse->ro_sel[fuse_corner];
10732 + vreg->corner[i].target_quot[ro] = quot + quot_adjust;
10733 + cpr3_debug(vreg, "corner=%d RO=%u target quot=%u\n",
10734 + i, ro, quot);
10735 +
10736 + if (quot_adjust)
10737 + cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n",
10738 + i, ro, quot, vreg->corner[i].target_quot[ro],
10739 + volt_adjust_fuse[fuse_corner] +
10740 + volt_adjust[i]);
10741 + }
10742 +
10743 + return 0;
10744 +}
10745 +
10746 +/**
10747 + * cpr4_ipq807x_apss_calculate_target_quotients() - calculate the CPR target
10748 + * quotient for each corner of a CPR3 regulator
10749 + * @vreg: Pointer to the CPR3 regulator
10750 + *
10751 + * If target quotient interpolation is allowed in device tree, then this
10752 + * function calculates the target quotient for a given corner using linear
10753 + * interpolation. This interpolation is performed using the processor
10754 + * frequencies of the lower and higher Fmax corners along with the fused
10755 + * target quotient and quotient offset of the higher Fmax corner.
10756 + *
10757 + * If target quotient interpolation is not allowed, then this function uses
10758 + * the Fmax fused target quotient for all of the corners associated with a
10759 + * given fuse corner.
10760 + *
10761 + * Return: 0 on success, errno on failure
10762 + */
10763 +static int cpr4_ipq807x_apss_calculate_target_quotients(
10764 + struct cpr3_regulator *vreg)
10765 +{
10766 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
10767 + int rc;
10768 + bool allow_interpolation;
10769 + u64 freq_low, freq_high, prev_quot;
10770 + u64 *quot_low;
10771 + u64 *quot_high;
10772 + u32 quot, ro;
10773 + int i, j, fuse_corner, quot_adjust;
10774 + int *fmax_corner;
10775 + int *volt_adjust, *volt_adjust_fuse, *ro_scale;
10776 + int *voltage_adj_misc;
10777 +
10778 + /* Log fused quotient values for debugging purposes. */
10779 + for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS;
10780 + i < vreg->fuse_corner_count; i++)
10781 + cpr3_info(vreg, "fused %8s: quot[%2llu]=%4llu, quot_offset[%2llu]=%4llu\n",
10782 + cpr4_ipq807x_apss_fuse_corner_name[i],
10783 + fuse->ro_sel[i], fuse->target_quot[i],
10784 + fuse->ro_sel[i], fuse->quot_offset[i] *
10785 + IPQ807x_APSS_QUOT_OFFSET_SCALE);
10786 +
10787 + allow_interpolation = of_property_read_bool(vreg->of_node,
10788 + "qcom,allow-quotient-interpolation");
10789 +
10790 + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
10791 + GFP_KERNEL);
10792 + volt_adjust_fuse = kcalloc(vreg->fuse_corner_count,
10793 + sizeof(*volt_adjust_fuse), GFP_KERNEL);
10794 + ro_scale = kcalloc(vreg->fuse_corner_count, sizeof(*ro_scale),
10795 + GFP_KERNEL);
10796 + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
10797 + GFP_KERNEL);
10798 + quot_low = kcalloc(vreg->fuse_corner_count, sizeof(*quot_low),
10799 + GFP_KERNEL);
10800 + quot_high = kcalloc(vreg->fuse_corner_count, sizeof(*quot_high),
10801 + GFP_KERNEL);
10802 + if (!volt_adjust || !volt_adjust_fuse || !ro_scale ||
10803 + !fmax_corner || !quot_low || !quot_high) {
10804 + rc = -ENOMEM;
10805 + goto done;
10806 + }
10807 +
10808 + rc = cpr3_parse_closed_loop_voltage_adjustments(vreg, &fuse->ro_sel[0],
10809 + volt_adjust, volt_adjust_fuse, ro_scale);
10810 + if (rc) {
10811 + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
10812 + rc);
10813 + goto done;
10814 + }
10815 +
10816 + if (of_find_property(vreg->of_node,
10817 + "qcom,cpr-misc-fuse-voltage-adjustment", NULL)) {
10818 + voltage_adj_misc = kcalloc(vreg->corner_count,
10819 + sizeof(*voltage_adj_misc), GFP_KERNEL);
10820 + if (!voltage_adj_misc) {
10821 + rc = -ENOMEM;
10822 + goto done;
10823 + }
10824 +
10825 + rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
10826 + voltage_adj_misc);
10827 + if (rc) {
10828 + cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
10829 + rc);
10830 + kfree(voltage_adj_misc);
10831 + goto done;
10832 + }
10833 +
10834 + for (i = 0; i < vreg->corner_count; i++)
10835 + volt_adjust[i] += voltage_adj_misc[i];
10836 +
10837 + kfree(voltage_adj_misc);
10838 + }
10839 +
10840 + if (!allow_interpolation) {
10841 + /* Use fused target quotients for lower frequencies. */
10842 + return cpr4_ipq807x_apss_set_no_interpolation_quotients(
10843 + vreg, volt_adjust, volt_adjust_fuse, ro_scale);
10844 + }
10845 +
10846 + /* Determine highest corner mapped to each fuse corner */
10847 + j = vreg->fuse_corner_count - 1;
10848 + for (i = vreg->corner_count - 1; i >= 0; i--) {
10849 + if (vreg->corner[i].cpr_fuse_corner == j) {
10850 + fmax_corner[j] = i;
10851 + j--;
10852 + }
10853 + }
10854 + if (j >= 0) {
10855 + cpr3_err(vreg, "invalid fuse corner mapping\n");
10856 + rc = -EINVAL;
10857 + goto done;
10858 + }
10859 +
10860 + /*
10861 + * Interpolation is not possible for corners mapped to the lowest fuse
10862 + * corner so use the fuse corner value directly.
10863 + */
10864 + i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS;
10865 + quot_adjust = cpr3_quot_adjustment(ro_scale[i], volt_adjust_fuse[i]);
10866 + quot = fuse->target_quot[i] + quot_adjust;
10867 + quot_high[i] = quot_low[i] = quot;
10868 + ro = fuse->ro_sel[i];
10869 + if (quot_adjust)
10870 + cpr3_debug(vreg, "adjusted fuse corner %d RO%u target quot: %llu --> %u (%d uV)\n",
10871 + i, ro, fuse->target_quot[i], quot, volt_adjust_fuse[i]);
10872 +
10873 + for (i = 0; i <= fmax_corner[CPR4_IPQ807x_APSS_FUSE_CORNER_SVS];
10874 + i++)
10875 + vreg->corner[i].target_quot[ro] = quot;
10876 +
10877 + for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_NOM;
10878 + i < vreg->fuse_corner_count; i++) {
10879 + quot_high[i] = fuse->target_quot[i];
10880 + if (fuse->ro_sel[i] == fuse->ro_sel[i - 1])
10881 + quot_low[i] = quot_high[i - 1];
10882 + else
10883 + quot_low[i] = quot_high[i]
10884 + - fuse->quot_offset[i]
10885 + * IPQ807x_APSS_QUOT_OFFSET_SCALE;
10886 + if (quot_high[i] < quot_low[i]) {
10887 + cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu; overriding: quot_high[%d]=%llu\n",
10888 + i, quot_high[i], i, quot_low[i],
10889 + i, quot_low[i]);
10890 + quot_high[i] = quot_low[i];
10891 + }
10892 + }
10893 +
10894 + /* Perform per-fuse-corner target quotient adjustment */
10895 + for (i = 1; i < vreg->fuse_corner_count; i++) {
10896 + quot_adjust = cpr3_quot_adjustment(ro_scale[i],
10897 + volt_adjust_fuse[i]);
10898 + if (quot_adjust) {
10899 + prev_quot = quot_high[i];
10900 + quot_high[i] += quot_adjust;
10901 + cpr3_debug(vreg, "adjusted fuse corner %d RO%llu target quot: %llu --> %llu (%d uV)\n",
10902 + i, fuse->ro_sel[i], prev_quot, quot_high[i],
10903 + volt_adjust_fuse[i]);
10904 + }
10905 +
10906 + if (fuse->ro_sel[i] == fuse->ro_sel[i - 1])
10907 + quot_low[i] = quot_high[i - 1];
10908 + else
10909 + quot_low[i] += cpr3_quot_adjustment(ro_scale[i],
10910 + volt_adjust_fuse[i - 1]);
10911 +
10912 + if (quot_high[i] < quot_low[i]) {
10913 + cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu after adjustment; overriding: quot_high[%d]=%llu\n",
10914 + i, quot_high[i], i, quot_low[i],
10915 + i, quot_low[i]);
10916 + quot_high[i] = quot_low[i];
10917 + }
10918 + }
10919 +
10920 + /* Interpolate voltages for the higher fuse corners. */
10921 + for (i = 1; i < vreg->fuse_corner_count; i++) {
10922 + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
10923 + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
10924 +
10925 + ro = fuse->ro_sel[i];
10926 + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
10927 + vreg->corner[j].target_quot[ro] = cpr3_interpolate(
10928 + freq_low, quot_low[i], freq_high, quot_high[i],
10929 + vreg->corner[j].proc_freq);
10930 + }
10931 +
10932 + /* Perform per-corner target quotient adjustment */
10933 + for (i = 0; i < vreg->corner_count; i++) {
10934 + fuse_corner = vreg->corner[i].cpr_fuse_corner;
10935 + ro = fuse->ro_sel[fuse_corner];
10936 + quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
10937 + volt_adjust[i]);
10938 + if (quot_adjust) {
10939 + prev_quot = vreg->corner[i].target_quot[ro];
10940 + vreg->corner[i].target_quot[ro] += quot_adjust;
10941 + cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n",
10942 + i, ro, prev_quot,
10943 + vreg->corner[i].target_quot[ro],
10944 + volt_adjust[i]);
10945 + }
10946 + }
10947 +
10948 + /* Ensure that target quotients increase monotonically */
10949 + for (i = 1; i < vreg->corner_count; i++) {
10950 + ro = fuse->ro_sel[vreg->corner[i].cpr_fuse_corner];
10951 + if (fuse->ro_sel[vreg->corner[i - 1].cpr_fuse_corner] == ro
10952 + && vreg->corner[i].target_quot[ro]
10953 + < vreg->corner[i - 1].target_quot[ro]) {
10954 + cpr3_debug(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
10955 + i, ro, vreg->corner[i].target_quot[ro],
10956 + i - 1, ro, vreg->corner[i - 1].target_quot[ro],
10957 + i, ro, vreg->corner[i - 1].target_quot[ro]);
10958 + vreg->corner[i].target_quot[ro]
10959 + = vreg->corner[i - 1].target_quot[ro];
10960 + }
10961 + }
10962 +
10963 +done:
10964 + kfree(volt_adjust);
10965 + kfree(volt_adjust_fuse);
10966 + kfree(ro_scale);
10967 + kfree(fmax_corner);
10968 + kfree(quot_low);
10969 + kfree(quot_high);
10970 + return rc;
10971 +}
10972 +
10973 +/**
10974 + * cpr4_apss_print_settings() - print out APSS CPR configuration settings into
10975 + * the kernel log for debugging purposes
10976 + * @vreg: Pointer to the CPR3 regulator
10977 + */
10978 +static void cpr4_apss_print_settings(struct cpr3_regulator *vreg)
10979 +{
10980 + struct cpr3_corner *corner;
10981 + int i;
10982 +
10983 + cpr3_debug(vreg, "Corner: Frequency (Hz), Fuse Corner, Floor (uV), Open-Loop (uV), Ceiling (uV)\n");
10984 + for (i = 0; i < vreg->corner_count; i++) {
10985 + corner = &vreg->corner[i];
10986 + cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n",
10987 + i, corner->proc_freq, corner->cpr_fuse_corner,
10988 + corner->floor_volt, corner->open_loop_volt,
10989 + corner->ceiling_volt);
10990 + }
10991 +
10992 + if (vreg->thread->ctrl->apm)
10993 + cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n",
10994 + vreg->thread->ctrl->apm_threshold_volt,
10995 + vreg->thread->ctrl->apm_adj_volt);
10996 +}
10997 +
10998 +/**
10999 + * cpr4_apss_init_thread() - perform steps necessary to initialize the
11000 + * configuration data for a CPR3 thread
11001 + * @thread: Pointer to the CPR3 thread
11002 + *
11003 + * Return: 0 on success, errno on failure
11004 + */
11005 +static int cpr4_apss_init_thread(struct cpr3_thread *thread)
11006 +{
11007 + int rc;
11008 +
11009 + rc = cpr3_parse_common_thread_data(thread);
11010 + if (rc) {
11011 + cpr3_err(thread->ctrl, "thread %u unable to read CPR thread data from device tree, rc=%d\n",
11012 + thread->thread_id, rc);
11013 + return rc;
11014 + }
11015 +
11016 + return 0;
11017 +}
11018 +
11019 +/**
11020 + * cpr4_apss_parse_temp_adj_properties() - parse temperature based
11021 + * adjustment properties from device tree.
11022 + * @ctrl: Pointer to the CPR3 controller
11023 + *
11024 + * Return: 0 on success, errno on failure
11025 + */
11026 +static int cpr4_apss_parse_temp_adj_properties(struct cpr3_controller *ctrl)
11027 +{
11028 + struct device_node *of_node = ctrl->dev->of_node;
11029 + int rc, i, len, temp_point_count;
11030 +
11031 + if (!of_find_property(of_node, "qcom,cpr-temp-point-map", &len)) {
11032 + /*
11033 + * Temperature based adjustments are not defined. Single
11034 + * temperature band is still valid for per-online-core
11035 + * adjustments.
11036 + */
11037 + ctrl->temp_band_count = 1;
11038 + return 0;
11039 + }
11040 +
11041 + temp_point_count = len / sizeof(u32);
11042 + if (temp_point_count <= 0 ||
11043 + temp_point_count > IPQ807x_APSS_MAX_TEMP_POINTS) {
11044 + cpr3_err(ctrl, "invalid number of temperature points %d > %d (max)\n",
11045 + temp_point_count, IPQ807x_APSS_MAX_TEMP_POINTS);
11046 + return -EINVAL;
11047 + }
11048 +
11049 + ctrl->temp_points = devm_kcalloc(ctrl->dev, temp_point_count,
11050 + sizeof(*ctrl->temp_points), GFP_KERNEL);
11051 + if (!ctrl->temp_points)
11052 + return -ENOMEM;
11053 +
11054 + rc = of_property_read_u32_array(of_node, "qcom,cpr-temp-point-map",
11055 + ctrl->temp_points, temp_point_count);
11056 + if (rc) {
11057 + cpr3_err(ctrl, "error reading property qcom,cpr-temp-point-map, rc=%d\n",
11058 + rc);
11059 + return rc;
11060 + }
11061 +
11062 + for (i = 0; i < temp_point_count; i++)
11063 + cpr3_debug(ctrl, "Temperature Point %d=%d\n", i,
11064 + ctrl->temp_points[i]);
11065 +
11066 + /*
11067 + * If t1, t2, and t3 are the temperature points, then the temperature
11068 + * bands are: (-inf, t1], (t1, t2], (t2, t3], and (t3, inf).
11069 + */
11070 + ctrl->temp_band_count = temp_point_count + 1;
11071 + cpr3_debug(ctrl, "Number of temp bands =%d\n", ctrl->temp_band_count);
11072 +
11073 + rc = of_property_read_u32(of_node, "qcom,cpr-initial-temp-band",
11074 + &ctrl->initial_temp_band);
11075 + if (rc) {
11076 + cpr3_err(ctrl, "error reading qcom,cpr-initial-temp-band, rc=%d\n",
11077 + rc);
11078 + return rc;
11079 + }
11080 +
11081 + if (ctrl->initial_temp_band >= ctrl->temp_band_count) {
11082 + cpr3_err(ctrl, "Initial temperature band value %d should be in range [0 - %d]\n",
11083 + ctrl->initial_temp_band, ctrl->temp_band_count - 1);
11084 + return -EINVAL;
11085 + }
11086 +
11087 + ctrl->temp_sensor_id_start = IPQ807x_APSS_TEMP_SENSOR_ID_START;
11088 + ctrl->temp_sensor_id_end = IPQ807x_APSS_TEMP_SENSOR_ID_END;
11089 + ctrl->allow_temp_adj = true;
11090 + return rc;
11091 +}
11092 +
11093 +/**
11094 + * cpr4_apss_parse_boost_properties() - parse configuration data for boost
11095 + * voltage adjustment for CPR3 regulator from device tree.
11096 + * @vreg: Pointer to the CPR3 regulator
11097 + *
11098 + * Return: 0 on success, errno on failure
11099 + */
11100 +static int cpr4_apss_parse_boost_properties(struct cpr3_regulator *vreg)
11101 +{
11102 + struct cpr3_controller *ctrl = vreg->thread->ctrl;
11103 + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
11104 + struct cpr3_corner *corner;
11105 + int i, boost_voltage, final_boost_volt, rc = 0;
11106 + int *boost_table = NULL, *boost_temp_adj = NULL;
11107 + int boost_voltage_adjust = 0, boost_num_cores = 0;
11108 + u32 boost_allowed = 0;
11109 +
11110 + if (!boost_fuse[fuse->boost_cfg])
11111 + /* Voltage boost is disabled in fuse */
11112 + return 0;
11113 +
11114 + if (of_find_property(vreg->of_node, "qcom,allow-boost", NULL)) {
11115 + rc = cpr3_parse_array_property(vreg, "qcom,allow-boost", 1,
11116 + &boost_allowed);
11117 + if (rc)
11118 + return rc;
11119 + }
11120 +
11121 + if (!boost_allowed) {
11122 + /* Voltage boost is not enabled for this regulator */
11123 + return 0;
11124 + }
11125 +
11126 + boost_voltage = cpr3_convert_open_loop_voltage_fuse(
11127 + vreg->cpr4_regulator_data->boost_fuse_ref_volt,
11128 + vreg->cpr4_regulator_data->fuse_step_volt,
11129 + fuse->boost_voltage,
11130 + IPQ807x_APSS_VOLTAGE_FUSE_SIZE);
11131 +
11132 + /* Log boost voltage value for debugging purposes. */
11133 + cpr3_info(vreg, "Boost open-loop=%7d uV\n", boost_voltage);
11134 +
11135 + if (of_find_property(vreg->of_node,
11136 + "qcom,cpr-boost-voltage-fuse-adjustment", NULL)) {
11137 + rc = cpr3_parse_array_property(vreg,
11138 + "qcom,cpr-boost-voltage-fuse-adjustment",
11139 + 1, &boost_voltage_adjust);
11140 + if (rc) {
11141 + cpr3_err(vreg, "qcom,cpr-boost-voltage-fuse-adjustment reading failed, rc=%d\n",
11142 + rc);
11143 + return rc;
11144 + }
11145 +
11146 + boost_voltage += boost_voltage_adjust;
11147 + /* Log boost voltage value for debugging purposes. */
11148 + cpr3_info(vreg, "Adjusted boost open-loop=%7d uV\n",
11149 + boost_voltage);
11150 + }
11151 +
11152 + /* Limit boost voltage value between ceiling and floor voltage limits */
11153 + boost_voltage = min(boost_voltage, vreg->cpr4_regulator_data->boost_ceiling_volt);
11154 + boost_voltage = max(boost_voltage, vreg->cpr4_regulator_data->boost_floor_volt);
11155 +
11156 + /*
11157 + * The boost feature can only be used for the highest voltage corner.
11158 + * Also, keep core-count adjustments disabled when the boost feature
11159 + * is enabled.
11160 + */
11161 + corner = &vreg->corner[vreg->corner_count - 1];
11162 + if (!corner->sdelta) {
11163 + /*
11164 + * If core-count/temp adjustments are not defined, the cpr4
11165 + * sdelta for this corner will not be allocated. Allocate it
11166 + * here for boost configuration.
11167 + */
11168 + corner->sdelta = devm_kzalloc(ctrl->dev,
11169 + sizeof(*corner->sdelta), GFP_KERNEL);
11170 + if (!corner->sdelta)
11171 + return -ENOMEM;
11172 + }
11173 + corner->sdelta->temp_band_count = ctrl->temp_band_count;
11174 +
11175 + rc = of_property_read_u32(vreg->of_node, "qcom,cpr-num-boost-cores",
11176 + &boost_num_cores);
11177 + if (rc) {
11178 + cpr3_err(vreg, "qcom,cpr-num-boost-cores reading failed, rc=%d\n",
11179 + rc);
11180 + return rc;
11181 + }
11182 +
11183 + if (boost_num_cores <= 0 ||
11184 + boost_num_cores > IPQ807x_APSS_CPR_SDELTA_CORE_COUNT) {
11185 + cpr3_err(vreg, "Invalid boost number of cores = %d\n",
11186 + boost_num_cores);
11187 + return -EINVAL;
11188 + }
11189 + corner->sdelta->boost_num_cores = boost_num_cores;
11190 +
11191 + boost_table = devm_kcalloc(ctrl->dev, corner->sdelta->temp_band_count,
11192 + sizeof(*boost_table), GFP_KERNEL);
11193 + if (!boost_table)
11194 + return -ENOMEM;
11195 +
11196 + if (of_find_property(vreg->of_node,
11197 + "qcom,cpr-boost-temp-adjustment", NULL)) {
11198 + boost_temp_adj = kcalloc(corner->sdelta->temp_band_count,
11199 + sizeof(*boost_temp_adj), GFP_KERNEL);
11200 + if (!boost_temp_adj)
11201 + return -ENOMEM;
11202 +
11203 + rc = cpr3_parse_array_property(vreg,
11204 + "qcom,cpr-boost-temp-adjustment",
11205 + corner->sdelta->temp_band_count,
11206 + boost_temp_adj);
11207 + if (rc) {
11208 + cpr3_err(vreg, "qcom,cpr-boost-temp-adjustment reading failed, rc=%d\n",
11209 + rc);
11210 + goto done;
11211 + }
11212 + }
11213 +
11214 + for (i = 0; i < corner->sdelta->temp_band_count; i++) {
11215 + /* Apply static adjustments to boost voltage */
11216 + final_boost_volt = boost_voltage + (boost_temp_adj == NULL
11217 + ? 0 : boost_temp_adj[i]);
11218 + /*
11219 + * Limit final adjusted boost voltage value between ceiling
11220 + * and floor voltage limits
11221 + */
11222 + final_boost_volt = min(final_boost_volt,
11223 + vreg->cpr4_regulator_data->boost_ceiling_volt);
11224 + final_boost_volt = max(final_boost_volt,
11225 + vreg->cpr4_regulator_data->boost_floor_volt);
11226 +
11227 + boost_table[i] = (corner->open_loop_volt - final_boost_volt)
11228 + / ctrl->step_volt;
11229 + cpr3_debug(vreg, "Adjusted boost voltage margin for temp band %d = %d steps\n",
11230 + i, boost_table[i]);
11231 + }
11232 +
11233 + corner->ceiling_volt = vreg->cpr4_regulator_data->boost_ceiling_volt;
11234 + corner->sdelta->boost_table = boost_table;
11235 + corner->sdelta->allow_boost = true;
11236 + corner->sdelta->allow_core_count_adj = false;
11237 + vreg->allow_boost = true;
11238 + ctrl->allow_boost = true;
11239 +done:
11240 + kfree(boost_temp_adj);
11241 + return rc;
11242 +}
11243 +
11244 +/**
11245 + * cpr4_apss_init_regulator() - perform all steps necessary to initialize the
11246 + * configuration data for a CPR3 regulator
11247 + * @vreg: Pointer to the CPR3 regulator
11248 + *
11249 + * Return: 0 on success, errno on failure
11250 + */
11251 +static int cpr4_apss_init_regulator(struct cpr3_regulator *vreg)
11252 +{
11253 + struct cpr4_ipq807x_apss_fuses *fuse;
11254 + int rc;
11255 +
11256 + rc = cpr4_ipq807x_apss_read_fuse_data(vreg);
11257 + if (rc) {
11258 + cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc);
11259 + return rc;
11260 + }
11261 +
11262 + fuse = vreg->platform_fuses;
11263 +
11264 + rc = cpr4_apss_parse_corner_data(vreg);
11265 + if (rc) {
11266 + cpr3_err(vreg, "unable to read CPR corner data from device tree, rc=%d\n",
11267 + rc);
11268 + return rc;
11269 + }
11270 +
11271 + rc = cpr3_mem_acc_init(vreg);
11272 + if (rc) {
11273 + if (rc != -EPROBE_DEFER)
11274 + cpr3_err(vreg, "unable to initialize mem-acc regulator settings, rc=%d\n",
11275 + rc);
11276 + return rc;
11277 + }
11278 +
11279 + rc = cpr4_ipq807x_apss_calculate_open_loop_voltages(vreg);
11280 + if (rc) {
11281 + cpr3_err(vreg, "unable to calculate open-loop voltages, rc=%d\n",
11282 + rc);
11283 + return rc;
11284 + }
11285 +
11286 + rc = cpr3_limit_open_loop_voltages(vreg);
11287 + if (rc) {
11288 + cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n",
11289 + rc);
11290 + return rc;
11291 + }
11292 +
11293 + cpr3_open_loop_voltage_as_ceiling(vreg);
11294 +
11295 + rc = cpr3_limit_floor_voltages(vreg);
11296 + if (rc) {
11297 + cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc);
11298 + return rc;
11299 + }
11300 +
11301 + rc = cpr4_ipq807x_apss_calculate_target_quotients(vreg);
11302 + if (rc) {
11303 + cpr3_err(vreg, "unable to calculate target quotients, rc=%d\n",
11304 + rc);
11305 + return rc;
11306 + }
11307 +
11308 + rc = cpr4_parse_core_count_temp_voltage_adj(vreg, false);
11309 + if (rc) {
11310 + cpr3_err(vreg, "unable to parse temperature and core count voltage adjustments, rc=%d\n",
11311 + rc);
11312 + return rc;
11313 + }
11314 +
11315 + if (vreg->allow_core_count_adj && (vreg->max_core_count <= 0
11316 + || vreg->max_core_count >
11317 + IPQ807x_APSS_CPR_SDELTA_CORE_COUNT)) {
11318 + cpr3_err(vreg, "qcom,max-core-count has invalid value = %d\n",
11319 + vreg->max_core_count);
11320 + return -EINVAL;
11321 + }
11322 +
11323 + rc = cpr4_apss_parse_boost_properties(vreg);
11324 + if (rc) {
11325 + cpr3_err(vreg, "unable to parse boost adjustments, rc=%d\n",
11326 + rc);
11327 + return rc;
11328 + }
11329 +
11330 + cpr4_apss_print_settings(vreg);
11331 +
11332 + return rc;
11333 +}
11334 +
11335 +/**
11336 + * cpr4_apss_init_controller() - perform APSS CPR4 controller specific
11337 + * initializations
11338 + * @ctrl: Pointer to the CPR3 controller
11339 + *
11340 + * Return: 0 on success, errno on failure
11341 + */
11342 +static int cpr4_apss_init_controller(struct cpr3_controller *ctrl)
11343 +{
11344 + int rc;
11345 +
11346 + rc = cpr3_parse_common_ctrl_data(ctrl);
11347 + if (rc) {
11348 + if (rc != -EPROBE_DEFER)
11349 + cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n",
11350 + rc);
11351 + return rc;
11352 + }
11353 +
11354 + rc = of_property_read_u32(ctrl->dev->of_node,
11355 + "qcom,cpr-down-error-step-limit",
11356 + &ctrl->down_error_step_limit);
11357 + if (rc) {
11358 + cpr3_err(ctrl, "error reading qcom,cpr-down-error-step-limit, rc=%d\n",
11359 + rc);
11360 + return rc;
11361 + }
11362 +
11363 + rc = of_property_read_u32(ctrl->dev->of_node,
11364 + "qcom,cpr-up-error-step-limit",
11365 + &ctrl->up_error_step_limit);
11366 + if (rc) {
11367 + cpr3_err(ctrl, "error reading qcom,cpr-up-error-step-limit, rc=%d\n",
11368 + rc);
11369 + return rc;
11370 + }
11371 +
11372 + /*
11373 + * Use fixed step quotient if specified otherwise use dynamic
11374 + * calculated per RO step quotient
11375 + */
11376 + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-step-quot-fixed",
11377 + &ctrl->step_quot_fixed);
11378 + ctrl->use_dynamic_step_quot = ctrl->step_quot_fixed ? false : true;
11379 +
11380 + ctrl->saw_use_unit_mV = of_property_read_bool(ctrl->dev->of_node,
11381 + "qcom,cpr-saw-use-unit-mV");
11382 +
11383 + of_property_read_u32(ctrl->dev->of_node,
11384 + "qcom,cpr-voltage-settling-time",
11385 + &ctrl->voltage_settling_time);
11386 +
11387 + if (of_find_property(ctrl->dev->of_node, "vdd-limit-supply", NULL)) {
11388 + ctrl->vdd_limit_regulator =
11389 + devm_regulator_get(ctrl->dev, "vdd-limit");
11390 + if (IS_ERR(ctrl->vdd_limit_regulator)) {
11391 + rc = PTR_ERR(ctrl->vdd_limit_regulator);
11392 + if (rc != -EPROBE_DEFER)
11393 + cpr3_err(ctrl, "unable to request vdd-limit regulator, rc=%d\n",
11394 + rc);
11395 + return rc;
11396 + }
11397 + }
11398 +
11399 + rc = cpr3_apm_init(ctrl);
11400 + if (rc) {
11401 + if (rc != -EPROBE_DEFER)
11402 + cpr3_err(ctrl, "unable to initialize APM settings, rc=%d\n",
11403 + rc);
11404 + return rc;
11405 + }
11406 +
11407 + rc = cpr4_apss_parse_temp_adj_properties(ctrl);
11408 + if (rc) {
11409 + cpr3_err(ctrl, "unable to parse temperature adjustment properties, rc=%d\n",
11410 + rc);
11411 + return rc;
11412 + }
11413 +
11414 + ctrl->sensor_count = IPQ807x_APSS_CPR_SENSOR_COUNT;
11415 +
11416 + /*
11417 + * APSS only has one thread (0) per controller so the zeroed
11418 + * array does not need further modification.
11419 + */
11420 + ctrl->sensor_owner = devm_kcalloc(ctrl->dev, ctrl->sensor_count,
11421 + sizeof(*ctrl->sensor_owner), GFP_KERNEL);
11422 + if (!ctrl->sensor_owner)
11423 + return -ENOMEM;
11424 +
11425 + ctrl->ctrl_type = CPR_CTRL_TYPE_CPR4;
11426 + ctrl->supports_hw_closed_loop = false;
11427 + ctrl->use_hw_closed_loop = of_property_read_bool(ctrl->dev->of_node,
11428 + "qcom,cpr-hw-closed-loop");
11429 + return 0;
11430 +}
11431 +
11432 +static int cpr4_apss_regulator_suspend(struct platform_device *pdev,
11433 + pm_message_t state)
11434 +{
11435 + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
11436 +
11437 + return cpr3_regulator_suspend(ctrl);
11438 +}
11439 +
11440 +static int cpr4_apss_regulator_resume(struct platform_device *pdev)
11441 +{
11442 + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
11443 +
11444 + return cpr3_regulator_resume(ctrl);
11445 +}
11446 +
11447 +static void ipq6018_set_mem_acc(struct regulator_dev *rdev)
11448 +{
11449 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
11450 +
11451 + ipq6018_mem_acc_tcsr[0].ioremap_addr =
11452 + ioremap(ipq6018_mem_acc_tcsr[0].phy_addr, 0x4);
11453 + ipq6018_mem_acc_tcsr[1].ioremap_addr =
11454 + ioremap(ipq6018_mem_acc_tcsr[1].phy_addr, 0x4);
11455 +
11456 + if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) &&
11457 + (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) &&
11458 + (vreg->current_corner == (vreg->corner_count - CPR3_CORNER_OFFSET))) {
11459 +
11460 + writel_relaxed(ipq6018_mem_acc_tcsr[0].value,
11461 + ipq6018_mem_acc_tcsr[0].ioremap_addr);
11462 + writel_relaxed(ipq6018_mem_acc_tcsr[1].value,
11463 + ipq6018_mem_acc_tcsr[1].ioremap_addr);
11464 + }
11465 +}
11466 +
11467 +static void ipq6018_clr_mem_acc(struct regulator_dev *rdev)
11468 +{
11469 + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
11470 +
11471 + if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) &&
11472 + (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) &&
11473 + (vreg->current_corner != vreg->corner_count - CPR3_CORNER_OFFSET)) {
11474 + writel_relaxed(0x0, ipq6018_mem_acc_tcsr[0].ioremap_addr);
11475 + writel_relaxed(0x0, ipq6018_mem_acc_tcsr[1].ioremap_addr);
11476 + }
11477 +
11478 + iounmap(ipq6018_mem_acc_tcsr[0].ioremap_addr);
11479 + iounmap(ipq6018_mem_acc_tcsr[1].ioremap_addr);
11480 +}
11481 +
11482 +static struct cpr4_mem_acc_func ipq6018_mem_acc_funcs = {
11483 + .set_mem_acc = ipq6018_set_mem_acc,
11484 + .clear_mem_acc = ipq6018_clr_mem_acc
11485 +};
11486 +
11487 +static const struct cpr4_reg_data ipq807x_cpr_apss = {
11488 + .cpr_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS,
11489 + .fuse_ref_volt = ipq807x_apss_fuse_ref_volt,
11490 + .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT,
11491 + .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE,
11492 + .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT,
11493 + .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT,
11494 + .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT,
11495 + .cpr3_fuse_params = &ipq807x_fuse_params,
11496 + .mem_acc_funcs = NULL,
11497 +};
11498 +
11499 +static const struct cpr4_reg_data ipq817x_cpr_apss = {
11500 + .cpr_valid_fuse_count = IPQ817x_APPS_FUSE_CORNERS,
11501 + .fuse_ref_volt = ipq807x_apss_fuse_ref_volt,
11502 + .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT,
11503 + .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE,
11504 + .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT,
11505 + .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT,
11506 + .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT,
11507 + .cpr3_fuse_params = &ipq807x_fuse_params,
11508 + .mem_acc_funcs = NULL,
11509 +};
11510 +
11511 +static const struct cpr4_reg_data ipq6018_cpr_apss = {
11512 + .cpr_valid_fuse_count = IPQ6018_APSS_FUSE_CORNERS,
11513 + .fuse_ref_volt = ipq6018_apss_fuse_ref_volt,
11514 + .fuse_step_volt = IPQ6018_APSS_FUSE_STEP_VOLT,
11515 + .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE,
11516 + .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT,
11517 + .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT,
11518 + .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT,
11519 + .cpr3_fuse_params = &ipq6018_fuse_params,
11520 + .mem_acc_funcs = &ipq6018_mem_acc_funcs,
11521 +};
11522 +
11523 +static const struct cpr4_reg_data ipq9574_cpr_apss = {
11524 + .cpr_valid_fuse_count = IPQ9574_APSS_FUSE_CORNERS,
11525 + .fuse_ref_volt = ipq9574_apss_fuse_ref_volt,
11526 + .fuse_step_volt = IPQ9574_APSS_FUSE_STEP_VOLT,
11527 + .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE,
11528 + .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT,
11529 + .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT,
11530 + .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT,
11531 + .cpr3_fuse_params = &ipq9574_fuse_params,
11532 + .mem_acc_funcs = NULL,
11533 +};
11534 +
11535 +static struct of_device_id cpr4_regulator_match_table[] = {
11536 + {
11537 + .compatible = "qcom,cpr4-ipq807x-apss-regulator",
11538 + .data = &ipq807x_cpr_apss
11539 + },
11540 + {
11541 + .compatible = "qcom,cpr4-ipq817x-apss-regulator",
11542 + .data = &ipq817x_cpr_apss
11543 + },
11544 + {
11545 + .compatible = "qcom,cpr4-ipq6018-apss-regulator",
11546 + .data = &ipq6018_cpr_apss
11547 + },
11548 + {
11549 + .compatible = "qcom,cpr4-ipq9574-apss-regulator",
11550 + .data = &ipq9574_cpr_apss
11551 + },
11552 + {}
11553 +};
11554 +
11555 +static int cpr4_apss_regulator_probe(struct platform_device *pdev)
11556 +{
11557 + struct device *dev = &pdev->dev;
11558 + struct cpr3_controller *ctrl;
11559 + const struct of_device_id *match;
11560 + struct cpr4_reg_data *cpr_data;
11561 + int i, rc;
11562 +
11563 + if (!dev->of_node) {
11564 + dev_err(dev, "Device tree node is missing\n");
11565 + return -EINVAL;
11566 + }
11567 +
11568 + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
11569 + if (!ctrl)
11570 + return -ENOMEM;
11571 +
11572 + match = of_match_device(cpr4_regulator_match_table, &pdev->dev);
11573 + if (!match)
11574 + return -ENODEV;
11575 +
11576 + cpr_data = (struct cpr4_reg_data *)match->data;
11577 + g_valid_fuse_count = cpr_data->cpr_valid_fuse_count;
11578 + dev_info(dev, "CPR valid fuse count: %d\n", g_valid_fuse_count);
11579 + ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate;
11580 +
11581 + ctrl->dev = dev;
11582 + /* Set to false later if anything precludes CPR operation. */
11583 + ctrl->cpr_allowed_hw = true;
11584 +
11585 + rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name",
11586 + &ctrl->name);
11587 + if (rc) {
11588 + cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n",
11589 + rc);
11590 + return rc;
11591 + }
11592 +
11593 + rc = cpr3_map_fuse_base(ctrl, pdev);
11594 + if (rc) {
11595 + cpr3_err(ctrl, "could not map fuse base address\n");
11596 + return rc;
11597 + }
11598 +
11599 + rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_APSS_CPR_TCSR_START,
11600 + IPQ807x_APSS_CPR_TCSR_END);
11601 + if (rc) {
11602 + cpr3_err(ctrl, "could not read CPR tcsr setting\n");
11603 + return rc;
11604 + }
11605 +
11606 + rc = cpr3_allocate_threads(ctrl, 0, 0);
11607 + if (rc) {
11608 + cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n",
11609 + rc);
11610 + return rc;
11611 + }
11612 +
11613 + if (ctrl->thread_count != 1) {
11614 + cpr3_err(ctrl, "expected 1 thread but found %d\n",
11615 + ctrl->thread_count);
11616 + return -EINVAL;
11617 + }
11618 +
11619 + rc = cpr4_apss_init_controller(ctrl);
11620 + if (rc) {
11621 + if (rc != -EPROBE_DEFER)
11622 + cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n",
11623 + rc);
11624 + return rc;
11625 + }
11626 +
11627 + rc = cpr4_apss_init_thread(&ctrl->thread[0]);
11628 + if (rc) {
11629 + cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc);
11630 + return rc;
11631 + }
11632 +
11633 + for (i = 0; i < ctrl->thread[0].vreg_count; i++) {
11634 + ctrl->thread[0].vreg[i].cpr4_regulator_data = cpr_data;
11635 + rc = cpr4_apss_init_regulator(&ctrl->thread[0].vreg[i]);
11636 + if (rc) {
11637 + cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n",
11638 + rc);
11639 + return rc;
11640 + }
11641 + }
11642 +
11643 + platform_set_drvdata(pdev, ctrl);
11644 +
11645 + return cpr3_regulator_register(pdev, ctrl);
11646 +}
11647 +
11648 +static int cpr4_apss_regulator_remove(struct platform_device *pdev)
11649 +{
11650 + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
11651 +
11652 + return cpr3_regulator_unregister(ctrl);
11653 +}
11654 +
11655 +static struct platform_driver cpr4_apss_regulator_driver = {
11656 + .driver = {
11657 + .name = "qcom,cpr4-apss-regulator",
11658 + .of_match_table = cpr4_regulator_match_table,
11659 + .owner = THIS_MODULE,
11660 + },
11661 + .probe = cpr4_apss_regulator_probe,
11662 + .remove = cpr4_apss_regulator_remove,
11663 + .suspend = cpr4_apss_regulator_suspend,
11664 + .resume = cpr4_apss_regulator_resume,
11665 +};
11666 +
11667 +static int cpr4_regulator_init(void)
11668 +{
11669 + return platform_driver_register(&cpr4_apss_regulator_driver);
11670 +}
11671 +
11672 +static void cpr4_regulator_exit(void)
11673 +{
11674 + platform_driver_unregister(&cpr4_apss_regulator_driver);
11675 +}
11676 +
11677 +MODULE_DESCRIPTION("CPR4 APSS regulator driver");
11678 +MODULE_LICENSE("GPL v2");
11679 +
11680 +arch_initcall(cpr4_regulator_init);
11681 +module_exit(cpr4_regulator_exit);
11682 --- /dev/null
11683 +++ b/include/soc/qcom/socinfo.h
11684 @@ -0,0 +1,463 @@
11685 +/* Copyright (c) 2009-2014, 2016, 2020, The Linux Foundation. All rights reserved.
11686 + *
11687 + * This program is free software; you can redistribute it and/or modify
11688 + * it under the terms of the GNU General Public License version 2 and
11689 + * only version 2 as published by the Free Software Foundation.
11690 + *
11691 + * This program is distributed in the hope that it will be useful,
11692 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11693 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11694 + * GNU General Public License for more details.
11695 + *
11696 + */
11697 +
11698 +#ifndef _ARCH_ARM_MACH_MSM_SOCINFO_H_
11699 +#define _ARCH_ARM_MACH_MSM_SOCINFO_H_
11700 +
11701 +#include <linux/of.h>
11702 +
11703 +#define CPU_IPQ8074 323
11704 +#define CPU_IPQ8072 342
11705 +#define CPU_IPQ8076 343
11706 +#define CPU_IPQ8078 344
11707 +#define CPU_IPQ8070 375
11708 +#define CPU_IPQ8071 376
11709 +
11710 +#define CPU_IPQ8072A 389
11711 +#define CPU_IPQ8074A 390
11712 +#define CPU_IPQ8076A 391
11713 +#define CPU_IPQ8078A 392
11714 +#define CPU_IPQ8070A 395
11715 +#define CPU_IPQ8071A 396
11716 +
11717 +#define CPU_IPQ8172 397
11718 +#define CPU_IPQ8173 398
11719 +#define CPU_IPQ8174 399
11720 +
11721 +#define CPU_IPQ6018 402
11722 +#define CPU_IPQ6028 403
11723 +#define CPU_IPQ6000 421
11724 +#define CPU_IPQ6010 422
11725 +#define CPU_IPQ6005 453
11726 +
11727 +#define CPU_IPQ5010 446
11728 +#define CPU_IPQ5018 447
11729 +#define CPU_IPQ5028 448
11730 +#define CPU_IPQ5000 503
11731 +#define CPU_IPQ0509 504
11732 +#define CPU_IPQ0518 505
11733 +
11734 +#define CPU_IPQ9514 510
11735 +#define CPU_IPQ9554 512
11736 +#define CPU_IPQ9570 513
11737 +#define CPU_IPQ9574 514
11738 +#define CPU_IPQ9550 511
11739 +#define CPU_IPQ9510 521
11740 +
11741 +static inline int read_ipq_soc_version_major(void)
11742 +{
11743 + const int *prop;
11744 + prop = of_get_property(of_find_node_by_path("/"), "soc_version_major",
11745 + NULL);
11746 +
11747 + if (!prop)
11748 + return -EINVAL;
11749 +
11750 + return le32_to_cpu(*prop);
11751 +}
11752 +
11753 +static inline int read_ipq_cpu_type(void)
11754 +{
11755 + const int *prop;
11756 + prop = of_get_property(of_find_node_by_path("/"), "cpu_type", NULL);
11757 + /*
11758 + * Return Default CPU type if "cpu_type" property is not found in DTSI
11759 + */
11760 + if (!prop)
11761 + return CPU_IPQ8074;
11762 +
11763 + return le32_to_cpu(*prop);
11764 +}
11765 +
11766 +static inline int cpu_is_ipq8070(void)
11767 +{
11768 +#ifdef CONFIG_ARCH_QCOM
11769 + return read_ipq_cpu_type() == CPU_IPQ8070;
11770 +#else
11771 + return 0;
11772 +#endif
11773 +}
11774 +
11775 +static inline int cpu_is_ipq8071(void)
11776 +{
11777 +#ifdef CONFIG_ARCH_QCOM
11778 + return read_ipq_cpu_type() == CPU_IPQ8071;
11779 +#else
11780 + return 0;
11781 +#endif
11782 +}
11783 +
11784 +static inline int cpu_is_ipq8072(void)
11785 +{
11786 +#ifdef CONFIG_ARCH_QCOM
11787 + return read_ipq_cpu_type() == CPU_IPQ8072;
11788 +#else
11789 + return 0;
11790 +#endif
11791 +}
11792 +
11793 +static inline int cpu_is_ipq8074(void)
11794 +{
11795 +#ifdef CONFIG_ARCH_QCOM
11796 + return read_ipq_cpu_type() == CPU_IPQ8074;
11797 +#else
11798 + return 0;
11799 +#endif
11800 +}
11801 +
11802 +static inline int cpu_is_ipq8076(void)
11803 +{
11804 +#ifdef CONFIG_ARCH_QCOM
11805 + return read_ipq_cpu_type() == CPU_IPQ8076;
11806 +#else
11807 + return 0;
11808 +#endif
11809 +}
11810 +
11811 +static inline int cpu_is_ipq8078(void)
11812 +{
11813 +#ifdef CONFIG_ARCH_QCOM
11814 + return read_ipq_cpu_type() == CPU_IPQ8078;
11815 +#else
11816 + return 0;
11817 +#endif
11818 +}
11819 +
11820 +static inline int cpu_is_ipq8072a(void)
11821 +{
11822 +#ifdef CONFIG_ARCH_QCOM
11823 + return read_ipq_cpu_type() == CPU_IPQ8072A;
11824 +#else
11825 + return 0;
11826 +#endif
11827 +}
11828 +
11829 +static inline int cpu_is_ipq8074a(void)
11830 +{
11831 +#ifdef CONFIG_ARCH_QCOM
11832 + return read_ipq_cpu_type() == CPU_IPQ8074A;
11833 +#else
11834 + return 0;
11835 +#endif
11836 +}
11837 +
11838 +static inline int cpu_is_ipq8076a(void)
11839 +{
11840 +#ifdef CONFIG_ARCH_QCOM
11841 + return read_ipq_cpu_type() == CPU_IPQ8076A;
11842 +#else
11843 + return 0;
11844 +#endif
11845 +}
11846 +
11847 +static inline int cpu_is_ipq8078a(void)
11848 +{
11849 +#ifdef CONFIG_ARCH_QCOM
11850 + return read_ipq_cpu_type() == CPU_IPQ8078A;
11851 +#else
11852 + return 0;
11853 +#endif
11854 +}
11855 +
11856 +static inline int cpu_is_ipq8070a(void)
11857 +{
11858 +#ifdef CONFIG_ARCH_QCOM
11859 + return read_ipq_cpu_type() == CPU_IPQ8070A;
11860 +#else
11861 + return 0;
11862 +#endif
11863 +}
11864 +
11865 +static inline int cpu_is_ipq8071a(void)
11866 +{
11867 +#ifdef CONFIG_ARCH_QCOM
11868 + return read_ipq_cpu_type() == CPU_IPQ8071A;
11869 +#else
11870 + return 0;
11871 +#endif
11872 +}
11873 +
11874 +static inline int cpu_is_ipq8172(void)
11875 +{
11876 +#ifdef CONFIG_ARCH_QCOM
11877 + return read_ipq_cpu_type() == CPU_IPQ8172;
11878 +#else
11879 + return 0;
11880 +#endif
11881 +}
11882 +
11883 +static inline int cpu_is_ipq8173(void)
11884 +{
11885 +#ifdef CONFIG_ARCH_QCOM
11886 + return read_ipq_cpu_type() == CPU_IPQ8173;
11887 +#else
11888 + return 0;
11889 +#endif
11890 +}
11891 +
11892 +static inline int cpu_is_ipq8174(void)
11893 +{
11894 +#ifdef CONFIG_ARCH_QCOM
11895 + return read_ipq_cpu_type() == CPU_IPQ8174;
11896 +#else
11897 + return 0;
11898 +#endif
11899 +}
11900 +
11901 +static inline int cpu_is_ipq6018(void)
11902 +{
11903 +#ifdef CONFIG_ARCH_QCOM
11904 + return read_ipq_cpu_type() == CPU_IPQ6018;
11905 +#else
11906 + return 0;
11907 +#endif
11908 +}
11909 +
11910 +static inline int cpu_is_ipq6028(void)
11911 +{
11912 +#ifdef CONFIG_ARCH_QCOM
11913 + return read_ipq_cpu_type() == CPU_IPQ6028;
11914 +#else
11915 + return 0;
11916 +#endif
11917 +}
11918 +
11919 +static inline int cpu_is_ipq6000(void)
11920 +{
11921 +#ifdef CONFIG_ARCH_QCOM
11922 + return read_ipq_cpu_type() == CPU_IPQ6000;
11923 +#else
11924 + return 0;
11925 +#endif
11926 +}
11927 +
11928 +static inline int cpu_is_ipq6010(void)
11929 +{
11930 +#ifdef CONFIG_ARCH_QCOM
11931 + return read_ipq_cpu_type() == CPU_IPQ6010;
11932 +#else
11933 + return 0;
11934 +#endif
11935 +}
11936 +
11937 +static inline int cpu_is_ipq6005(void)
11938 +{
11939 +#ifdef CONFIG_ARCH_QCOM
11940 + return read_ipq_cpu_type() == CPU_IPQ6005;
11941 +#else
11942 + return 0;
11943 +#endif
11944 +}
11945 +
11946 +static inline int cpu_is_ipq5010(void)
11947 +{
11948 +#ifdef CONFIG_ARCH_QCOM
11949 + return read_ipq_cpu_type() == CPU_IPQ5010;
11950 +#else
11951 + return 0;
11952 +#endif
11953 +}
11954 +
11955 +static inline int cpu_is_ipq5018(void)
11956 +{
11957 +#ifdef CONFIG_ARCH_QCOM
11958 + return read_ipq_cpu_type() == CPU_IPQ5018;
11959 +#else
11960 + return 0;
11961 +#endif
11962 +}
11963 +
11964 +static inline int cpu_is_ipq5028(void)
11965 +{
11966 +#ifdef CONFIG_ARCH_QCOM
11967 + return read_ipq_cpu_type() == CPU_IPQ5028;
11968 +#else
11969 + return 0;
11970 +#endif
11971 +}
11972 +
11973 +static inline int cpu_is_ipq5000(void)
11974 +{
11975 +#ifdef CONFIG_ARCH_QCOM
11976 + return read_ipq_cpu_type() == CPU_IPQ5000;
11977 +#else
11978 + return 0;
11979 +#endif
11980 +}
11981 +
11982 +static inline int cpu_is_ipq0509(void)
11983 +{
11984 +#ifdef CONFIG_ARCH_QCOM
11985 + return read_ipq_cpu_type() == CPU_IPQ0509;
11986 +#else
11987 + return 0;
11988 +#endif
11989 +}
11990 +
11991 +static inline int cpu_is_ipq0518(void)
11992 +{
11993 +#ifdef CONFIG_ARCH_QCOM
11994 + return read_ipq_cpu_type() == CPU_IPQ0518;
11995 +#else
11996 + return 0;
11997 +#endif
11998 +}
11999 +
12000 +static inline int cpu_is_ipq9514(void)
12001 +{
12002 +#ifdef CONFIG_ARCH_QCOM
12003 + return read_ipq_cpu_type() == CPU_IPQ9514;
12004 +#else
12005 + return 0;
12006 +#endif
12007 +}
12008 +
12009 +static inline int cpu_is_ipq9554(void)
12010 +{
12011 +#ifdef CONFIG_ARCH_QCOM
12012 + return read_ipq_cpu_type() == CPU_IPQ9554;
12013 +#else
12014 + return 0;
12015 +#endif
12016 +}
12017 +
12018 +static inline int cpu_is_ipq9570(void)
12019 +{
12020 +#ifdef CONFIG_ARCH_QCOM
12021 + return read_ipq_cpu_type() == CPU_IPQ9570;
12022 +#else
12023 + return 0;
12024 +#endif
12025 +}
12026 +
12027 +static inline int cpu_is_ipq9574(void)
12028 +{
12029 +#ifdef CONFIG_ARCH_QCOM
12030 + return read_ipq_cpu_type() == CPU_IPQ9574;
12031 +#else
12032 + return 0;
12033 +#endif
12034 +}
12035 +
12036 +static inline int cpu_is_ipq9550(void)
12037 +{
12038 +#ifdef CONFIG_ARCH_QCOM
12039 + return read_ipq_cpu_type() == CPU_IPQ9550;
12040 +#else
12041 + return 0;
12042 +#endif
12043 +}
12044 +
12045 +static inline int cpu_is_ipq9510(void)
12046 +{
12047 +#ifdef CONFIG_ARCH_QCOM
12048 + return read_ipq_cpu_type() == CPU_IPQ9510;
12049 +#else
12050 + return 0;
12051 +#endif
12052 +}
12053 +
12054 +static inline int cpu_is_ipq807x(void)
12055 +{
12056 +#ifdef CONFIG_ARCH_QCOM
12057 + return cpu_is_ipq8072() || cpu_is_ipq8074() ||
12058 + cpu_is_ipq8076() || cpu_is_ipq8078() ||
12059 + cpu_is_ipq8070() || cpu_is_ipq8071() ||
12060 + cpu_is_ipq8072a() || cpu_is_ipq8074a() ||
12061 + cpu_is_ipq8076a() || cpu_is_ipq8078a() ||
12062 + cpu_is_ipq8070a() || cpu_is_ipq8071a() ||
12063 + cpu_is_ipq8172() || cpu_is_ipq8173() ||
12064 + cpu_is_ipq8174();
12065 +#else
12066 + return 0;
12067 +#endif
12068 +}
12069 +
12070 +static inline int cpu_is_ipq60xx(void)
12071 +{
12072 +#ifdef CONFIG_ARCH_QCOM
12073 + return cpu_is_ipq6018() || cpu_is_ipq6028() ||
12074 + cpu_is_ipq6000() || cpu_is_ipq6010() ||
12075 + cpu_is_ipq6005();
12076 +#else
12077 + return 0;
12078 +#endif
12079 +}
12080 +
12081 +static inline int cpu_is_ipq50xx(void)
12082 +{
12083 +#ifdef CONFIG_ARCH_QCOM
12084 + return cpu_is_ipq5010() || cpu_is_ipq5018() ||
12085 + cpu_is_ipq5028() || cpu_is_ipq5000() ||
12086 + cpu_is_ipq0509() || cpu_is_ipq0518();
12087 +#else
12088 + return 0;
12089 +#endif
12090 +}
12091 +
12092 +static inline int cpu_is_ipq95xx(void)
12093 +{
12094 +#ifdef CONFIG_ARCH_QCOM
12095 + return cpu_is_ipq9514() || cpu_is_ipq9554() ||
12096 + cpu_is_ipq9570() || cpu_is_ipq9574() ||
12097 + cpu_is_ipq9550() || cpu_is_ipq9510();
12098 +#else
12099 + return 0;
12100 +#endif
12101 +}
12102 +
12103 +static inline int cpu_is_nss_crypto_enabled(void)
12104 +{
12105 +#ifdef CONFIG_ARCH_QCOM
12106 + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
12107 + cpu_is_ipq50xx() || cpu_is_ipq9570() ||
12108 + cpu_is_ipq9550() || cpu_is_ipq9574() ||
12109 + cpu_is_ipq9554();
12110 +#else
12111 + return 0;
12112 +#endif
12113 +}
12114 +
12115 +static inline int cpu_is_internal_wifi_enabled(void)
12116 +{
12117 +#ifdef CONFIG_ARCH_QCOM
12118 + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
12119 + cpu_is_ipq50xx() || cpu_is_ipq9514() ||
12120 + cpu_is_ipq9554() || cpu_is_ipq9574();
12121 +#else
12122 + return 0;
12123 +#endif
12124 +}
12125 +
12126 +static inline int cpu_is_uniphy1_enabled(void)
12127 +{
12128 +#ifdef CONFIG_ARCH_QCOM
12129 + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
12130 + cpu_is_ipq9554() || cpu_is_ipq9570() ||
12131 + cpu_is_ipq9574() || cpu_is_ipq9550();
12132 +#else
12133 + return 0;
12134 +#endif
12135 +}
12136 +
12137 +static inline int cpu_is_uniphy2_enabled(void)
12138 +{
12139 +#ifdef CONFIG_ARCH_QCOM
12140 + return cpu_is_ipq807x() || cpu_is_ipq9570() ||
12141 + cpu_is_ipq9574();
12142 +#else
12143 + return 0;
12144 +#endif
12145 +}
12146 +
12147 +#endif /* _ARCH_ARM_MACH_MSM_SOCINFO_H_ */