aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Collins <collinsd@codeaurora.org>2018-05-24 03:19:02 -0400
committerEduardo Valentin <edubezval@gmail.com>2018-06-01 17:22:28 -0400
commit10c8251cce3380823c755a63f97cca432fcc4aec (patch)
treeea005414c14128756e3c7366088f2dc384d41308
parentd86910b9141e16f2bbe38e53429f63f13569624b (diff)
thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals
Add support for the TEMP_ALARM GEN2 PMIC peripheral subtype. The GEN2 subtype defines an over temperature state with hysteresis instead of stage in the status register. There are two GEN2 states corresponding to stages 1 and 2. Signed-off-by: David Collins <collinsd@codeaurora.org> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
-rw-r--r--drivers/thermal/qcom-spmi-temp-alarm.c92
1 files changed, 71 insertions, 21 deletions
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c
index 95f987d5aa71..ad4f3a8d6560 100644
--- a/drivers/thermal/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom-spmi-temp-alarm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. 2 * Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 */ 12 */
13 13
14#include <linux/bitops.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/err.h> 16#include <linux/err.h>
16#include <linux/iio/consumer.h> 17#include <linux/iio/consumer.h>
@@ -29,13 +30,17 @@
29#define QPNP_TM_REG_ALARM_CTRL 0x46 30#define QPNP_TM_REG_ALARM_CTRL 0x46
30 31
31#define QPNP_TM_TYPE 0x09 32#define QPNP_TM_TYPE 0x09
32#define QPNP_TM_SUBTYPE 0x08 33#define QPNP_TM_SUBTYPE_GEN1 0x08
34#define QPNP_TM_SUBTYPE_GEN2 0x09
33 35
34#define STATUS_STAGE_MASK 0x03 36#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
37#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
38#define STATUS_GEN2_STATE_SHIFT 4
35 39
36#define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03 40#define SHUTDOWN_CTRL1_OVERRIDE_MASK GENMASK(7, 6)
41#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
37 42
38#define ALARM_CTRL_FORCE_ENABLE 0x80 43#define ALARM_CTRL_FORCE_ENABLE BIT(7)
39 44
40/* 45/*
41 * Trip point values based on threshold control 46 * Trip point values based on threshold control
@@ -58,6 +63,7 @@
58struct qpnp_tm_chip { 63struct qpnp_tm_chip {
59 struct regmap *map; 64 struct regmap *map;
60 struct thermal_zone_device *tz_dev; 65 struct thermal_zone_device *tz_dev;
66 unsigned int subtype;
61 long temp; 67 long temp;
62 unsigned int thresh; 68 unsigned int thresh;
63 unsigned int stage; 69 unsigned int stage;
@@ -66,6 +72,9 @@ struct qpnp_tm_chip {
66 struct iio_channel *adc; 72 struct iio_channel *adc;
67}; 73};
68 74
75/* This array maps from GEN2 alarm state to GEN1 alarm stage */
76static const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3};
77
69static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data) 78static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data)
70{ 79{
71 unsigned int val; 80 unsigned int val;
@@ -84,30 +93,59 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data)
84 return regmap_write(chip->map, chip->base + addr, data); 93 return regmap_write(chip->map, chip->base + addr, data);
85} 94}
86 95
96/**
97 * qpnp_tm_get_temp_stage() - return over-temperature stage
98 * @chip: Pointer to the qpnp_tm chip
99 *
100 * Return: stage (GEN1) or state (GEN2) on success, or errno on failure.
101 */
102static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
103{
104 int ret;
105 u8 reg = 0;
106
107 ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
108 if (ret < 0)
109 return ret;
110
111 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
112 ret = reg & STATUS_GEN1_STAGE_MASK;
113 else
114 ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT;
115
116 return ret;
117}
118
87/* 119/*
88 * This function updates the internal temp value based on the 120 * This function updates the internal temp value based on the
89 * current thermal stage and threshold as well as the previous stage 121 * current thermal stage and threshold as well as the previous stage
90 */ 122 */
91static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) 123static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
92{ 124{
93 unsigned int stage; 125 unsigned int stage, stage_new, stage_old;
94 int ret; 126 int ret;
95 u8 reg = 0;
96 127
97 ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg); 128 ret = qpnp_tm_get_temp_stage(chip);
98 if (ret < 0) 129 if (ret < 0)
99 return ret; 130 return ret;
131 stage = ret;
100 132
101 stage = reg & STATUS_STAGE_MASK; 133 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
134 stage_new = stage;
135 stage_old = chip->stage;
136 } else {
137 stage_new = alarm_state_map[stage];
138 stage_old = alarm_state_map[chip->stage];
139 }
102 140
103 if (stage > chip->stage) { 141 if (stage_new > stage_old) {
104 /* increasing stage, use lower bound */ 142 /* increasing stage, use lower bound */
105 chip->temp = (stage - 1) * TEMP_STAGE_STEP + 143 chip->temp = (stage_new - 1) * TEMP_STAGE_STEP +
106 chip->thresh * TEMP_THRESH_STEP + 144 chip->thresh * TEMP_THRESH_STEP +
107 TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; 145 TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
108 } else if (stage < chip->stage) { 146 } else if (stage_new < stage_old) {
109 /* decreasing stage, use upper bound */ 147 /* decreasing stage, use upper bound */
110 chip->temp = stage * TEMP_STAGE_STEP + 148 chip->temp = stage_new * TEMP_STAGE_STEP +
111 chip->thresh * TEMP_THRESH_STEP - 149 chip->thresh * TEMP_THRESH_STEP -
112 TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; 150 TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
113 } 151 }
@@ -162,28 +200,37 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
162 */ 200 */
163static int qpnp_tm_init(struct qpnp_tm_chip *chip) 201static int qpnp_tm_init(struct qpnp_tm_chip *chip)
164{ 202{
203 unsigned int stage;
165 int ret; 204 int ret;
166 u8 reg; 205 u8 reg = 0;
167 206
168 chip->thresh = THRESH_MIN; 207 ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg);
208 if (ret < 0)
209 return ret;
210
211 chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
169 chip->temp = DEFAULT_TEMP; 212 chip->temp = DEFAULT_TEMP;
170 213
171 ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg); 214 ret = qpnp_tm_get_temp_stage(chip);
172 if (ret < 0) 215 if (ret < 0)
173 return ret; 216 return ret;
217 chip->stage = ret;
174 218
175 chip->stage = reg & STATUS_STAGE_MASK; 219 stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
220 ? chip->stage : alarm_state_map[chip->stage];
176 221
177 if (chip->stage) 222 if (stage)
178 chip->temp = chip->thresh * TEMP_THRESH_STEP + 223 chip->temp = chip->thresh * TEMP_THRESH_STEP +
179 (chip->stage - 1) * TEMP_STAGE_STEP + 224 (stage - 1) * TEMP_STAGE_STEP +
180 TEMP_THRESH_MIN; 225 TEMP_THRESH_MIN;
181 226
182 /* 227 /*
183 * Set threshold and disable software override of stage 2 and 3 228 * Set threshold and disable software override of stage 2 and 3
184 * shutdowns. 229 * shutdowns.
185 */ 230 */
186 reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK; 231 chip->thresh = THRESH_MIN;
232 reg &= ~(SHUTDOWN_CTRL1_OVERRIDE_MASK | SHUTDOWN_CTRL1_THRESHOLD_MASK);
233 reg |= chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
187 ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); 234 ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
188 if (ret < 0) 235 if (ret < 0)
189 return ret; 236 return ret;
@@ -246,12 +293,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
246 return ret; 293 return ret;
247 } 294 }
248 295
249 if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { 296 if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
297 && subtype != QPNP_TM_SUBTYPE_GEN2)) {
250 dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", 298 dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
251 type, subtype); 299 type, subtype);
252 return -ENODEV; 300 return -ENODEV;
253 } 301 }
254 302
303 chip->subtype = subtype;
304
255 ret = qpnp_tm_init(chip); 305 ret = qpnp_tm_init(chip);
256 if (ret < 0) { 306 if (ret < 0) {
257 dev_err(&pdev->dev, "init failed\n"); 307 dev_err(&pdev->dev, "init failed\n");