blob: af8b158b7c9575f14e668b05a742a67b2dc40667 [file] [log] [blame]
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +05301/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "QG-K: %s: " fmt, __func__
14
15#include <linux/alarmtimer.h>
Vamshi Krishna B Va791d522018-04-10 18:20:42 +053016#include <linux/kernel.h>
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053017#include <linux/module.h>
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053018#include <linux/power_supply.h>
19#include <uapi/linux/qg.h>
Vamshi Krishna B Va791d522018-04-10 18:20:42 +053020#include "fg-alg.h"
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053021#include "qg-sdam.h"
22#include "qg-core.h"
23#include "qg-reg.h"
24#include "qg-util.h"
25#include "qg-defs.h"
26
27#define DEFAULT_UPDATE_TIME_MS 64000
28#define SOC_SCALE_HYST_MS 2000
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053029
30static int qg_delta_soc_interval_ms = 20000;
31module_param_named(
Anirudh Ghayal20386de2018-04-16 14:29:56 +053032 soc_interval_ms, qg_delta_soc_interval_ms, int, 0600
33);
34
35static int qg_delta_soc_cold_interval_ms = 4000;
36module_param_named(
37 soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053038);
39
40static void get_next_update_time(struct qpnp_qg *chip)
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053041{
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053042 int soc_points = 0, batt_temp = 0;
43 int min_delta_soc_interval_ms = qg_delta_soc_interval_ms;
44 int rc = 0, rt_time_ms = 0, full_time_ms = DEFAULT_UPDATE_TIME_MS;
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053045
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053046 get_fifo_done_time(chip, false, &full_time_ms);
47 get_fifo_done_time(chip, true, &rt_time_ms);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053048
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053049 full_time_ms = CAP(0, DEFAULT_UPDATE_TIME_MS,
50 full_time_ms - rt_time_ms);
51
52 soc_points = abs(chip->msoc - chip->catch_up_soc);
53 if (chip->maint_soc > 0)
54 soc_points = max(abs(chip->msoc - chip->maint_soc), soc_points);
55 soc_points /= chip->dt.delta_soc;
56
57 /* Lower the delta soc interval by half at cold */
58 rc = qg_get_battery_temp(chip, &batt_temp);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053059 if (rc < 0)
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053060 pr_err("Failed to read battery temperature rc=%d\n", rc);
Anirudh Ghayal20386de2018-04-16 14:29:56 +053061 else if (batt_temp < chip->dt.cold_temp_threshold)
62 min_delta_soc_interval_ms = qg_delta_soc_cold_interval_ms;
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053063
Anirudh Ghayal20386de2018-04-16 14:29:56 +053064 if (!min_delta_soc_interval_ms)
65 min_delta_soc_interval_ms = 1000; /* 1 second */
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053066
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053067 chip->next_wakeup_ms = (full_time_ms / (soc_points + 1))
68 - SOC_SCALE_HYST_MS;
69 chip->next_wakeup_ms = max(chip->next_wakeup_ms,
70 min_delta_soc_interval_ms);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053071
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053072 qg_dbg(chip, QG_DEBUG_SOC, "fifo_full_time=%d secs fifo_real_time=%d secs soc_scale_points=%d\n",
73 full_time_ms / 1000, rt_time_ms / 1000, soc_points);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053074}
75
76static bool is_scaling_required(struct qpnp_qg *chip)
77{
Anirudh Ghayale4923382018-03-11 20:32:10 +053078 if (!chip->profile_loaded)
79 return false;
80
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +053081 if (chip->maint_soc > 0 &&
82 (abs(chip->maint_soc - chip->msoc) >= chip->dt.delta_soc))
83 return true;
84
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +053085 if ((abs(chip->catch_up_soc - chip->msoc) < chip->dt.delta_soc) &&
86 chip->catch_up_soc != 0 && chip->catch_up_soc != 100)
87 return false;
88
89 if (chip->catch_up_soc == chip->msoc)
90 /* SOC has not changed */
91 return false;
92
93
94 if (chip->catch_up_soc > chip->msoc && !is_usb_present(chip))
95 /* USB is not present and SOC has increased */
96 return false;
97
98 return true;
99}
100
101static void update_msoc(struct qpnp_qg *chip)
102{
Vamshi Krishna B Va791d522018-04-10 18:20:42 +0530103 int rc = 0, batt_temp = 0, batt_soc_32bit = 0;
104 bool usb_present = is_usb_present(chip);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530105
106 if (chip->catch_up_soc > chip->msoc) {
107 /* SOC increased */
Vamshi Krishna B Va791d522018-04-10 18:20:42 +0530108 if (usb_present) /* Increment if USB is present */
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530109 chip->msoc += chip->dt.delta_soc;
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530110 } else if (chip->catch_up_soc < chip->msoc) {
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530111 /* SOC dropped */
112 chip->msoc -= chip->dt.delta_soc;
113 }
114 chip->msoc = CAP(0, 100, chip->msoc);
115
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530116 if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc) {
117 chip->maint_soc -= chip->dt.delta_soc;
118 chip->maint_soc = CAP(0, 100, chip->maint_soc);
119 }
120
121 /* maint_soc dropped below msoc, skip using it */
122 if (chip->maint_soc <= chip->msoc)
123 chip->maint_soc = -EINVAL;
124
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530125 /* update the SOC register */
126 rc = qg_write_monotonic_soc(chip, chip->msoc);
127 if (rc < 0)
128 pr_err("Failed to update MSOC register rc=%d\n", rc);
129
130 /* update SDAM with the new MSOC */
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530131 chip->sdam_data[SDAM_SOC] = chip->msoc;
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530132 rc = qg_sdam_write(SDAM_SOC, chip->msoc);
133 if (rc < 0)
134 pr_err("Failed to update SDAM with MSOC rc=%d\n", rc);
135
Vamshi Krishna B Va791d522018-04-10 18:20:42 +0530136 if (!chip->dt.cl_disable && chip->cl->active) {
137 rc = qg_get_battery_temp(chip, &batt_temp);
138 if (rc < 0) {
139 pr_err("Failed to read BATT_TEMP rc=%d\n", rc);
140 } else {
141 batt_soc_32bit = div64_u64(
142 chip->batt_soc * BATT_SOC_32BIT,
143 QG_SOC_FULL);
144 cap_learning_update(chip->cl, batt_temp, batt_soc_32bit,
145 chip->charge_status, chip->charge_done,
146 usb_present, false);
147 }
148 }
149
150 cycle_count_update(chip->counter,
151 DIV_ROUND_CLOSEST(chip->msoc * 255, 100),
152 chip->charge_status, chip->charge_done,
153 usb_present);
154
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530155 qg_dbg(chip, QG_DEBUG_SOC,
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530156 "SOC scale: Update maint_soc=%d msoc=%d catch_up_soc=%d delta_soc=%d\n",
157 chip->maint_soc, chip->msoc,
158 chip->catch_up_soc, chip->dt.delta_soc);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530159}
160
161static void scale_soc_stop(struct qpnp_qg *chip)
162{
163 chip->next_wakeup_ms = 0;
164 alarm_cancel(&chip->alarm_timer);
165
166 qg_dbg(chip, QG_DEBUG_SOC,
167 "SOC scale stopped: msoc=%d catch_up_soc=%d\n",
168 chip->msoc, chip->catch_up_soc);
169}
170
171static void scale_soc_work(struct work_struct *work)
172{
173 struct qpnp_qg *chip = container_of(work,
174 struct qpnp_qg, scale_soc_work);
175
176 mutex_lock(&chip->soc_lock);
177
178 if (!is_scaling_required(chip)) {
179 scale_soc_stop(chip);
180 goto done;
181 }
182
183 update_msoc(chip);
184
185 if (is_scaling_required(chip)) {
186 alarm_start_relative(&chip->alarm_timer,
187 ms_to_ktime(chip->next_wakeup_ms));
188 } else {
189 scale_soc_stop(chip);
190 goto done_psy;
191 }
192
193 qg_dbg(chip, QG_DEBUG_SOC,
194 "SOC scale: Work msoc=%d catch_up_soc=%d delta_soc=%d next_wakeup=%d sec\n",
195 chip->msoc, chip->catch_up_soc, chip->dt.delta_soc,
196 chip->next_wakeup_ms / 1000);
197
198done_psy:
199 power_supply_changed(chip->qg_psy);
200done:
201 pm_relax(chip->dev);
202 mutex_unlock(&chip->soc_lock);
203}
204
205static enum alarmtimer_restart
206 qpnp_msoc_timer(struct alarm *alarm, ktime_t now)
207{
208 struct qpnp_qg *chip = container_of(alarm,
209 struct qpnp_qg, alarm_timer);
210
211 /* timer callback runs in atomic context, cannot use voter */
212 pm_stay_awake(chip->dev);
213 schedule_work(&chip->scale_soc_work);
214
215 return ALARMTIMER_NORESTART;
216}
217
218int qg_scale_soc(struct qpnp_qg *chip, bool force_soc)
219{
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530220 int rc = 0;
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530221
222 mutex_lock(&chip->soc_lock);
223
224 qg_dbg(chip, QG_DEBUG_SOC,
225 "SOC scale: Start msoc=%d catch_up_soc=%d delta_soc=%d\n",
226 chip->msoc, chip->catch_up_soc, chip->dt.delta_soc);
227
228 if (force_soc) {
229 chip->msoc = chip->catch_up_soc;
230 rc = qg_write_monotonic_soc(chip, chip->msoc);
231 if (rc < 0)
232 pr_err("Failed to update MSOC register rc=%d\n", rc);
233
234 qg_dbg(chip, QG_DEBUG_SOC,
235 "SOC scale: Forced msoc=%d\n", chip->msoc);
236 goto done_psy;
237 }
238
239 if (!is_scaling_required(chip)) {
240 scale_soc_stop(chip);
241 goto done;
242 }
243
244 update_msoc(chip);
245
246 if (is_scaling_required(chip)) {
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530247 get_next_update_time(chip);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530248 alarm_start_relative(&chip->alarm_timer,
249 ms_to_ktime(chip->next_wakeup_ms));
250 } else {
251 scale_soc_stop(chip);
252 goto done_psy;
253 }
254
255 qg_dbg(chip, QG_DEBUG_SOC,
Vamshi Krishna B V2b61cf62018-03-13 13:54:33 +0530256 "SOC scale: msoc=%d catch_up_soc=%d delta_soc=%d next_wakeup=%d sec\n",
257 chip->msoc, chip->catch_up_soc, chip->dt.delta_soc,
258 chip->next_wakeup_ms / 1000);
Anirudh Ghayale6b2f4a2018-01-02 19:35:40 +0530259
260done_psy:
261 power_supply_changed(chip->qg_psy);
262done:
263 mutex_unlock(&chip->soc_lock);
264 return rc;
265}
266
267int qg_soc_init(struct qpnp_qg *chip)
268{
269 if (alarmtimer_get_rtcdev()) {
270 alarm_init(&chip->alarm_timer, ALARM_BOOTTIME,
271 qpnp_msoc_timer);
272 } else {
273 pr_err("Failed to get soc alarm-timer\n");
274 return -EINVAL;
275 }
276 INIT_WORK(&chip->scale_soc_work, scale_soc_work);
277
278 return 0;
279}
280
281void qg_soc_exit(struct qpnp_qg *chip)
282{
283 alarm_cancel(&chip->alarm_timer);
284}