hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/power/supply/cpcap-charger.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Motorola CPCAP PMIC battery charger driver
34 *
....@@ -7,15 +8,6 @@
78 * on earlier driver found in the Motorola Linux kernel:
89 *
910 * Copyright (C) 2009-2010 Motorola, Inc.
10
- *
11
- * This program is free software; you can redistribute it and/or modify
12
- * it under the terms of the GNU General Public License version 2 as
13
- * published by the Free Software Foundation.
14
- *
15
- * This program is distributed in the hope that it will be useful,
16
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
- * GNU General Public License for more details.
1911 */
2012
2113 #include <linux/atomic.h>
....@@ -116,6 +108,9 @@
116108 #define CPCAP_REG_CRM_ICHRG_1A596 CPCAP_REG_CRM_ICHRG(0xe)
117109 #define CPCAP_REG_CRM_ICHRG_NO_LIMIT CPCAP_REG_CRM_ICHRG(0xf)
118110
111
+/* CPCAP_REG_VUSBC register bits needed for VBUS */
112
+#define CPCAP_BIT_VBUS_SWITCH BIT(0) /* VBUS boost to 5V */
113
+
119114 enum {
120115 CPCAP_CHARGER_IIO_BATTDET,
121116 CPCAP_CHARGER_IIO_VOLTAGE,
....@@ -123,6 +118,13 @@
123118 CPCAP_CHARGER_IIO_CHRG_CURRENT,
124119 CPCAP_CHARGER_IIO_BATT_CURRENT,
125120 CPCAP_CHARGER_IIO_NR,
121
+};
122
+
123
+enum {
124
+ CPCAP_CHARGER_DISCONNECTED,
125
+ CPCAP_CHARGER_DETECTING,
126
+ CPCAP_CHARGER_CHARGING,
127
+ CPCAP_CHARGER_DONE,
126128 };
127129
128130 struct cpcap_charger_ddata {
....@@ -138,10 +140,13 @@
138140 struct power_supply *usb;
139141
140142 struct phy_companion comparator; /* For USB VBUS */
141
- bool vbus_enabled;
143
+ unsigned int vbus_enabled:1;
144
+ unsigned int feeding_vbus:1;
142145 atomic_t active;
143146
144147 int status;
148
+ int state;
149
+ int voltage;
145150 };
146151
147152 struct cpcap_interrupt_desc {
....@@ -157,6 +162,7 @@
157162
158163 bool chrg_se1b;
159164 bool rvrs_mode;
165
+ bool chrgcurr2;
160166 bool chrgcurr1;
161167 bool vbusvld;
162168
....@@ -166,24 +172,26 @@
166172 static enum power_supply_property cpcap_charger_props[] = {
167173 POWER_SUPPLY_PROP_STATUS,
168174 POWER_SUPPLY_PROP_ONLINE,
175
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
169176 POWER_SUPPLY_PROP_VOLTAGE_NOW,
170177 POWER_SUPPLY_PROP_CURRENT_NOW,
171178 };
172179
180
+/* No battery always shows temperature of -40000 */
173181 static bool cpcap_charger_battery_found(struct cpcap_charger_ddata *ddata)
174182 {
175183 struct iio_channel *channel;
176
- int error, value;
184
+ int error, temperature;
177185
178186 channel = ddata->channels[CPCAP_CHARGER_IIO_BATTDET];
179
- error = iio_read_channel_raw(channel, &value);
187
+ error = iio_read_channel_processed(channel, &temperature);
180188 if (error < 0) {
181189 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);
182190
183191 return false;
184192 }
185193
186
- return value == 1;
194
+ return temperature > -20000 && temperature < 60000;
187195 }
188196
189197 static int cpcap_charger_get_charge_voltage(struct cpcap_charger_ddata *ddata)
....@@ -228,6 +236,9 @@
228236 case POWER_SUPPLY_PROP_STATUS:
229237 val->intval = ddata->status;
230238 break;
239
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
240
+ val->intval = ddata->voltage;
241
+ break;
231242 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
232243 if (ddata->status == POWER_SUPPLY_STATUS_CHARGING)
233244 val->intval = cpcap_charger_get_charge_voltage(ddata) *
....@@ -250,6 +261,85 @@
250261 }
251262
252263 return 0;
264
+}
265
+
266
+static int cpcap_charger_match_voltage(int voltage)
267
+{
268
+ switch (voltage) {
269
+ case 0 ... 4100000 - 1: return 3800000;
270
+ case 4100000 ... 4120000 - 1: return 4100000;
271
+ case 4120000 ... 4150000 - 1: return 4120000;
272
+ case 4150000 ... 4170000 - 1: return 4150000;
273
+ case 4170000 ... 4200000 - 1: return 4170000;
274
+ case 4200000 ... 4230000 - 1: return 4200000;
275
+ case 4230000 ... 4250000 - 1: return 4230000;
276
+ case 4250000 ... 4270000 - 1: return 4250000;
277
+ case 4270000 ... 4300000 - 1: return 4270000;
278
+ case 4300000 ... 4330000 - 1: return 4300000;
279
+ case 4330000 ... 4350000 - 1: return 4330000;
280
+ case 4350000 ... 4380000 - 1: return 4350000;
281
+ case 4380000 ... 4400000 - 1: return 4380000;
282
+ case 4400000 ... 4420000 - 1: return 4400000;
283
+ case 4420000 ... 4440000 - 1: return 4420000;
284
+ case 4440000: return 4440000;
285
+ default: return 0;
286
+ }
287
+}
288
+
289
+static int
290
+cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata)
291
+{
292
+ union power_supply_propval prop;
293
+ struct power_supply *battery;
294
+ int voltage = ddata->voltage;
295
+ int error;
296
+
297
+ battery = power_supply_get_by_name("battery");
298
+ if (battery) {
299
+ error = power_supply_get_property(battery,
300
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
301
+ &prop);
302
+ if (!error)
303
+ voltage = prop.intval;
304
+
305
+ power_supply_put(battery);
306
+ }
307
+
308
+ return voltage;
309
+}
310
+
311
+static int cpcap_charger_set_property(struct power_supply *psy,
312
+ enum power_supply_property psp,
313
+ const union power_supply_propval *val)
314
+{
315
+ struct cpcap_charger_ddata *ddata = dev_get_drvdata(psy->dev.parent);
316
+ int voltage, batvolt;
317
+
318
+ switch (psp) {
319
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
320
+ voltage = cpcap_charger_match_voltage(val->intval);
321
+ batvolt = cpcap_charger_get_bat_const_charge_voltage(ddata);
322
+ if (voltage > batvolt)
323
+ voltage = batvolt;
324
+ ddata->voltage = voltage;
325
+ schedule_delayed_work(&ddata->detect_work, 0);
326
+ break;
327
+ default:
328
+ return -EINVAL;
329
+ }
330
+
331
+ return 0;
332
+}
333
+
334
+static int cpcap_charger_property_is_writeable(struct power_supply *psy,
335
+ enum power_supply_property psp)
336
+{
337
+ switch (psp) {
338
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
339
+ return 1;
340
+ default:
341
+ return 0;
342
+ }
253343 }
254344
255345 static void cpcap_charger_set_cable_path(struct cpcap_charger_ddata *ddata,
....@@ -333,7 +423,6 @@
333423 }
334424
335425 /* VBUS control functions for the USB PHY companion */
336
-
337426 static void cpcap_charger_vbus_work(struct work_struct *work)
338427 {
339428 struct cpcap_charger_ddata *ddata;
....@@ -351,10 +440,17 @@
351440 return;
352441 }
353442
443
+ ddata->feeding_vbus = true;
354444 cpcap_charger_set_cable_path(ddata, false);
355445 cpcap_charger_set_inductive_path(ddata, false);
356446
357447 error = cpcap_charger_set_state(ddata, 0, 0, 0);
448
+ if (error)
449
+ goto out_err;
450
+
451
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
452
+ CPCAP_BIT_VBUS_SWITCH,
453
+ CPCAP_BIT_VBUS_SWITCH);
358454 if (error)
359455 goto out_err;
360456
....@@ -364,6 +460,11 @@
364460 if (error)
365461 goto out_err;
366462 } else {
463
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
464
+ CPCAP_BIT_VBUS_SWITCH, 0);
465
+ if (error)
466
+ goto out_err;
467
+
367468 error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
368469 CPCAP_REG_CRM_RVRSMODE, 0);
369470 if (error)
....@@ -371,6 +472,7 @@
371472
372473 cpcap_charger_set_cable_path(ddata, true);
373474 cpcap_charger_set_inductive_path(ddata, true);
475
+ ddata->feeding_vbus = false;
374476 }
375477
376478 return;
....@@ -414,6 +516,7 @@
414516
415517 s->chrg_se1b = val & BIT(13);
416518 s->rvrs_mode = val & BIT(6);
519
+ s->chrgcurr2 = val & BIT(5);
417520 s->chrgcurr1 = val & BIT(4);
418521 s->vbusvld = val & BIT(3);
419522
....@@ -424,6 +527,79 @@
424527 s->battdetb = val & BIT(6);
425528
426529 return 0;
530
+}
531
+
532
+static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
533
+ int state)
534
+{
535
+ const char *status;
536
+
537
+ if (state > CPCAP_CHARGER_DONE) {
538
+ dev_warn(ddata->dev, "unknown state: %i\n", state);
539
+
540
+ return;
541
+ }
542
+
543
+ ddata->state = state;
544
+
545
+ switch (state) {
546
+ case CPCAP_CHARGER_DISCONNECTED:
547
+ status = "DISCONNECTED";
548
+ break;
549
+ case CPCAP_CHARGER_DETECTING:
550
+ status = "DETECTING";
551
+ break;
552
+ case CPCAP_CHARGER_CHARGING:
553
+ status = "CHARGING";
554
+ break;
555
+ case CPCAP_CHARGER_DONE:
556
+ status = "DONE";
557
+ break;
558
+ default:
559
+ return;
560
+ }
561
+
562
+ dev_dbg(ddata->dev, "state: %s\n", status);
563
+}
564
+
565
+static int cpcap_charger_voltage_to_regval(int voltage)
566
+{
567
+ int offset;
568
+
569
+ switch (voltage) {
570
+ case 0 ... 4100000 - 1:
571
+ return 0;
572
+ case 4100000 ... 4200000 - 1:
573
+ offset = 1;
574
+ break;
575
+ case 4200000 ... 4300000 - 1:
576
+ offset = 0;
577
+ break;
578
+ case 4300000 ... 4380000 - 1:
579
+ offset = -1;
580
+ break;
581
+ case 4380000 ... 4440000:
582
+ offset = -2;
583
+ break;
584
+ default:
585
+ return 0;
586
+ }
587
+
588
+ return ((voltage - 4100000) / 20000) + offset;
589
+}
590
+
591
+static void cpcap_charger_disconnect(struct cpcap_charger_ddata *ddata,
592
+ int state, unsigned long delay)
593
+{
594
+ int error;
595
+
596
+ error = cpcap_charger_set_state(ddata, 0, 0, 0);
597
+ if (error)
598
+ return;
599
+
600
+ cpcap_charger_update_state(ddata, state);
601
+ power_supply_changed(ddata->usb);
602
+ schedule_delayed_work(&ddata->detect_work, delay);
427603 }
428604
429605 static void cpcap_usb_detect(struct work_struct *work)
....@@ -439,23 +615,70 @@
439615 if (error)
440616 return;
441617
442
- if (cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) {
618
+ /* Just init the state if a charger is connected with no chrg_det set */
619
+ if (!s.chrg_det && s.chrgcurr1 && s.vbusvld) {
620
+ cpcap_charger_update_state(ddata, CPCAP_CHARGER_DETECTING);
621
+
622
+ return;
623
+ }
624
+
625
+ /*
626
+ * If battery voltage is higher than charge voltage, it may have been
627
+ * charged to 4.35V by Android. Try again in 10 minutes.
628
+ */
629
+ if (cpcap_charger_get_charge_voltage(ddata) > ddata->voltage) {
630
+ cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DETECTING,
631
+ HZ * 60 * 10);
632
+
633
+ return;
634
+ }
635
+
636
+ /* Delay for 80ms to avoid vbus bouncing when usb cable is plugged in */
637
+ usleep_range(80000, 120000);
638
+
639
+ /* Throttle chrgcurr2 interrupt for charger done and retry */
640
+ switch (ddata->state) {
641
+ case CPCAP_CHARGER_CHARGING:
642
+ if (s.chrgcurr2)
643
+ break;
644
+ if (s.chrgcurr1 && s.vbusvld) {
645
+ cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DONE,
646
+ HZ * 5);
647
+ return;
648
+ }
649
+ break;
650
+ case CPCAP_CHARGER_DONE:
651
+ if (!s.chrgcurr2)
652
+ break;
653
+ cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DETECTING,
654
+ HZ * 5);
655
+ return;
656
+ default:
657
+ break;
658
+ }
659
+
660
+ if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) &&
661
+ s.chrgcurr1) {
443662 int max_current;
663
+ int vchrg;
444664
445665 if (cpcap_charger_battery_found(ddata))
446666 max_current = CPCAP_REG_CRM_ICHRG_1A596;
447667 else
448668 max_current = CPCAP_REG_CRM_ICHRG_0A532;
449669
670
+ vchrg = cpcap_charger_voltage_to_regval(ddata->voltage);
450671 error = cpcap_charger_set_state(ddata,
451
- CPCAP_REG_CRM_VCHRG_4V35,
672
+ CPCAP_REG_CRM_VCHRG(vchrg),
452673 max_current, 0);
453674 if (error)
454675 goto out_err;
676
+ cpcap_charger_update_state(ddata, CPCAP_CHARGER_CHARGING);
455677 } else {
456678 error = cpcap_charger_set_state(ddata, 0, 0, 0);
457679 if (error)
458680 goto out_err;
681
+ cpcap_charger_update_state(ddata, CPCAP_CHARGER_DISCONNECTED);
459682 }
460683
461684 power_supply_changed(ddata->usb);
....@@ -490,7 +713,7 @@
490713
491714 error = devm_request_threaded_irq(ddata->dev, irq, NULL,
492715 cpcap_charger_irq_thread,
493
- IRQF_SHARED,
716
+ IRQF_SHARED | IRQF_ONESHOT,
494717 name, ddata);
495718 if (error) {
496719 dev_err(ddata->dev, "could not get irq %s: %i\n",
....@@ -515,7 +738,7 @@
515738 "chrg_det", "rvrs_chrg",
516739
517740 /* REG_INT1 */
518
- "chrg_se1b", "se0conn", "rvrs_mode", "chrgcurr1", "vbusvld",
741
+ "chrg_se1b", "se0conn", "rvrs_mode", "chrgcurr2", "chrgcurr1", "vbusvld",
519742
520743 /* REG_INT_3 */
521744 "battdetb",
....@@ -545,7 +768,7 @@
545768 if (IS_ERR(ddata->gpio[i])) {
546769 dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
547770 i, PTR_ERR(ddata->gpio[i]));
548
- ddata->gpio[i] = NULL;
771
+ ddata->gpio[i] = NULL;
549772 }
550773 }
551774 }
....@@ -574,8 +797,9 @@
574797 return 0;
575798
576799 out_err:
577
- dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
578
- error);
800
+ if (error != -EPROBE_DEFER)
801
+ dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
802
+ error);
579803
580804 return error;
581805 }
....@@ -586,6 +810,8 @@
586810 .properties = cpcap_charger_props,
587811 .num_properties = ARRAY_SIZE(cpcap_charger_props),
588812 .get_property = cpcap_charger_get_property,
813
+ .set_property = cpcap_charger_set_property,
814
+ .property_is_writeable = cpcap_charger_property_is_writeable,
589815 };
590816
591817 #ifdef CONFIG_OF
....@@ -615,6 +841,7 @@
615841 return -ENOMEM;
616842
617843 ddata->dev = &pdev->dev;
844
+ ddata->voltage = 4200000;
618845
619846 ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);
620847 if (!ddata->reg)