blob: 1ad1321e0e9079eaecb8def3e50a6ec4f175bf20 [file] [log] [blame]
Abhijeet Dharmapurikar50c0f2c2017-01-04 19:18:32 -08001/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07002 *
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#include <linux/device.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/regmap.h>
17#include <linux/power_supply.h>
18#include <linux/interrupt.h>
19#include <linux/of.h>
20#include <linux/of_irq.h>
21#include <linux/qpnp/qpnp-revid.h>
22#include "pmic-voter.h"
23
24#define QNOVO_REVISION1 0x00
25#define QNOVO_REVISION2 0x01
26#define QNOVO_PERPH_TYPE 0x04
27#define QNOVO_PERPH_SUBTYPE 0x05
28#define QNOVO_PTTIME_STS 0x07
29#define QNOVO_PTRAIN_STS 0x08
30#define QNOVO_ERROR_STS 0x09
31#define QNOVO_ERROR_BIT BIT(0)
32#define QNOVO_INT_RT_STS 0x10
33#define QNOVO_INT_SET_TYPE 0x11
34#define QNOVO_INT_POLARITY_HIGH 0x12
35#define QNOVO_INT_POLARITY_LOW 0x13
36#define QNOVO_INT_LATCHED_CLR 0x14
37#define QNOVO_INT_EN_SET 0x15
38#define QNOVO_INT_EN_CLR 0x16
39#define QNOVO_INT_LATCHED_STS 0x18
40#define QNOVO_INT_PENDING_STS 0x19
41#define QNOVO_INT_MID_SEL 0x1A
42#define QNOVO_INT_PRIORITY 0x1B
43#define QNOVO_PE_CTRL 0x40
44#define QNOVO_PREST1_CTRL 0x41
45#define QNOVO_PPULS1_LSB_CTRL 0x42
46#define QNOVO_PPULS1_MSB_CTRL 0x43
47#define QNOVO_NREST1_CTRL 0x44
48#define QNOVO_NPULS1_CTRL 0x45
49#define QNOVO_PPCNT_CTRL 0x46
50#define QNOVO_VLIM1_LSB_CTRL 0x47
51#define QNOVO_VLIM1_MSB_CTRL 0x48
52#define QNOVO_PTRAIN_EN 0x49
53#define QNOVO_PTRAIN_EN_BIT BIT(0)
54#define QNOVO_PE_CTRL2 0x4A
55#define QNOVO_PREST2_LSB_CTRL 0x50
56#define QNOVO_PREST2_MSB_CTRL 0x51
57#define QNOVO_PPULS2_LSB_CTRL 0x52
58#define QNOVO_PPULS2_MSB_CTRL 0x53
59#define QNOVO_NREST2_CTRL 0x54
60#define QNOVO_NPULS2_CTRL 0x55
61#define QNOVO_VLIM2_LSB_CTRL 0x56
62#define QNOVO_VLIM2_MSB_CTRL 0x57
63#define QNOVO_PVOLT1_LSB 0x60
64#define QNOVO_PVOLT1_MSB 0x61
65#define QNOVO_PCUR1_LSB 0x62
66#define QNOVO_PCUR1_MSB 0x63
67#define QNOVO_PVOLT2_LSB 0x70
68#define QNOVO_PVOLT2_MSB 0x71
69#define QNOVO_RVOLT2_LSB 0x72
70#define QNOVO_RVOLT2_MSB 0x73
71#define QNOVO_PCUR2_LSB 0x74
72#define QNOVO_PCUR2_MSB 0x75
73#define QNOVO_SCNT 0x80
74#define QNOVO_VMAX_LSB 0x90
75#define QNOVO_VMAX_MSB 0x91
76#define QNOVO_SNUM 0x92
77
78/* Registers ending in 0 imply external rsense */
79#define QNOVO_IADC_OFFSET_0 0xA0
80#define QNOVO_IADC_OFFSET_1 0xA1
81#define QNOVO_IADC_GAIN_0 0xA2
82#define QNOVO_IADC_GAIN_1 0xA3
83#define QNOVO_VADC_OFFSET 0xA4
84#define QNOVO_VADC_GAIN 0xA5
85#define QNOVO_IADC_GAIN_2 0xA6
86#define QNOVO_SPARE 0xA7
87#define QNOVO_STRM_CTRL 0xA8
88#define QNOVO_IADC_OFFSET_OVR_VAL 0xA9
89#define QNOVO_IADC_OFFSET_OVR 0xAA
90#define QNOVO_DISABLE_CHARGING 0xAB
91
92#define QNOVO_TR_IADC_OFFSET_0 0xF1
93#define QNOVO_TR_IADC_OFFSET_1 0xF2
94
95#define DRV_MAJOR_VERSION 1
96#define DRV_MINOR_VERSION 0
97
98#define IADC_LSB_NA 2441400
99#define VADC_LSB_NA 1220700
100#define GAIN_LSB_FACTOR 976560
101
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700102#define USER_VOTER "user_voter"
103#define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter"
104
105#define QNOVO_VOTER "qnovo_voter"
106
107struct qnovo_dt_props {
108 bool external_rsense;
109 struct device_node *revid_dev_node;
110};
111
112enum {
113 QNOVO_ERASE_OFFSET_WA_BIT = BIT(0),
114 QNOVO_NO_ERR_STS_BIT = BIT(1),
115};
116
117struct chg_props {
118 bool charging;
119 bool usb_online;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700120 bool dc_online;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700121};
122
123struct chg_status {
124 bool ok_to_qnovo;
125};
126
127struct qnovo {
128 int base;
129 struct mutex write_lock;
130 struct regmap *regmap;
131 struct qnovo_dt_props dt;
132 struct device *dev;
133 struct votable *disable_votable;
134 struct class qnovo_class;
135 struct pmic_revid_data *pmic_rev_id;
136 u32 wa_flags;
137 s64 external_offset_nA;
138 s64 internal_offset_nA;
139 s64 offset_nV;
140 s64 external_i_gain_mega;
141 s64 internal_i_gain_mega;
142 s64 v_gain_mega;
143 struct notifier_block nb;
144 struct power_supply *batt_psy;
145 struct power_supply *usb_psy;
146 struct power_supply *dc_psy;
147 struct chg_props cp;
148 struct chg_status cs;
149 struct work_struct status_change_work;
150 int fv_uV_request;
151 int fcc_uA_request;
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700152 struct votable *fcc_max_votable;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700153 struct votable *fv_votable;
154};
155
156static int debug_mask;
157module_param_named(debug_mask, debug_mask, int, 0600);
158
159#define qnovo_dbg(chip, reason, fmt, ...) \
160 do { \
161 if (debug_mask & (reason)) \
162 dev_info(chip->dev, fmt, ##__VA_ARGS__); \
163 else \
164 dev_dbg(chip->dev, fmt, ##__VA_ARGS__); \
165 } while (0)
166
167static bool is_secure(struct qnovo *chip, int addr)
168{
169 /* assume everything above 0x40 is secure */
170 return (bool)(addr >= 0x40);
171}
172
173static int qnovo_read(struct qnovo *chip, u16 addr, u8 *buf, int len)
174{
175 return regmap_bulk_read(chip->regmap, chip->base + addr, buf, len);
176}
177
178static int qnovo_masked_write(struct qnovo *chip, u16 addr, u8 mask, u8 val)
179{
180 int rc = 0;
181
182 mutex_lock(&chip->write_lock);
183 if (is_secure(chip, addr)) {
184 rc = regmap_write(chip->regmap,
185 ((chip->base + addr) & ~(0xFF)) | 0xD0, 0xA5);
186 if (rc < 0)
187 goto unlock;
188 }
189
190 rc = regmap_update_bits(chip->regmap, chip->base + addr, mask, val);
191
192unlock:
193 mutex_unlock(&chip->write_lock);
194 return rc;
195}
196
197static int qnovo_write(struct qnovo *chip, u16 addr, u8 *buf, int len)
198{
199 int i, rc = 0;
200 bool is_start_secure, is_end_secure;
201
202 is_start_secure = is_secure(chip, addr);
203 is_end_secure = is_secure(chip, addr + len);
204
205 if (!is_start_secure && !is_end_secure) {
206 mutex_lock(&chip->write_lock);
207 rc = regmap_bulk_write(chip->regmap, chip->base + addr,
208 buf, len);
209 goto unlock;
210 }
211
212 mutex_lock(&chip->write_lock);
213 for (i = addr; i < addr + len; i++) {
214 if (is_secure(chip, i)) {
215 rc = regmap_write(chip->regmap,
216 ((chip->base + i) & ~(0xFF)) | 0xD0, 0xA5);
217 if (rc < 0)
218 goto unlock;
219 }
220 rc = regmap_write(chip->regmap, chip->base + i, buf[i - addr]);
221 if (rc < 0)
222 goto unlock;
223 }
224
225unlock:
226 mutex_unlock(&chip->write_lock);
227 return rc;
228}
229
230static int qnovo_disable_cb(struct votable *votable, void *data, int disable,
231 const char *client)
232{
233 struct qnovo *chip = data;
234 int rc = 0;
235
236 if (disable) {
237 if (chip->fv_uV_request != -EINVAL) {
238 if (chip->fv_votable)
239 vote(chip->fv_votable, QNOVO_VOTER, false, 0);
240 }
241 if (chip->fcc_uA_request != -EINVAL) {
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700242 if (chip->fcc_max_votable)
243 vote(chip->fcc_max_votable, QNOVO_VOTER,
244 false, 0);
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700245 }
246 }
247
248 rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
249 disable ? 0 : QNOVO_PTRAIN_EN_BIT);
250 if (rc < 0) {
251 dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
252 disable ? "disable" : "enable", rc);
253 return rc;
254 }
255
256 if (!disable) {
257 if (chip->fv_uV_request != -EINVAL) {
258 if (!chip->fv_votable)
259 chip->fv_votable = find_votable("FV");
260 if (chip->fv_votable)
261 vote(chip->fv_votable, QNOVO_VOTER,
262 true, chip->fv_uV_request);
263 }
264 if (chip->fcc_uA_request != -EINVAL) {
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700265 if (!chip->fcc_max_votable)
266 chip->fcc_max_votable = find_votable("FCC_MAX");
267 if (chip->fcc_max_votable)
268 vote(chip->fcc_max_votable, QNOVO_VOTER,
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700269 true, chip->fcc_uA_request);
270 }
271 }
272
273 return rc;
274}
275
276static int qnovo_parse_dt(struct qnovo *chip)
277{
278 struct device_node *node = chip->dev->of_node;
279 int rc;
280
281 if (!node) {
282 pr_err("device tree node missing\n");
283 return -EINVAL;
284 }
285
286 rc = of_property_read_u32(node, "reg", &chip->base);
287 if (rc < 0) {
288 pr_err("Couldn't read base rc = %d\n", rc);
289 return rc;
290 }
291
292 chip->dt.external_rsense = of_property_read_bool(node,
293 "qcom,external-rsense");
294
295 chip->dt.revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
296 if (!chip->dt.revid_dev_node) {
297 pr_err("Missing qcom,pmic-revid property - driver failed\n");
298 return -EINVAL;
299 }
300
301 return 0;
302}
303
304static int qnovo_check_chg_version(struct qnovo *chip)
305{
306 int rc;
307
308 chip->pmic_rev_id = get_revid_data(chip->dt.revid_dev_node);
309 if (IS_ERR(chip->pmic_rev_id)) {
310 rc = PTR_ERR(chip->pmic_rev_id);
311 if (rc != -EPROBE_DEFER)
312 pr_err("Unable to get pmic_revid rc=%d\n", rc);
313 return rc;
314 }
315
Harry Yang2452b272017-03-06 13:56:14 -0800316 if ((chip->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE)
317 && (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4)) {
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -0700318 chip->wa_flags |= QNOVO_ERASE_OFFSET_WA_BIT;
319 chip->wa_flags |= QNOVO_NO_ERR_STS_BIT;
320 }
321
322 return 0;
323}
324
325enum {
326 VER = 0,
327 OK_TO_QNOVO,
328 ENABLE,
329 FV_REQUEST,
330 FCC_REQUEST,
331 PE_CTRL_REG,
332 PE_CTRL2_REG,
333 PTRAIN_STS_REG,
334 INT_RT_STS_REG,
335 PREST1,
336 PPULS1,
337 NREST1,
338 NPULS1,
339 PPCNT,
340 VLIM1,
341 PVOLT1,
342 PCUR1,
343 PTTIME,
344 PREST2,
345 PPULS2,
346 NREST2,
347 NPULS2,
348 VLIM2,
349 PVOLT2,
350 RVOLT2,
351 PCUR2,
352 SCNT,
353 VMAX,
354 SNUM,
355 VBATT,
356 IBATT,
357 BATTTEMP,
358 BATTSOC,
359};
360
361struct param_info {
362 char *name;
363 int start_addr;
364 int num_regs;
365 int reg_to_unit_multiplier;
366 int reg_to_unit_divider;
367 int reg_to_unit_offset;
368 int min_val;
369 int max_val;
370 char *units_str;
371};
372
373static struct param_info params[] = {
374 [FV_REQUEST] = {
375 .units_str = "uV",
376 },
377 [FCC_REQUEST] = {
378 .units_str = "uA",
379 },
380 [PE_CTRL_REG] = {
381 .name = "CTRL_REG",
382 .start_addr = QNOVO_PE_CTRL,
383 .num_regs = 1,
384 .units_str = "",
385 },
386 [PE_CTRL2_REG] = {
387 .name = "PE_CTRL2_REG",
388 .start_addr = QNOVO_PE_CTRL2,
389 .num_regs = 1,
390 .units_str = "",
391 },
392 [PTRAIN_STS_REG] = {
393 .name = "PTRAIN_STS",
394 .start_addr = QNOVO_PTRAIN_STS,
395 .num_regs = 1,
396 .units_str = "",
397 },
398 [INT_RT_STS_REG] = {
399 .name = "INT_RT_STS",
400 .start_addr = QNOVO_INT_RT_STS,
401 .num_regs = 1,
402 .units_str = "",
403 },
404 [PREST1] = {
405 .name = "PREST1",
406 .start_addr = QNOVO_PREST1_CTRL,
407 .num_regs = 1,
408 .reg_to_unit_multiplier = 5,
409 .reg_to_unit_divider = 1,
410 .min_val = 5,
411 .max_val = 1275,
412 .units_str = "mS",
413 },
414 [PPULS1] = {
415 .name = "PPULS1",
416 .start_addr = QNOVO_PPULS1_LSB_CTRL,
417 .num_regs = 2,
418 .reg_to_unit_multiplier = 1600, /* converts to uC */
419 .reg_to_unit_divider = 1,
420 .min_val = 0,
421 .max_val = 104856000,
422 .units_str = "uC",
423 },
424 [NREST1] = {
425 .name = "NREST1",
426 .start_addr = QNOVO_NREST1_CTRL,
427 .num_regs = 1,
428 .reg_to_unit_multiplier = 5,
429 .reg_to_unit_divider = 1,
430 .min_val = 5,
431 .max_val = 1275,
432 .units_str = "mS",
433 },
434 [NPULS1] = {
435 .name = "NPULS1",
436 .start_addr = QNOVO_NPULS1_CTRL,
437 .num_regs = 1,
438 .reg_to_unit_multiplier = 5,
439 .reg_to_unit_divider = 1,
440 .min_val = 5,
441 .max_val = 1275,
442 .units_str = "mS",
443 },
444 [PPCNT] = {
445 .name = "PPCNT",
446 .start_addr = QNOVO_PPCNT_CTRL,
447 .num_regs = 1,
448 .reg_to_unit_multiplier = 1,
449 .reg_to_unit_divider = 1,
450 .units_str = "pulses",
451 },
452 [VLIM1] = {
453 .name = "VLIM1",
454 .start_addr = QNOVO_VLIM1_LSB_CTRL,
455 .num_regs = 2,
456 .reg_to_unit_multiplier = 610350, /* converts to nV */
457 .reg_to_unit_divider = 1,
458 .min_val = 0,
459 .max_val = 5000000,
460 .units_str = "uV",
461 },
462 [PVOLT1] = {
463 .name = "PVOLT1",
464 .start_addr = QNOVO_PVOLT1_LSB,
465 .num_regs = 2,
466 .reg_to_unit_multiplier = 610350, /* converts to nV */
467 .reg_to_unit_divider = 1,
468 .units_str = "uV",
469 },
470 [PCUR1] = {
471 .name = "PCUR1",
472 .start_addr = QNOVO_PCUR1_LSB,
473 .num_regs = 2,
474 .reg_to_unit_multiplier = 1220700, /* converts to nA */
475 .reg_to_unit_divider = 1,
476 .units_str = "uA",
477 },
478 [PTTIME] = {
479 .name = "PTTIME",
480 .start_addr = QNOVO_PTTIME_STS,
481 .num_regs = 1,
482 .reg_to_unit_multiplier = 2,
483 .reg_to_unit_divider = 1,
484 .min_val = 5,
485 .max_val = 1275,
486 .units_str = "S",
487 },
488 [PREST2] = {
489 .name = "PREST2",
490 .start_addr = QNOVO_PREST2_LSB_CTRL,
491 .num_regs = 2,
492 .reg_to_unit_multiplier = 5,
493 .reg_to_unit_divider = 1,
494 .min_val = 5,
495 .max_val = 327675,
496 .units_str = "mS",
497 },
498 [PPULS2] = {
499 .name = "PPULS2",
500 .start_addr = QNOVO_PPULS2_LSB_CTRL,
501 .num_regs = 2,
502 .reg_to_unit_multiplier = 1600, /* converts to uC */
503 .reg_to_unit_divider = 1,
504 .min_val = 0,
505 .max_val = 104856000,
506 .units_str = "uC",
507 },
508 [NREST2] = {
509 .name = "NREST2",
510 .start_addr = QNOVO_NREST2_CTRL,
511 .num_regs = 1,
512 .reg_to_unit_multiplier = 5,
513 .reg_to_unit_divider = 1,
514 .reg_to_unit_offset = -5,
515 .min_val = 5,
516 .max_val = 1280,
517 .units_str = "mS",
518 },
519 [NPULS2] = {
520 .name = "NPULS2",
521 .start_addr = QNOVO_NPULS2_CTRL,
522 .num_regs = 1,
523 .reg_to_unit_multiplier = 5,
524 .reg_to_unit_divider = 1,
525 .min_val = 5,
526 .max_val = 1275,
527 .units_str = "mS",
528 },
529 [VLIM2] = {
530 .name = "VLIM1",
531 .start_addr = QNOVO_VLIM2_LSB_CTRL,
532 .num_regs = 2,
533 .reg_to_unit_multiplier = 610350, /* converts to nV */
534 .reg_to_unit_divider = 1,
535 .min_val = 0,
536 .max_val = 5000000,
537 .units_str = "uV",
538 },
539 [PVOLT2] = {
540 .name = "PVOLT2",
541 .start_addr = QNOVO_PVOLT2_LSB,
542 .num_regs = 2,
543 .reg_to_unit_multiplier = 610350, /* converts to nV */
544 .reg_to_unit_divider = 1,
545 .units_str = "uV",
546 },
547 [RVOLT2] = {
548 .name = "RVOLT2",
549 .start_addr = QNOVO_RVOLT2_LSB,
550 .num_regs = 2,
551 .reg_to_unit_multiplier = 610350,
552 .reg_to_unit_divider = 1,
553 .units_str = "uV",
554 },
555 [PCUR2] = {
556 .name = "PCUR2",
557 .start_addr = QNOVO_PCUR2_LSB,
558 .num_regs = 2,
559 .reg_to_unit_multiplier = 1220700, /* converts to nA */
560 .reg_to_unit_divider = 1,
561 .units_str = "uA",
562 },
563 [SCNT] = {
564 .name = "SCNT",
565 .start_addr = QNOVO_SCNT,
566 .num_regs = 1,
567 .reg_to_unit_multiplier = 1,
568 .reg_to_unit_divider = 1,
569 .units_str = "pulses",
570 },
571 [VMAX] = {
572 .name = "VMAX",
573 .start_addr = QNOVO_VMAX_LSB,
574 .num_regs = 2,
575 .reg_to_unit_multiplier = 814000, /* converts to nV */
576 .reg_to_unit_divider = 1,
577 .units_str = "uV",
578 },
579 [SNUM] = {
580 .name = "SNUM",
581 .start_addr = QNOVO_SNUM,
582 .num_regs = 1,
583 .reg_to_unit_multiplier = 1,
584 .reg_to_unit_divider = 1,
585 .units_str = "pulses",
586 },
587 [VBATT] = {
588 .name = "POWER_SUPPLY_PROP_VOLTAGE_NOW",
589 .start_addr = POWER_SUPPLY_PROP_VOLTAGE_NOW,
590 .units_str = "uV",
591 },
592 [IBATT] = {
593 .name = "POWER_SUPPLY_PROP_CURRENT_NOW",
594 .start_addr = POWER_SUPPLY_PROP_CURRENT_NOW,
595 .units_str = "uA",
596 },
597 [BATTTEMP] = {
598 .name = "POWER_SUPPLY_PROP_TEMP",
599 .start_addr = POWER_SUPPLY_PROP_TEMP,
600 .units_str = "uV",
601 },
602 [BATTSOC] = {
603 .name = "POWER_SUPPLY_PROP_CAPACITY",
604 .start_addr = POWER_SUPPLY_PROP_CAPACITY,
605 .units_str = "%",
606 },
607};
608
609static struct class_attribute qnovo_attributes[];
610
611static ssize_t version_show(struct class *c, struct class_attribute *attr,
612 char *buf)
613{
614 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
615 DRV_MAJOR_VERSION, DRV_MINOR_VERSION);
616}
617
618static ssize_t ok_to_qnovo_show(struct class *c, struct class_attribute *attr,
619 char *buf)
620{
621 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
622
623 return snprintf(buf, PAGE_SIZE, "%d\n", chip->cs.ok_to_qnovo);
624}
625
626static ssize_t enable_show(struct class *c, struct class_attribute *attr,
627 char *ubuf)
628{
629 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
630 int val;
631
632 val = get_client_vote(chip->disable_votable, USER_VOTER);
633 return snprintf(ubuf, PAGE_SIZE, "%d\n", val);
634}
635
636static ssize_t enable_store(struct class *c, struct class_attribute *attr,
637 const char *ubuf, size_t count)
638{
639 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
640 unsigned long val;
641 bool disable;
642
643 if (kstrtoul(ubuf, 10, &val))
644 return -EINVAL;
645
646 disable = !val;
647
648 vote(chip->disable_votable, USER_VOTER, disable, 0);
649 return count;
650}
651
652static ssize_t val_show(struct class *c, struct class_attribute *attr,
653 char *ubuf)
654{
655 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
656 int i = attr - qnovo_attributes;
657 int val = 0;
658
659 if (i == FV_REQUEST)
660 val = chip->fv_uV_request;
661
662 if (i == FCC_REQUEST)
663 val = chip->fcc_uA_request;
664
665 return snprintf(ubuf, PAGE_SIZE, "%d%s\n", val, params[i].units_str);
666}
667
668static ssize_t val_store(struct class *c, struct class_attribute *attr,
669 const char *ubuf, size_t count)
670{
671 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
672 int i = attr - qnovo_attributes;
673 unsigned long val;
674
675 if (kstrtoul(ubuf, 10, &val))
676 return -EINVAL;
677
678 if (i == FV_REQUEST)
679 chip->fv_uV_request = val;
680
681 if (i == FCC_REQUEST)
682 chip->fcc_uA_request = val;
683
684 return count;
685}
686
687static ssize_t reg_show(struct class *c, struct class_attribute *attr,
688 char *ubuf)
689{
690 int i = attr - qnovo_attributes;
691 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
692 u8 buf[2] = {0, 0};
693 u16 regval;
694 int rc;
695
696 rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
697 if (rc < 0) {
698 pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
699 return -EINVAL;
700 }
701 regval = buf[1] << 8 | buf[0];
702
703 return snprintf(ubuf, PAGE_SIZE, "0x%04x%s\n",
704 regval, params[i].units_str);
705}
706
707static ssize_t reg_store(struct class *c, struct class_attribute *attr,
708 const char *ubuf, size_t count)
709{
710 int i = attr - qnovo_attributes;
711 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
712 u8 buf[2] = {0, 0};
713 unsigned long val;
714 int rc;
715
716 if (kstrtoul(ubuf, 16, &val))
717 return -EINVAL;
718
719 buf[0] = val & 0xFF;
720 buf[1] = (val >> 8) & 0xFF;
721
722 rc = qnovo_write(chip, params[i].start_addr, buf, params[i].num_regs);
723 if (rc < 0) {
724 pr_err("Couldn't write %s rc = %d\n", params[i].name, rc);
725 return -EINVAL;
726 }
727 return count;
728}
729
730static ssize_t time_show(struct class *c, struct class_attribute *attr,
731 char *ubuf)
732{
733 int i = attr - qnovo_attributes;
734 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
735 u8 buf[2] = {0, 0};
736 u16 regval;
737 int val;
738 int rc;
739
740 rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
741 if (rc < 0) {
742 pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
743 return -EINVAL;
744 }
745 regval = buf[1] << 8 | buf[0];
746
747 val = ((regval * params[i].reg_to_unit_multiplier)
748 / params[i].reg_to_unit_divider)
749 - params[i].reg_to_unit_offset;
750
751 return snprintf(ubuf, PAGE_SIZE, "%d%s\n", val, params[i].units_str);
752}
753
754static ssize_t time_store(struct class *c, struct class_attribute *attr,
755 const char *ubuf, size_t count)
756{
757 int i = attr - qnovo_attributes;
758 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
759 u8 buf[2] = {0, 0};
760 u16 regval;
761 unsigned long val;
762 int rc;
763
764 if (kstrtoul(ubuf, 10, &val))
765 return -EINVAL;
766
767 if (val < params[i].min_val || val > params[i].max_val) {
768 pr_err("Out of Range %d%s for %s\n", (int)val,
769 params[i].units_str,
770 params[i].name);
771 return -ERANGE;
772 }
773
774 regval = (((int)val + params[i].reg_to_unit_offset)
775 * params[i].reg_to_unit_divider)
776 / params[i].reg_to_unit_multiplier;
777 buf[0] = regval & 0xFF;
778 buf[1] = (regval >> 8) & 0xFF;
779
780 rc = qnovo_write(chip, params[i].start_addr, buf, params[i].num_regs);
781 if (rc < 0) {
782 pr_err("Couldn't write %s rc = %d\n", params[i].name, rc);
783 return -EINVAL;
784 }
785
786 return count;
787}
788
789static ssize_t current_show(struct class *c, struct class_attribute *attr,
790 char *ubuf)
791{
792 int i = attr - qnovo_attributes;
793 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
794 u8 buf[2] = {0, 0};
795 int rc;
796 int comp_val_uA;
797 s64 regval_nA;
798 s64 gain, offset_nA, comp_val_nA;
799
800 rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
801 if (rc < 0) {
802 pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
803 return -EINVAL;
804 }
805 regval_nA = buf[1] << 8 | buf[0];
806 regval_nA = div_s64(regval_nA * params[i].reg_to_unit_multiplier,
807 params[i].reg_to_unit_divider)
808 - params[i].reg_to_unit_offset;
809
810 if (chip->dt.external_rsense) {
811 offset_nA = chip->external_offset_nA;
812 gain = chip->external_i_gain_mega;
813 } else {
814 offset_nA = chip->internal_offset_nA;
815 gain = chip->internal_i_gain_mega;
816 }
817
818 comp_val_nA = div_s64(regval_nA * gain, 1000000) + offset_nA;
819 comp_val_uA = comp_val_nA / 1000;
820
821 return snprintf(ubuf, PAGE_SIZE, "%d%s\n",
822 comp_val_uA, params[i].units_str);
823}
824
825static ssize_t voltage_show(struct class *c, struct class_attribute *attr,
826 char *ubuf)
827{
828 int i = attr - qnovo_attributes;
829 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
830 u8 buf[2] = {0, 0};
831 int rc;
832 int comp_val_uV;
833 s64 regval_nV;
834 s64 gain, offset_nV, comp_val_nV;
835
836 rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
837 if (rc < 0) {
838 pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
839 return -EINVAL;
840 }
841 regval_nV = buf[1] << 8 | buf[0];
842 regval_nV = div_s64(regval_nV * params[i].reg_to_unit_multiplier,
843 params[i].reg_to_unit_divider)
844 - params[i].reg_to_unit_offset;
845
846 offset_nV = chip->offset_nV;
847 gain = chip->v_gain_mega;
848
849 comp_val_nV = div_s64(regval_nV * gain, 1000000) + offset_nV;
850 comp_val_uV = comp_val_nV / 1000;
851
852 return snprintf(ubuf, PAGE_SIZE, "%d%s\n",
853 comp_val_uV, params[i].units_str);
854}
855
856static ssize_t voltage_store(struct class *c, struct class_attribute *attr,
857 const char *ubuf, size_t count)
858{
859 int i = attr - qnovo_attributes;
860 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
861 u8 buf[2] = {0, 0};
862 int rc;
863 unsigned long val_uV;
864 s64 regval_nV;
865 s64 gain, offset_nV;
866
867 if (kstrtoul(ubuf, 10, &val_uV))
868 return -EINVAL;
869
870 if (val_uV < params[i].min_val || val_uV > params[i].max_val) {
871 pr_err("Out of Range %d%s for %s\n", (int)val_uV,
872 params[i].units_str,
873 params[i].name);
874 return -ERANGE;
875 }
876
877 offset_nV = chip->offset_nV;
878 gain = chip->v_gain_mega;
879
880 regval_nV = (s64)val_uV * 1000 - offset_nV;
881 regval_nV = div_s64(regval_nV * 1000000, gain);
882
883 regval_nV = div_s64((regval_nV + params[i].reg_to_unit_offset)
884 * params[i].reg_to_unit_divider,
885 params[i].reg_to_unit_multiplier);
886 buf[0] = regval_nV & 0xFF;
887 buf[1] = ((u64)regval_nV >> 8) & 0xFF;
888
889 rc = qnovo_write(chip, params[i].start_addr, buf, params[i].num_regs);
890 if (rc < 0) {
891 pr_err("Couldn't write %s rc = %d\n", params[i].name, rc);
892 return -EINVAL;
893 }
894
895 return count;
896}
897
898static ssize_t coulomb_show(struct class *c, struct class_attribute *attr,
899 char *ubuf)
900{
901 int i = attr - qnovo_attributes;
902 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
903 u8 buf[2] = {0, 0};
904 int rc;
905 int comp_val_uC;
906 s64 regval_uC, gain;
907
908 rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
909 if (rc < 0) {
910 pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
911 return -EINVAL;
912 }
913 regval_uC = buf[1] << 8 | buf[0];
914 regval_uC = div_s64(regval_uC * params[i].reg_to_unit_multiplier,
915 params[i].reg_to_unit_divider)
916 - params[i].reg_to_unit_offset;
917
918 if (chip->dt.external_rsense)
919 gain = chip->external_i_gain_mega;
920 else
921 gain = chip->internal_i_gain_mega;
922
923 comp_val_uC = div_s64(regval_uC * gain, 1000000);
924 return snprintf(ubuf, PAGE_SIZE, "%d%s\n",
925 comp_val_uC, params[i].units_str);
926}
927
928static ssize_t coulomb_store(struct class *c, struct class_attribute *attr,
929 const char *ubuf, size_t count)
930{
931 int i = attr - qnovo_attributes;
932 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
933 u8 buf[2] = {0, 0};
934 int rc;
935 unsigned long val_uC;
936 s64 regval;
937 s64 gain;
938
939 if (kstrtoul(ubuf, 10, &val_uC))
940 return -EINVAL;
941
942 if (val_uC < params[i].min_val || val_uC > params[i].max_val) {
943 pr_err("Out of Range %d%s for %s\n", (int)val_uC,
944 params[i].units_str,
945 params[i].name);
946 return -ERANGE;
947 }
948
949 if (chip->dt.external_rsense)
950 gain = chip->external_i_gain_mega;
951 else
952 gain = chip->internal_i_gain_mega;
953
954 regval = div_s64((s64)val_uC * 1000000, gain);
955
956 regval = div_s64((regval + params[i].reg_to_unit_offset)
957 * params[i].reg_to_unit_divider,
958 params[i].reg_to_unit_multiplier);
959
960 buf[0] = regval & 0xFF;
961 buf[1] = ((u64)regval >> 8) & 0xFF;
962
963 rc = qnovo_write(chip, params[i].start_addr, buf, params[i].num_regs);
964 if (rc < 0) {
965 pr_err("Couldn't write %s rc = %d\n", params[i].name, rc);
966 return -EINVAL;
967 }
968
969 return count;
970}
971
972static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr,
973 char *ubuf)
974{
975 int i = attr - qnovo_attributes;
976 struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
977 int rc = -EINVAL;
978 int prop = params[i].start_addr;
979 union power_supply_propval pval = {0};
980
981 if (!chip->batt_psy)
982 chip->batt_psy = power_supply_get_by_name("battery");
983
984 if (!chip->batt_psy)
985 return -EINVAL;
986
987 rc = power_supply_get_property(chip->batt_psy, prop, &pval);
988 if (rc < 0) {
989 pr_err("Couldn't read battery prop %s rc = %d\n",
990 params[i].name, rc);
991 return -EINVAL;
992 }
993
994 return snprintf(ubuf, PAGE_SIZE, "%d%s\n",
995 pval.intval, params[i].units_str);
996}
997
998static struct class_attribute qnovo_attributes[] = {
999 [VER] = __ATTR_RO(version),
1000 [OK_TO_QNOVO] = __ATTR_RO(ok_to_qnovo),
1001 [ENABLE] = __ATTR(enable, 0644,
1002 enable_show, enable_store),
1003 [FV_REQUEST] = __ATTR(fv_uV_request, 0644,
1004 val_show, val_store),
1005 [FCC_REQUEST] = __ATTR(fcc_uA_request, 0644,
1006 val_show, val_store),
1007 [PE_CTRL_REG] = __ATTR(PE_CTRL_REG, 0644,
1008 reg_show, reg_store),
1009 [PE_CTRL2_REG] = __ATTR(PE_CTRL2_REG, 0644,
1010 reg_show, reg_store),
1011 [PTRAIN_STS_REG] = __ATTR(PTRAIN_STS_REG, 0644,
1012 reg_show, reg_store),
1013 [INT_RT_STS_REG] = __ATTR(INT_RT_STS_REG, 0644,
1014 reg_show, reg_store),
1015 [PREST1] = __ATTR(PREST1_mS, 0644,
1016 time_show, time_store),
1017 [PPULS1] = __ATTR(PPULS1_uC, 0644,
1018 coulomb_show, coulomb_store),
1019 [NREST1] = __ATTR(NREST1_mS, 0644,
1020 time_show, time_store),
1021 [NPULS1] = __ATTR(NPULS1_mS, 0644,
1022 time_show, time_store),
1023 [PPCNT] = __ATTR(PPCNT, 0644,
1024 time_show, time_store),
1025 [VLIM1] = __ATTR(VLIM1_uV, 0644,
1026 voltage_show, voltage_store),
1027 [PVOLT1] = __ATTR(PVOLT1_uV, 0444,
1028 voltage_show, NULL),
1029 [PCUR1] = __ATTR(PCUR1_uA, 0444,
1030 current_show, NULL),
1031 [PTTIME] = __ATTR(PTTIME_S, 0444,
1032 time_show, NULL),
1033 [PREST2] = __ATTR(PREST2_mS, 0644,
1034 time_show, time_store),
1035 [PPULS2] = __ATTR(PPULS2_mS, 0644,
1036 coulomb_show, coulomb_store),
1037 [NREST2] = __ATTR(NREST2_mS, 0644,
1038 time_show, time_store),
1039 [NPULS2] = __ATTR(NPULS2_mS, 0644,
1040 time_show, time_store),
1041 [VLIM2] = __ATTR(VLIM2_uV, 0644,
1042 voltage_show, voltage_store),
1043 [PVOLT2] = __ATTR(PVOLT2_uV, 0444,
1044 voltage_show, NULL),
1045 [RVOLT2] = __ATTR(RVOLT2_uV, 0444,
1046 voltage_show, NULL),
1047 [PCUR2] = __ATTR(PCUR2_uA, 0444,
1048 current_show, NULL),
1049 [SCNT] = __ATTR(SCNT, 0644,
1050 time_show, time_store),
1051 [VMAX] = __ATTR(VMAX_uV, 0444,
1052 voltage_show, NULL),
1053 [SNUM] = __ATTR(SNUM, 0644,
1054 time_show, time_store),
1055 [VBATT] = __ATTR(VBATT_uV, 0444,
1056 batt_prop_show, NULL),
1057 [IBATT] = __ATTR(IBATT_uA, 0444,
1058 batt_prop_show, NULL),
1059 [BATTTEMP] = __ATTR(BATTTEMP_deciDegC, 0444,
1060 batt_prop_show, NULL),
1061 [BATTSOC] = __ATTR(BATTSOC, 0444,
1062 batt_prop_show, NULL),
1063 __ATTR_NULL,
1064};
1065
1066static void get_chg_props(struct qnovo *chip, struct chg_props *cp)
1067{
1068 union power_supply_propval pval;
1069 u8 val = 0;
1070 int rc;
1071
1072 cp->charging = true;
1073 rc = qnovo_read(chip, QNOVO_ERROR_STS, &val, 1);
1074 if (rc < 0) {
1075 pr_err("Couldn't read error sts rc = %d\n", rc);
1076 cp->charging = false;
1077 } else {
1078 cp->charging = (!(val & QNOVO_ERROR_BIT));
1079 }
1080
1081 if (chip->wa_flags & QNOVO_NO_ERR_STS_BIT) {
1082 /*
1083 * on v1.0 and v1.1 pmic's force charging to true
1084 * if things are not good to charge s/w gets a PTRAIN_DONE
1085 * interrupt
1086 */
1087 cp->charging = true;
1088 }
1089
1090 cp->usb_online = false;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07001091 if (!chip->usb_psy)
1092 chip->usb_psy = power_supply_get_by_name("usb");
1093 if (chip->usb_psy) {
1094 rc = power_supply_get_property(chip->usb_psy,
1095 POWER_SUPPLY_PROP_ONLINE, &pval);
1096 if (rc < 0)
1097 pr_err("Couldn't read usb online rc = %d\n", rc);
1098 else
1099 cp->usb_online = (bool)pval.intval;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07001100 }
1101
1102 cp->dc_online = false;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07001103 if (!chip->dc_psy)
1104 chip->dc_psy = power_supply_get_by_name("dc");
1105 if (chip->dc_psy) {
1106 rc = power_supply_get_property(chip->dc_psy,
1107 POWER_SUPPLY_PROP_ONLINE, &pval);
1108 if (rc < 0)
1109 pr_err("Couldn't read dc online rc = %d\n", rc);
1110 else
1111 cp->dc_online = (bool)pval.intval;
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07001112 }
1113}
1114
1115static void get_chg_status(struct qnovo *chip, const struct chg_props *cp,
1116 struct chg_status *cs)
1117{
1118 cs->ok_to_qnovo = false;
1119
1120 if (cp->charging &&
Abhijeet Dharmapurikar50c0f2c2017-01-04 19:18:32 -08001121 (cp->usb_online || cp->dc_online))
Abhijeet Dharmapurikar21f9af1d2016-05-10 18:48:39 -07001122 cs->ok_to_qnovo = true;
1123}
1124
1125static void status_change_work(struct work_struct *work)
1126{
1127 struct qnovo *chip = container_of(work,
1128 struct qnovo, status_change_work);
1129 bool notify_uevent = false;
1130 struct chg_props cp;
1131 struct chg_status cs;
1132
1133 get_chg_props(chip, &cp);
1134 get_chg_status(chip, &cp, &cs);
1135
1136 if (cs.ok_to_qnovo ^ chip->cs.ok_to_qnovo) {
1137 /*
1138 * when it is not okay to Qnovo charge, disable both voters,
1139 * so that when it becomes okay to Qnovo charge the user voter
1140 * has to specifically enable its vote to being Qnovo charging
1141 */
1142 if (!cs.ok_to_qnovo) {
1143 vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 1, 0);
1144 vote(chip->disable_votable, USER_VOTER, 1, 0);
1145 } else {
1146 vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 0, 0);
1147 }
1148 notify_uevent = true;
1149 }
1150
1151 memcpy(&chip->cp, &cp, sizeof(struct chg_props));
1152 memcpy(&chip->cs, &cs, sizeof(struct chg_status));
1153
1154 if (notify_uevent)
1155 kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
1156}
1157
1158static int qnovo_notifier_call(struct notifier_block *nb,
1159 unsigned long ev, void *v)
1160{
1161 struct power_supply *psy = v;
1162 struct qnovo *chip = container_of(nb, struct qnovo, nb);
1163
1164 if (ev != PSY_EVENT_PROP_CHANGED)
1165 return NOTIFY_OK;
1166 if ((strcmp(psy->desc->name, "battery") == 0)
1167 || (strcmp(psy->desc->name, "usb") == 0))
1168 schedule_work(&chip->status_change_work);
1169
1170 return NOTIFY_OK;
1171}
1172
1173static irqreturn_t handle_ptrain_done(int irq, void *data)
1174{
1175 struct qnovo *chip = data;
1176
1177 /* disable user voter here */
1178 vote(chip->disable_votable, USER_VOTER, 0, 0);
1179 kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
1180 return IRQ_HANDLED;
1181}
1182
1183static int qnovo_hw_init(struct qnovo *chip)
1184{
1185 int rc;
1186 u8 iadc_offset_external, iadc_offset_internal;
1187 u8 iadc_gain_external, iadc_gain_internal;
1188 u8 vadc_offset, vadc_gain;
1189 u8 buf[2] = {0, 0};
1190
1191 vote(chip->disable_votable, USER_VOTER, 1, 0);
1192
1193 rc = qnovo_read(chip, QNOVO_IADC_OFFSET_0, &iadc_offset_external, 1);
1194 if (rc < 0) {
1195 pr_err("Couldn't read iadc exernal offset rc = %d\n", rc);
1196 return rc;
1197 }
1198
1199 rc = qnovo_read(chip, QNOVO_IADC_OFFSET_1, &iadc_offset_internal, 1);
1200 if (rc < 0) {
1201 pr_err("Couldn't read iadc internal offset rc = %d\n", rc);
1202 return rc;
1203 }
1204
1205 rc = qnovo_read(chip, QNOVO_IADC_GAIN_0, &iadc_gain_external, 1);
1206 if (rc < 0) {
1207 pr_err("Couldn't read iadc external gain rc = %d\n", rc);
1208 return rc;
1209 }
1210
1211 rc = qnovo_read(chip, QNOVO_IADC_GAIN_1, &iadc_gain_internal, 1);
1212 if (rc < 0) {
1213 pr_err("Couldn't read iadc internal gain rc = %d\n", rc);
1214 return rc;
1215 }
1216
1217 rc = qnovo_read(chip, QNOVO_VADC_OFFSET, &vadc_offset, 1);
1218 if (rc < 0) {
1219 pr_err("Couldn't read vadc offset rc = %d\n", rc);
1220 return rc;
1221 }
1222
1223 rc = qnovo_read(chip, QNOVO_VADC_GAIN, &vadc_gain, 1);
1224 if (rc < 0) {
1225 pr_err("Couldn't read vadc external gain rc = %d\n", rc);
1226 return rc;
1227 }
1228
1229 chip->external_offset_nA = (s64)iadc_offset_external * IADC_LSB_NA;
1230 chip->internal_offset_nA = (s64)iadc_offset_internal * IADC_LSB_NA;
1231 chip->offset_nV = (s64)vadc_offset * VADC_LSB_NA;
1232 chip->external_i_gain_mega
1233 = 1000000000 + (s64)iadc_gain_external * GAIN_LSB_FACTOR;
1234 chip->external_i_gain_mega
1235 = div_s64(chip->external_i_gain_mega, 1000);
1236 chip->internal_i_gain_mega
1237 = 1000000000 + (s64)iadc_gain_internal * GAIN_LSB_FACTOR;
1238 chip->internal_i_gain_mega
1239 = div_s64(chip->internal_i_gain_mega, 1000);
1240 chip->v_gain_mega = 1000000000 + (s64)vadc_gain * GAIN_LSB_FACTOR;
1241 chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000);
1242
1243 if (chip->wa_flags & QNOVO_ERASE_OFFSET_WA_BIT) {
1244 rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_0, buf, 2);
1245 if (rc < 0) {
1246 pr_err("Couldn't erase offset rc = %d\n", rc);
1247 return rc;
1248 }
1249 }
1250 return 0;
1251}
1252
1253static int qnovo_register_notifier(struct qnovo *chip)
1254{
1255 int rc;
1256
1257 chip->nb.notifier_call = qnovo_notifier_call;
1258 rc = power_supply_reg_notifier(&chip->nb);
1259 if (rc < 0) {
1260 pr_err("Couldn't register psy notifier rc = %d\n", rc);
1261 return rc;
1262 }
1263
1264 return 0;
1265}
1266
1267static int qnovo_determine_initial_status(struct qnovo *chip)
1268{
1269 status_change_work(&chip->status_change_work);
1270 return 0;
1271}
1272
1273static int qnovo_request_interrupts(struct qnovo *chip)
1274{
1275 int rc = 0;
1276 int irq_ptrain_done = of_irq_get_byname(chip->dev->of_node,
1277 "ptrain-done");
1278
1279 rc = devm_request_threaded_irq(chip->dev, irq_ptrain_done, NULL,
1280 handle_ptrain_done,
1281 IRQF_ONESHOT, "ptrain-done", chip);
1282 if (rc < 0) {
1283 pr_err("Couldn't request irq %d rc = %d\n",
1284 irq_ptrain_done, rc);
1285 return rc;
1286 }
1287 return rc;
1288}
1289
1290static int qnovo_probe(struct platform_device *pdev)
1291{
1292 struct qnovo *chip;
1293 int rc = 0;
1294
1295 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
1296 if (!chip)
1297 return -ENOMEM;
1298
1299 chip->fv_uV_request = -EINVAL;
1300 chip->fcc_uA_request = -EINVAL;
1301 chip->dev = &pdev->dev;
1302 mutex_init(&chip->write_lock);
1303
1304 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
1305 if (!chip->regmap) {
1306 pr_err("parent regmap is missing\n");
1307 return -EINVAL;
1308 }
1309
1310 rc = qnovo_parse_dt(chip);
1311 if (rc < 0) {
1312 pr_err("Couldn't parse device tree rc=%d\n", rc);
1313 return rc;
1314 }
1315
1316 rc = qnovo_check_chg_version(chip);
1317 if (rc < 0) {
1318 if (rc != -EPROBE_DEFER)
1319 pr_err("Couldn't check version rc=%d\n", rc);
1320 return rc;
1321 }
1322
1323 /* set driver data before resources request it */
1324 platform_set_drvdata(pdev, chip);
1325
1326 chip->disable_votable = create_votable("QNOVO_DISABLE", VOTE_SET_ANY,
1327 qnovo_disable_cb, chip);
1328 if (IS_ERR(chip->disable_votable)) {
1329 rc = PTR_ERR(chip->disable_votable);
1330 goto cleanup;
1331 }
1332
1333 INIT_WORK(&chip->status_change_work, status_change_work);
1334
1335 rc = qnovo_hw_init(chip);
1336 if (rc < 0) {
1337 pr_err("Couldn't initialize hardware rc=%d\n", rc);
1338 goto destroy_votable;
1339 }
1340
1341 rc = qnovo_register_notifier(chip);
1342 if (rc < 0) {
1343 pr_err("Couldn't register psy notifier rc = %d\n", rc);
1344 goto unreg_notifier;
1345 }
1346
1347 rc = qnovo_determine_initial_status(chip);
1348 if (rc < 0) {
1349 pr_err("Couldn't determine initial status rc=%d\n", rc);
1350 goto unreg_notifier;
1351 }
1352
1353 rc = qnovo_request_interrupts(chip);
1354 if (rc < 0) {
1355 pr_err("Couldn't request interrupts rc=%d\n", rc);
1356 goto unreg_notifier;
1357 }
1358 chip->qnovo_class.name = "qnovo",
1359 chip->qnovo_class.owner = THIS_MODULE,
1360 chip->qnovo_class.class_attrs = qnovo_attributes;
1361
1362 rc = class_register(&chip->qnovo_class);
1363 if (rc < 0) {
1364 pr_err("couldn't register qnovo sysfs class rc = %d\n", rc);
1365 goto unreg_notifier;
1366 }
1367
1368 return rc;
1369
1370unreg_notifier:
1371 power_supply_unreg_notifier(&chip->nb);
1372destroy_votable:
1373 destroy_votable(chip->disable_votable);
1374cleanup:
1375 platform_set_drvdata(pdev, NULL);
1376 return rc;
1377}
1378
1379static int qnovo_remove(struct platform_device *pdev)
1380{
1381 struct qnovo *chip = platform_get_drvdata(pdev);
1382
1383 class_unregister(&chip->qnovo_class);
1384 power_supply_unreg_notifier(&chip->nb);
1385 destroy_votable(chip->disable_votable);
1386 platform_set_drvdata(pdev, NULL);
1387 return 0;
1388}
1389
1390static const struct of_device_id match_table[] = {
1391 { .compatible = "qcom,qpnp-qnovo", },
1392 { },
1393};
1394
1395static struct platform_driver qnovo_driver = {
1396 .driver = {
1397 .name = "qcom,qnovo-driver",
1398 .owner = THIS_MODULE,
1399 .of_match_table = match_table,
1400 },
1401 .probe = qnovo_probe,
1402 .remove = qnovo_remove,
1403};
1404module_platform_driver(qnovo_driver);
1405
1406MODULE_DESCRIPTION("QPNP Qnovo Driver");
1407MODULE_LICENSE("GPL v2");