hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/power/supply/charger-manager.c
....@@ -1,15 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
34 * MyungJoo Ham <myungjoo.ham@samsung.com>
45 *
56 * This driver enables to monitor battery health and control charger
67 * during suspend-to-mem.
7
- * Charger manager depends on other devices. register this later than
8
+ * Charger manager depends on other devices. Register this later than
89 * the depending devices.
910 *
10
- * This program is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License version 2 as
12
- * published by the Free Software Foundation.
1311 **/
1412
1513 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
....@@ -28,24 +26,35 @@
2826 #include <linux/of.h>
2927 #include <linux/thermal.h>
3028
29
+static struct {
30
+ const char *name;
31
+ u64 extcon_type;
32
+} extcon_mapping[] = {
33
+ /* Current textual representations */
34
+ { "USB", EXTCON_USB },
35
+ { "USB-HOST", EXTCON_USB_HOST },
36
+ { "SDP", EXTCON_CHG_USB_SDP },
37
+ { "DCP", EXTCON_CHG_USB_DCP },
38
+ { "CDP", EXTCON_CHG_USB_CDP },
39
+ { "ACA", EXTCON_CHG_USB_ACA },
40
+ { "FAST-CHARGER", EXTCON_CHG_USB_FAST },
41
+ { "SLOW-CHARGER", EXTCON_CHG_USB_SLOW },
42
+ { "WPT", EXTCON_CHG_WPT },
43
+ { "PD", EXTCON_CHG_USB_PD },
44
+ { "DOCK", EXTCON_DOCK },
45
+ { "JIG", EXTCON_JIG },
46
+ { "MECHANICAL", EXTCON_MECHANICAL },
47
+ /* Deprecated textual representations */
48
+ { "TA", EXTCON_CHG_USB_SDP },
49
+ { "CHARGE-DOWNSTREAM", EXTCON_CHG_USB_CDP },
50
+};
51
+
3152 /*
32
- * Default termperature threshold for charging.
53
+ * Default temperature threshold for charging.
3354 * Every temperature units are in tenth of centigrade.
3455 */
3556 #define CM_DEFAULT_RECHARGE_TEMP_DIFF 50
3657 #define CM_DEFAULT_CHARGE_TEMP_MAX 500
37
-
38
-static const char * const default_event_names[] = {
39
- [CM_EVENT_UNKNOWN] = "Unknown",
40
- [CM_EVENT_BATT_FULL] = "Battery Full",
41
- [CM_EVENT_BATT_IN] = "Battery Inserted",
42
- [CM_EVENT_BATT_OUT] = "Battery Pulled Out",
43
- [CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
44
- [CM_EVENT_BATT_COLD] = "Battery Cold",
45
- [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
46
- [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
47
- [CM_EVENT_OTHERS] = "Other battery events"
48
-};
4958
5059 /*
5160 * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
....@@ -62,8 +71,6 @@
6271 * rtc alarm. It should be 2 or larger
6372 */
6473 #define CM_RTC_SMALL (2)
65
-
66
-#define UEVENT_BUF_SIZE 32
6774
6875 static LIST_HEAD(cm_list);
6976 static DEFINE_MUTEX(cm_list_mtx);
....@@ -287,6 +294,19 @@
287294 if (!fuel_gauge)
288295 return false;
289296
297
+ /* Full, if it's over the fullbatt voltage */
298
+ if (desc->fullbatt_uV > 0) {
299
+ ret = get_batt_uV(cm, &uV);
300
+ if (!ret) {
301
+ /* Battery is already full, checks voltage drop. */
302
+ if (cm->battery_status == POWER_SUPPLY_STATUS_FULL
303
+ && desc->fullbatt_vchkdrop_uV)
304
+ uV += desc->fullbatt_vchkdrop_uV;
305
+ if (uV >= desc->fullbatt_uV)
306
+ return true;
307
+ }
308
+ }
309
+
290310 if (desc->fullbatt_full_capacity > 0) {
291311 val.intval = 0;
292312
....@@ -294,15 +314,6 @@
294314 ret = power_supply_get_property(fuel_gauge,
295315 POWER_SUPPLY_PROP_CHARGE_FULL, &val);
296316 if (!ret && val.intval > desc->fullbatt_full_capacity) {
297
- is_full = true;
298
- goto out;
299
- }
300
- }
301
-
302
- /* Full, if it's over the fullbatt voltage */
303
- if (desc->fullbatt_uV > 0) {
304
- ret = get_batt_uV(cm, &uV);
305
- if (!ret && uV >= desc->fullbatt_uV) {
306317 is_full = true;
307318 goto out;
308319 }
....@@ -356,14 +367,14 @@
356367 * Note that Charger Manager keeps the charger enabled regardless whether
357368 * the charger is charging or not (because battery is full or no external
358369 * power source exists) except when CM needs to disable chargers forcibly
359
- * bacause of emergency causes; when the battery is overheated or too cold.
370
+ * because of emergency causes; when the battery is overheated or too cold.
360371 */
361372 static int try_charger_enable(struct charger_manager *cm, bool enable)
362373 {
363374 int err = 0, i;
364375 struct charger_desc *desc = cm->desc;
365376
366
- /* Ignore if it's redundent command */
377
+ /* Ignore if it's redundant command */
367378 if (enable == cm->charger_enabled)
368379 return 0;
369380
....@@ -429,122 +440,6 @@
429440 }
430441
431442 /**
432
- * try_charger_restart - Restart charging.
433
- * @cm: the Charger Manager representing the battery.
434
- *
435
- * Restart charging by turning off and on the charger.
436
- */
437
-static int try_charger_restart(struct charger_manager *cm)
438
-{
439
- int err;
440
-
441
- if (cm->emergency_stop)
442
- return -EAGAIN;
443
-
444
- err = try_charger_enable(cm, false);
445
- if (err)
446
- return err;
447
-
448
- return try_charger_enable(cm, true);
449
-}
450
-
451
-/**
452
- * uevent_notify - Let users know something has changed.
453
- * @cm: the Charger Manager representing the battery.
454
- * @event: the event string.
455
- *
456
- * If @event is null, it implies that uevent_notify is called
457
- * by resume function. When called in the resume function, cm_suspended
458
- * should be already reset to false in order to let uevent_notify
459
- * notify the recent event during the suspend to users. While
460
- * suspended, uevent_notify does not notify users, but tracks
461
- * events so that uevent_notify can notify users later after resumed.
462
- */
463
-static void uevent_notify(struct charger_manager *cm, const char *event)
464
-{
465
- static char env_str[UEVENT_BUF_SIZE + 1] = "";
466
- static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
467
-
468
- if (cm_suspended) {
469
- /* Nothing in suspended-event buffer */
470
- if (env_str_save[0] == 0) {
471
- if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
472
- return; /* status not changed */
473
- strncpy(env_str_save, event, UEVENT_BUF_SIZE);
474
- return;
475
- }
476
-
477
- if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
478
- return; /* Duplicated. */
479
- strncpy(env_str_save, event, UEVENT_BUF_SIZE);
480
- return;
481
- }
482
-
483
- if (event == NULL) {
484
- /* No messages pending */
485
- if (!env_str_save[0])
486
- return;
487
-
488
- strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
489
- kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
490
- env_str_save[0] = 0;
491
-
492
- return;
493
- }
494
-
495
- /* status not changed */
496
- if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
497
- return;
498
-
499
- /* save the status and notify the update */
500
- strncpy(env_str, event, UEVENT_BUF_SIZE);
501
- kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
502
-
503
- dev_info(cm->dev, "%s\n", event);
504
-}
505
-
506
-/**
507
- * fullbatt_vchk - Check voltage drop some times after "FULL" event.
508
- * @work: the work_struct appointing the function
509
- *
510
- * If a user has designated "fullbatt_vchkdrop_ms/uV" values with
511
- * charger_desc, Charger Manager checks voltage drop after the battery
512
- * "FULL" event. It checks whether the voltage has dropped more than
513
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
514
- */
515
-static void fullbatt_vchk(struct work_struct *work)
516
-{
517
- struct delayed_work *dwork = to_delayed_work(work);
518
- struct charger_manager *cm = container_of(dwork,
519
- struct charger_manager, fullbatt_vchk_work);
520
- struct charger_desc *desc = cm->desc;
521
- int batt_uV, err, diff;
522
-
523
- /* remove the appointment for fullbatt_vchk */
524
- cm->fullbatt_vchk_jiffies_at = 0;
525
-
526
- if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
527
- return;
528
-
529
- err = get_batt_uV(cm, &batt_uV);
530
- if (err) {
531
- dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err);
532
- return;
533
- }
534
-
535
- diff = desc->fullbatt_uV - batt_uV;
536
- if (diff < 0)
537
- return;
538
-
539
- dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
540
-
541
- if (diff > desc->fullbatt_vchkdrop_uV) {
542
- try_charger_restart(cm);
543
- uevent_notify(cm, "Recharging");
544
- }
545
-}
546
-
547
-/**
548443 * check_charging_duration - Monitor charging/discharging duration
549444 * @cm: the Charger Manager representing the battery.
550445 *
....@@ -571,19 +466,14 @@
571466 if (duration > desc->charging_max_duration_ms) {
572467 dev_info(cm->dev, "Charging duration exceed %ums\n",
573468 desc->charging_max_duration_ms);
574
- uevent_notify(cm, "Discharging");
575
- try_charger_enable(cm, false);
576469 ret = true;
577470 }
578
- } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
471
+ } else if (cm->battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
579472 duration = curr - cm->charging_end_time;
580473
581
- if (duration > desc->discharging_max_duration_ms &&
582
- is_ext_pwr_online(cm)) {
474
+ if (duration > desc->discharging_max_duration_ms) {
583475 dev_info(cm->dev, "Discharging duration exceed %ums\n",
584476 desc->discharging_max_duration_ms);
585
- uevent_notify(cm, "Recharging");
586
- try_charger_enable(cm, true);
587477 ret = true;
588478 }
589479 }
....@@ -643,7 +533,7 @@
643533 if (ret) {
644534 /* FIXME:
645535 * No information of battery temperature might
646
- * occur hazadous result. We have to handle it
536
+ * occur hazardous result. We have to handle it
647537 * depending on battery type.
648538 */
649539 dev_err(cm->dev, "Failed to get battery temperature\n");
....@@ -659,11 +549,50 @@
659549 }
660550
661551 if (temp > upper_limit)
662
- ret = CM_EVENT_BATT_OVERHEAT;
552
+ ret = CM_BATT_OVERHEAT;
663553 else if (temp < lower_limit)
664
- ret = CM_EVENT_BATT_COLD;
554
+ ret = CM_BATT_COLD;
555
+ else
556
+ ret = CM_BATT_OK;
557
+
558
+ cm->emergency_stop = ret;
665559
666560 return ret;
561
+}
562
+
563
+/**
564
+ * cm_get_target_status - Check current status and get next target status.
565
+ * @cm: the Charger Manager representing the battery.
566
+ */
567
+static int cm_get_target_status(struct charger_manager *cm)
568
+{
569
+ if (!is_ext_pwr_online(cm))
570
+ return POWER_SUPPLY_STATUS_DISCHARGING;
571
+
572
+ if (cm_check_thermal_status(cm)) {
573
+ /* Check if discharging duration exeeds limit. */
574
+ if (check_charging_duration(cm))
575
+ goto charging_ok;
576
+ return POWER_SUPPLY_STATUS_NOT_CHARGING;
577
+ }
578
+
579
+ switch (cm->battery_status) {
580
+ case POWER_SUPPLY_STATUS_CHARGING:
581
+ /* Check if charging duration exeeds limit. */
582
+ if (check_charging_duration(cm))
583
+ return POWER_SUPPLY_STATUS_FULL;
584
+ fallthrough;
585
+ case POWER_SUPPLY_STATUS_FULL:
586
+ if (is_full_charged(cm))
587
+ return POWER_SUPPLY_STATUS_FULL;
588
+ fallthrough;
589
+ default:
590
+ break;
591
+ }
592
+
593
+charging_ok:
594
+ /* Charging is allowed. */
595
+ return POWER_SUPPLY_STATUS_CHARGING;
667596 }
668597
669598 /**
....@@ -675,60 +604,18 @@
675604 */
676605 static bool _cm_monitor(struct charger_manager *cm)
677606 {
678
- int temp_alrt;
607
+ int target;
679608
680
- temp_alrt = cm_check_thermal_status(cm);
609
+ target = cm_get_target_status(cm);
681610
682
- /* It has been stopped already */
683
- if (temp_alrt && cm->emergency_stop)
684
- return false;
611
+ try_charger_enable(cm, (target == POWER_SUPPLY_STATUS_CHARGING));
685612
686
- /*
687
- * Check temperature whether overheat or cold.
688
- * If temperature is out of range normal state, stop charging.
689
- */
690
- if (temp_alrt) {
691
- cm->emergency_stop = temp_alrt;
692
- if (!try_charger_enable(cm, false))
693
- uevent_notify(cm, default_event_names[temp_alrt]);
694
-
695
- /*
696
- * Check whole charging duration and discharing duration
697
- * after full-batt.
698
- */
699
- } else if (!cm->emergency_stop && check_charging_duration(cm)) {
700
- dev_dbg(cm->dev,
701
- "Charging/Discharging duration is out of range\n");
702
- /*
703
- * Check dropped voltage of battery. If battery voltage is more
704
- * dropped than fullbatt_vchkdrop_uV after fully charged state,
705
- * charger-manager have to recharge battery.
706
- */
707
- } else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
708
- !cm->charger_enabled) {
709
- fullbatt_vchk(&cm->fullbatt_vchk_work.work);
710
-
711
- /*
712
- * Check whether fully charged state to protect overcharge
713
- * if charger-manager is charging for battery.
714
- */
715
- } else if (!cm->emergency_stop && is_full_charged(cm) &&
716
- cm->charger_enabled) {
717
- dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
718
- uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]);
719
-
720
- try_charger_enable(cm, false);
721
-
722
- fullbatt_vchk(&cm->fullbatt_vchk_work.work);
723
- } else {
724
- cm->emergency_stop = 0;
725
- if (is_ext_pwr_online(cm)) {
726
- if (!try_charger_enable(cm, true))
727
- uevent_notify(cm, "CHARGING");
728
- }
613
+ if (cm->battery_status != target) {
614
+ cm->battery_status = target;
615
+ power_supply_changed(cm->charger_psy);
729616 }
730617
731
- return true;
618
+ return (cm->battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING);
732619 }
733620
734621 /**
....@@ -821,66 +708,6 @@
821708 schedule_work(&setup_polling);
822709 }
823710
824
-/**
825
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
826
- * @cm: the Charger Manager representing the battery.
827
- */
828
-static void fullbatt_handler(struct charger_manager *cm)
829
-{
830
- struct charger_desc *desc = cm->desc;
831
-
832
- if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
833
- goto out;
834
-
835
- if (cm_suspended)
836
- device_set_wakeup_capable(cm->dev, true);
837
-
838
- mod_delayed_work(cm_wq, &cm->fullbatt_vchk_work,
839
- msecs_to_jiffies(desc->fullbatt_vchkdrop_ms));
840
- cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
841
- desc->fullbatt_vchkdrop_ms);
842
-
843
- if (cm->fullbatt_vchk_jiffies_at == 0)
844
- cm->fullbatt_vchk_jiffies_at = 1;
845
-
846
-out:
847
- dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
848
- uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]);
849
-}
850
-
851
-/**
852
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
853
- * @cm: the Charger Manager representing the battery.
854
- */
855
-static void battout_handler(struct charger_manager *cm)
856
-{
857
- if (cm_suspended)
858
- device_set_wakeup_capable(cm->dev, true);
859
-
860
- if (!is_batt_present(cm)) {
861
- dev_emerg(cm->dev, "Battery Pulled Out!\n");
862
- uevent_notify(cm, default_event_names[CM_EVENT_BATT_OUT]);
863
- } else {
864
- uevent_notify(cm, "Battery Reinserted?");
865
- }
866
-}
867
-
868
-/**
869
- * misc_event_handler - Handler for other evnets
870
- * @cm: the Charger Manager representing the battery.
871
- * @type: the Charger Manager representing the battery.
872
- */
873
-static void misc_event_handler(struct charger_manager *cm,
874
- enum cm_event_types type)
875
-{
876
- if (cm_suspended)
877
- device_set_wakeup_capable(cm->dev, true);
878
-
879
- if (is_polling_required(cm) && cm->desc->polling_interval_ms)
880
- schedule_work(&setup_polling);
881
- uevent_notify(cm, default_event_names[type]);
882
-}
883
-
884711 static int charger_get_property(struct power_supply *psy,
885712 enum power_supply_property psp,
886713 union power_supply_propval *val)
....@@ -893,12 +720,7 @@
893720
894721 switch (psp) {
895722 case POWER_SUPPLY_PROP_STATUS:
896
- if (is_charging(cm))
897
- val->intval = POWER_SUPPLY_STATUS_CHARGING;
898
- else if (is_ext_pwr_online(cm))
899
- val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
900
- else
901
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
723
+ val->intval = cm->battery_status;
902724 break;
903725 case POWER_SUPPLY_PROP_HEALTH:
904726 if (cm->emergency_stop > 0)
....@@ -927,7 +749,6 @@
927749 POWER_SUPPLY_PROP_CURRENT_NOW, val);
928750 break;
929751 case POWER_SUPPLY_PROP_TEMP:
930
- case POWER_SUPPLY_PROP_TEMP_AMBIENT:
931752 return cm_get_battery_temperature(cm, &val->intval);
932753 case POWER_SUPPLY_PROP_CAPACITY:
933754 if (!is_batt_present(cm)) {
....@@ -983,35 +804,13 @@
983804 val->intval = 0;
984805 break;
985806 case POWER_SUPPLY_PROP_CHARGE_FULL:
986
- if (is_full_charged(cm))
987
- val->intval = 1;
988
- else
989
- val->intval = 0;
990
- ret = 0;
991
- break;
992807 case POWER_SUPPLY_PROP_CHARGE_NOW:
993
- if (is_charging(cm)) {
994
- fuel_gauge = power_supply_get_by_name(
995
- cm->desc->psy_fuel_gauge);
996
- if (!fuel_gauge) {
997
- ret = -ENODEV;
998
- break;
999
- }
1000
-
1001
- ret = power_supply_get_property(fuel_gauge,
1002
- POWER_SUPPLY_PROP_CHARGE_NOW,
1003
- val);
1004
- if (ret) {
1005
- val->intval = 1;
1006
- ret = 0;
1007
- } else {
1008
- /* If CHARGE_NOW is supplied, use it */
1009
- val->intval = (val->intval > 0) ?
1010
- val->intval : 1;
1011
- }
1012
- } else {
1013
- val->intval = 0;
808
+ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
809
+ if (!fuel_gauge) {
810
+ ret = -ENODEV;
811
+ break;
1014812 }
813
+ ret = power_supply_get_property(fuel_gauge, psp, val);
1015814 break;
1016815 default:
1017816 return -EINVAL;
....@@ -1030,13 +829,12 @@
1030829 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1031830 POWER_SUPPLY_PROP_CAPACITY,
1032831 POWER_SUPPLY_PROP_ONLINE,
1033
- POWER_SUPPLY_PROP_CHARGE_FULL,
1034832 /*
1035833 * Optional properties are:
834
+ * POWER_SUPPLY_PROP_CHARGE_FULL,
1036835 * POWER_SUPPLY_PROP_CHARGE_NOW,
1037836 * POWER_SUPPLY_PROP_CURRENT_NOW,
1038
- * POWER_SUPPLY_PROP_TEMP, and
1039
- * POWER_SUPPLY_PROP_TEMP_AMBIENT,
837
+ * POWER_SUPPLY_PROP_TEMP,
1040838 */
1041839 };
1042840
....@@ -1071,21 +869,6 @@
1071869
1072870 mutex_lock(&cm_list_mtx);
1073871 list_for_each_entry(cm, &cm_list, entry) {
1074
- unsigned int fbchk_ms = 0;
1075
-
1076
- /* fullbatt_vchk is required. setup timer for that */
1077
- if (cm->fullbatt_vchk_jiffies_at) {
1078
- fbchk_ms = jiffies_to_msecs(cm->fullbatt_vchk_jiffies_at
1079
- - jiffies);
1080
- if (time_is_before_eq_jiffies(
1081
- cm->fullbatt_vchk_jiffies_at) ||
1082
- msecs_to_jiffies(fbchk_ms) < CM_JIFFIES_SMALL) {
1083
- fullbatt_vchk(&cm->fullbatt_vchk_work.work);
1084
- fbchk_ms = 0;
1085
- }
1086
- }
1087
- CM_MIN_VALID(wakeup_ms, fbchk_ms);
1088
-
1089872 /* Skip if polling is not required for this CM */
1090873 if (!is_polling_required(cm) && !cm->emergency_stop)
1091874 continue;
....@@ -1147,7 +930,8 @@
1147930 cable->min_uA, cable->max_uA);
1148931 }
1149932
1150
- try_charger_enable(cable->cm, cable->attached);
933
+ cancel_delayed_work(&cm_monitor_work);
934
+ queue_delayed_work(cm_wq, &cm_monitor_work, 0);
1151935 }
1152936
1153937 /**
....@@ -1171,15 +955,6 @@
1171955 cable->attached = event;
1172956
1173957 /*
1174
- * Setup monitoring to check battery state
1175
- * when charger cable is attached.
1176
- */
1177
- if (cable->attached && is_polling_required(cable->cm)) {
1178
- cancel_work_sync(&setup_polling);
1179
- schedule_work(&setup_polling);
1180
- }
1181
-
1182
- /*
1183958 * Setup work for controlling charger(regulator)
1184959 * according to charger cable.
1185960 */
....@@ -1198,7 +973,8 @@
1198973 static int charger_extcon_init(struct charger_manager *cm,
1199974 struct charger_cable *cable)
1200975 {
1201
- int ret;
976
+ int ret, i;
977
+ u64 extcon_type = EXTCON_NONE;
1202978
1203979 /*
1204980 * Charger manager use Extcon framework to identify
....@@ -1207,18 +983,43 @@
1207983 */
1208984 INIT_WORK(&cable->wq, charger_extcon_work);
1209985 cable->nb.notifier_call = charger_extcon_notifier;
1210
- ret = extcon_register_interest(&cable->extcon_dev,
1211
- cable->extcon_name, cable->name, &cable->nb);
1212
- if (ret < 0) {
1213
- pr_info("Cannot register extcon_dev for %s(cable: %s)\n",
986
+
987
+ cable->extcon_dev = extcon_get_extcon_dev(cable->extcon_name);
988
+ if (IS_ERR_OR_NULL(cable->extcon_dev)) {
989
+ pr_err("Cannot find extcon_dev for %s (cable: %s)\n",
1214990 cable->extcon_name, cable->name);
991
+ if (cable->extcon_dev == NULL)
992
+ return -EPROBE_DEFER;
993
+ else
994
+ return PTR_ERR(cable->extcon_dev);
1215995 }
1216996
1217
- return ret;
997
+ for (i = 0; i < ARRAY_SIZE(extcon_mapping); i++) {
998
+ if (!strcmp(cable->name, extcon_mapping[i].name)) {
999
+ extcon_type = extcon_mapping[i].extcon_type;
1000
+ break;
1001
+ }
1002
+ }
1003
+ if (extcon_type == EXTCON_NONE) {
1004
+ pr_err("Cannot find cable for type %s", cable->name);
1005
+ return -EINVAL;
1006
+ }
1007
+
1008
+ cable->extcon_type = extcon_type;
1009
+
1010
+ ret = devm_extcon_register_notifier(cm->dev, cable->extcon_dev,
1011
+ cable->extcon_type, &cable->nb);
1012
+ if (ret < 0) {
1013
+ pr_err("Cannot register extcon_dev for %s (cable: %s)\n",
1014
+ cable->extcon_name, cable->name);
1015
+ return ret;
1016
+ }
1017
+
1018
+ return 0;
12181019 }
12191020
12201021 /**
1221
- * charger_manager_register_extcon - Register extcon device to recevie state
1022
+ * charger_manager_register_extcon - Register extcon device to receive state
12221023 * of charger cable.
12231024 * @cm: the Charger Manager representing the battery.
12241025 *
....@@ -1231,6 +1032,7 @@
12311032 {
12321033 struct charger_desc *desc = cm->desc;
12331034 struct charger_regulator *charger;
1035
+ unsigned long event;
12341036 int ret;
12351037 int i;
12361038 int j;
....@@ -1258,6 +1060,11 @@
12581060 }
12591061 cable->charger = charger;
12601062 cable->cm = cm;
1063
+
1064
+ event = extcon_get_state(cable->extcon_dev,
1065
+ cable->extcon_type);
1066
+ charger_extcon_notifier(&cable->nb,
1067
+ event, NULL);
12611068 }
12621069 }
12631070
....@@ -1351,7 +1158,7 @@
13511158 }
13521159
13531160 /**
1354
- * charger_manager_register_sysfs - Register sysfs entry for each charger
1161
+ * charger_manager_prepare_sysfs - Prepare sysfs entry for each charger
13551162 * @cm: the Charger Manager representing the battery.
13561163 *
13571164 * This function add sysfs entry for charger(regulator) to control charger from
....@@ -1363,34 +1170,30 @@
13631170 * externally_control, this charger isn't controlled from charger-manager and
13641171 * always stay off state of regulator.
13651172 */
1366
-static int charger_manager_register_sysfs(struct charger_manager *cm)
1173
+static int charger_manager_prepare_sysfs(struct charger_manager *cm)
13671174 {
13681175 struct charger_desc *desc = cm->desc;
13691176 struct charger_regulator *charger;
13701177 int chargers_externally_control = 1;
1371
- char buf[11];
1372
- char *str;
1373
- int ret;
1178
+ char *name;
13741179 int i;
13751180
13761181 /* Create sysfs entry to control charger(regulator) */
13771182 for (i = 0; i < desc->num_charger_regulators; i++) {
13781183 charger = &desc->charger_regulators[i];
13791184
1380
- snprintf(buf, 10, "charger.%d", i);
1381
- str = devm_kzalloc(cm->dev,
1382
- strlen(buf) + 1, GFP_KERNEL);
1383
- if (!str)
1185
+ name = devm_kasprintf(cm->dev, GFP_KERNEL, "charger.%d", i);
1186
+ if (!name)
13841187 return -ENOMEM;
1385
-
1386
- strcpy(str, buf);
13871188
13881189 charger->attrs[0] = &charger->attr_name.attr;
13891190 charger->attrs[1] = &charger->attr_state.attr;
13901191 charger->attrs[2] = &charger->attr_externally_control.attr;
13911192 charger->attrs[3] = NULL;
1392
- charger->attr_g.name = str;
1393
- charger->attr_g.attrs = charger->attrs;
1193
+
1194
+ charger->attr_grp.name = name;
1195
+ charger->attr_grp.attrs = charger->attrs;
1196
+ desc->sysfs_groups[i] = &charger->attr_grp;
13941197
13951198 sysfs_attr_init(&charger->attr_name.attr);
13961199 charger->attr_name.attr.name = "name";
....@@ -1417,14 +1220,6 @@
14171220
14181221 dev_info(cm->dev, "'%s' regulator's externally_control is %d\n",
14191222 charger->regulator_name, charger->externally_control);
1420
-
1421
- ret = sysfs_create_group(&cm->charger_psy->dev.kobj,
1422
- &charger->attr_g);
1423
- if (ret < 0) {
1424
- dev_err(cm->dev, "Cannot create sysfs entry of %s regulator\n",
1425
- charger->regulator_name);
1426
- return ret;
1427
- }
14281223 }
14291224
14301225 if (chargers_externally_control) {
....@@ -1436,7 +1231,9 @@
14361231 }
14371232
14381233 static int cm_init_thermal_data(struct charger_manager *cm,
1439
- struct power_supply *fuel_gauge)
1234
+ struct power_supply *fuel_gauge,
1235
+ enum power_supply_property *properties,
1236
+ size_t *num_properties)
14401237 {
14411238 struct charger_desc *desc = cm->desc;
14421239 union power_supply_propval val;
....@@ -1447,9 +1244,8 @@
14471244 POWER_SUPPLY_PROP_TEMP, &val);
14481245
14491246 if (!ret) {
1450
- cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
1451
- POWER_SUPPLY_PROP_TEMP;
1452
- cm->charger_psy_desc.num_properties++;
1247
+ properties[*num_properties] = POWER_SUPPLY_PROP_TEMP;
1248
+ (*num_properties)++;
14531249 cm->desc->measure_battery_temp = true;
14541250 }
14551251 #ifdef CONFIG_THERMAL
....@@ -1460,9 +1256,8 @@
14601256 return PTR_ERR(cm->tzd_batt);
14611257
14621258 /* Use external thermometer */
1463
- cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
1464
- POWER_SUPPLY_PROP_TEMP_AMBIENT;
1465
- cm->charger_psy_desc.num_properties++;
1259
+ properties[*num_properties] = POWER_SUPPLY_PROP_TEMP;
1260
+ (*num_properties)++;
14661261 cm->desc->measure_battery_temp = true;
14671262 ret = 0;
14681263 }
....@@ -1506,8 +1301,6 @@
15061301 of_property_read_u32(np, "cm-poll-interval",
15071302 &desc->polling_interval_ms);
15081303
1509
- of_property_read_u32(np, "cm-fullbatt-vchkdrop-ms",
1510
- &desc->fullbatt_vchkdrop_ms);
15111304 of_property_read_u32(np, "cm-fullbatt-vchkdrop-volt",
15121305 &desc->fullbatt_vchkdrop_uV);
15131306 of_property_read_u32(np, "cm-fullbatt-voltage", &desc->fullbatt_uV);
....@@ -1519,21 +1312,21 @@
15191312 desc->battery_present = battery_stat;
15201313
15211314 /* chargers */
1522
- of_property_read_u32(np, "cm-num-chargers", &num_chgs);
1523
- if (num_chgs) {
1315
+ num_chgs = of_property_count_strings(np, "cm-chargers");
1316
+ if (num_chgs > 0) {
1317
+ int i;
1318
+
15241319 /* Allocate empty bin at the tail of array */
15251320 desc->psy_charger_stat = devm_kcalloc(dev,
15261321 num_chgs + 1,
15271322 sizeof(char *),
15281323 GFP_KERNEL);
1529
- if (desc->psy_charger_stat) {
1530
- int i;
1531
- for (i = 0; i < num_chgs; i++)
1532
- of_property_read_string_index(np, "cm-chargers",
1533
- i, &desc->psy_charger_stat[i]);
1534
- } else {
1324
+ if (!desc->psy_charger_stat)
15351325 return ERR_PTR(-ENOMEM);
1536
- }
1326
+
1327
+ for (i = 0; i < num_chgs; i++)
1328
+ of_property_read_string_index(np, "cm-chargers",
1329
+ i, &desc->psy_charger_stat[i]);
15371330 }
15381331
15391332 of_property_read_string(np, "cm-fuel-gauge", &desc->psy_fuel_gauge);
....@@ -1551,7 +1344,7 @@
15511344 of_property_read_u32(np, "cm-discharging-max",
15521345 &desc->discharging_max_duration_ms);
15531346
1554
- /* battery charger regualtors */
1347
+ /* battery charger regulators */
15551348 desc->num_charger_regulators = of_get_child_count(np);
15561349 if (desc->num_charger_regulators) {
15571350 struct charger_regulator *chg_regs;
....@@ -1565,6 +1358,13 @@
15651358 return ERR_PTR(-ENOMEM);
15661359
15671360 desc->charger_regulators = chg_regs;
1361
+
1362
+ desc->sysfs_groups = devm_kcalloc(dev,
1363
+ desc->num_charger_regulators + 1,
1364
+ sizeof(*desc->sysfs_groups),
1365
+ GFP_KERNEL);
1366
+ if (!desc->sysfs_groups)
1367
+ return ERR_PTR(-ENOMEM);
15681368
15691369 for_each_child_of_node(np, child) {
15701370 struct charger_cable *cables;
....@@ -1626,9 +1426,10 @@
16261426 struct charger_desc *desc = cm_get_drv_data(pdev);
16271427 struct charger_manager *cm;
16281428 int ret, i = 0;
1629
- int j = 0;
16301429 union power_supply_propval val;
16311430 struct power_supply *fuel_gauge;
1431
+ enum power_supply_property *properties;
1432
+ size_t num_properties;
16321433 struct power_supply_config psy_cfg = {};
16331434
16341435 if (IS_ERR(desc)) {
....@@ -1660,9 +1461,8 @@
16601461 if (desc->fullbatt_uV == 0) {
16611462 dev_info(&pdev->dev, "Ignoring full-battery voltage threshold as it is not supplied\n");
16621463 }
1663
- if (!desc->fullbatt_vchkdrop_ms || !desc->fullbatt_vchkdrop_uV) {
1464
+ if (!desc->fullbatt_vchkdrop_uV) {
16641465 dev_info(&pdev->dev, "Disabling full-battery voltage drop checking mechanism as it is not supplied\n");
1665
- desc->fullbatt_vchkdrop_ms = 0;
16661466 desc->fullbatt_vchkdrop_uV = 0;
16671467 }
16681468 if (desc->fullbatt_soc == 0) {
....@@ -1686,10 +1486,6 @@
16861486 dev_err(&pdev->dev, "No fuel gauge power supply defined\n");
16871487 return -EINVAL;
16881488 }
1689
-
1690
- /* Counting index only */
1691
- while (desc->psy_charger_stat[i])
1692
- i++;
16931489
16941490 /* Check if charger's supplies are present at probe */
16951491 for (i = 0; desc->psy_charger_stat[i]; i++) {
....@@ -1729,18 +1525,17 @@
17291525 cm->charger_psy_desc.name = cm->psy_name_buf;
17301526
17311527 /* Allocate for psy properties because they may vary */
1732
- cm->charger_psy_desc.properties =
1733
- devm_kcalloc(&pdev->dev,
1528
+ properties = devm_kcalloc(&pdev->dev,
17341529 ARRAY_SIZE(default_charger_props) +
17351530 NUM_CHARGER_PSY_OPTIONAL,
1736
- sizeof(enum power_supply_property), GFP_KERNEL);
1737
- if (!cm->charger_psy_desc.properties)
1531
+ sizeof(*properties), GFP_KERNEL);
1532
+ if (!properties)
17381533 return -ENOMEM;
17391534
1740
- memcpy(cm->charger_psy_desc.properties, default_charger_props,
1535
+ memcpy(properties, default_charger_props,
17411536 sizeof(enum power_supply_property) *
17421537 ARRAY_SIZE(default_charger_props));
1743
- cm->charger_psy_desc.num_properties = psy_default.num_properties;
1538
+ num_properties = ARRAY_SIZE(default_charger_props);
17441539
17451540 /* Find which optional psy-properties are available */
17461541 fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
....@@ -1750,27 +1545,43 @@
17501545 return -ENODEV;
17511546 }
17521547 if (!power_supply_get_property(fuel_gauge,
1548
+ POWER_SUPPLY_PROP_CHARGE_FULL, &val)) {
1549
+ properties[num_properties] =
1550
+ POWER_SUPPLY_PROP_CHARGE_FULL;
1551
+ num_properties++;
1552
+ }
1553
+ if (!power_supply_get_property(fuel_gauge,
17531554 POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
1754
- cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
1555
+ properties[num_properties] =
17551556 POWER_SUPPLY_PROP_CHARGE_NOW;
1756
- cm->charger_psy_desc.num_properties++;
1557
+ num_properties++;
17571558 }
17581559 if (!power_supply_get_property(fuel_gauge,
17591560 POWER_SUPPLY_PROP_CURRENT_NOW,
17601561 &val)) {
1761
- cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
1562
+ properties[num_properties] =
17621563 POWER_SUPPLY_PROP_CURRENT_NOW;
1763
- cm->charger_psy_desc.num_properties++;
1564
+ num_properties++;
17641565 }
17651566
1766
- ret = cm_init_thermal_data(cm, fuel_gauge);
1567
+ ret = cm_init_thermal_data(cm, fuel_gauge, properties, &num_properties);
17671568 if (ret) {
17681569 dev_err(&pdev->dev, "Failed to initialize thermal data\n");
17691570 cm->desc->measure_battery_temp = false;
17701571 }
17711572 power_supply_put(fuel_gauge);
17721573
1773
- INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
1574
+ cm->charger_psy_desc.properties = properties;
1575
+ cm->charger_psy_desc.num_properties = num_properties;
1576
+
1577
+ /* Register sysfs entry for charger(regulator) */
1578
+ ret = charger_manager_prepare_sysfs(cm);
1579
+ if (ret < 0) {
1580
+ dev_err(&pdev->dev,
1581
+ "Cannot prepare sysfs entry of regulators\n");
1582
+ return ret;
1583
+ }
1584
+ psy_cfg.attr_grp = desc->sysfs_groups;
17741585
17751586 cm->charger_psy = power_supply_register(&pdev->dev,
17761587 &cm->charger_psy_desc,
....@@ -1788,14 +1599,6 @@
17881599 goto err_reg_extcon;
17891600 }
17901601
1791
- /* Register sysfs entry for charger(regulator) */
1792
- ret = charger_manager_register_sysfs(cm);
1793
- if (ret < 0) {
1794
- dev_err(&pdev->dev,
1795
- "Cannot initialize sysfs entry of regulator\n");
1796
- goto err_reg_sysfs;
1797
- }
1798
-
17991602 /* Add to the list */
18001603 mutex_lock(&cm_list_mtx);
18011604 list_add(&cm->entry, &cm_list);
....@@ -1803,14 +1606,14 @@
18031606
18041607 /*
18051608 * Charger-manager is capable of waking up the systme from sleep
1806
- * when event is happend through cm_notify_event()
1609
+ * when event is happened through cm_notify_event()
18071610 */
18081611 device_init_wakeup(&pdev->dev, true);
18091612 device_set_wakeup_capable(&pdev->dev, false);
18101613
18111614 /*
18121615 * Charger-manager have to check the charging state right after
1813
- * tialization of charger-manager and then update current charging
1616
+ * initialization of charger-manager and then update current charging
18141617 * state.
18151618 */
18161619 cm_monitor();
....@@ -1819,28 +1622,9 @@
18191622
18201623 return 0;
18211624
1822
-err_reg_sysfs:
1823
- for (i = 0; i < desc->num_charger_regulators; i++) {
1824
- struct charger_regulator *charger;
1825
-
1826
- charger = &desc->charger_regulators[i];
1827
- sysfs_remove_group(&cm->charger_psy->dev.kobj,
1828
- &charger->attr_g);
1829
- }
18301625 err_reg_extcon:
1831
- for (i = 0; i < desc->num_charger_regulators; i++) {
1832
- struct charger_regulator *charger;
1833
-
1834
- charger = &desc->charger_regulators[i];
1835
- for (j = 0; j < charger->num_cables; j++) {
1836
- struct charger_cable *cable = &charger->cables[j];
1837
- /* Remove notifier block if only edev exists */
1838
- if (cable->extcon_dev.edev)
1839
- extcon_unregister_interest(&cable->extcon_dev);
1840
- }
1841
-
1626
+ for (i = 0; i < desc->num_charger_regulators; i++)
18421627 regulator_put(desc->charger_regulators[i].consumer);
1843
- }
18441628
18451629 power_supply_unregister(cm->charger_psy);
18461630
....@@ -1852,7 +1636,6 @@
18521636 struct charger_manager *cm = platform_get_drvdata(pdev);
18531637 struct charger_desc *desc = cm->desc;
18541638 int i = 0;
1855
- int j = 0;
18561639
18571640 /* Remove from the list */
18581641 mutex_lock(&cm_list_mtx);
....@@ -1861,15 +1644,6 @@
18611644
18621645 cancel_work_sync(&setup_polling);
18631646 cancel_delayed_work_sync(&cm_monitor_work);
1864
-
1865
- for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1866
- struct charger_regulator *charger
1867
- = &desc->charger_regulators[i];
1868
- for (j = 0 ; j < charger->num_cables ; j++) {
1869
- struct charger_cable *cable = &charger->cables[j];
1870
- extcon_unregister_interest(&cable->extcon_dev);
1871
- }
1872
- }
18731647
18741648 for (i = 0 ; i < desc->num_charger_regulators ; i++)
18751649 regulator_put(desc->charger_regulators[i].consumer);
....@@ -1918,8 +1692,6 @@
19181692
19191693 static int cm_suspend_prepare(struct device *dev)
19201694 {
1921
- struct charger_manager *cm = dev_get_drvdata(dev);
1922
-
19231695 if (cm_need_to_awake())
19241696 return -EBUSY;
19251697
....@@ -1931,7 +1703,6 @@
19311703 if (cm_timer_set) {
19321704 cancel_work_sync(&setup_polling);
19331705 cancel_delayed_work_sync(&cm_monitor_work);
1934
- cancel_delayed_work(&cm->fullbatt_vchk_work);
19351706 }
19361707
19371708 return 0;
....@@ -1956,31 +1727,6 @@
19561727
19571728 _cm_monitor(cm);
19581729
1959
- /* Re-enqueue delayed work (fullbatt_vchk_work) */
1960
- if (cm->fullbatt_vchk_jiffies_at) {
1961
- unsigned long delay = 0;
1962
- unsigned long now = jiffies + CM_JIFFIES_SMALL;
1963
-
1964
- if (time_after_eq(now, cm->fullbatt_vchk_jiffies_at)) {
1965
- delay = (unsigned long)((long)now
1966
- - (long)(cm->fullbatt_vchk_jiffies_at));
1967
- delay = jiffies_to_msecs(delay);
1968
- } else {
1969
- delay = 0;
1970
- }
1971
-
1972
- /*
1973
- * Account for cm_suspend_duration_ms with assuming that
1974
- * timer stops in suspend.
1975
- */
1976
- if (delay > cm_suspend_duration_ms)
1977
- delay -= cm_suspend_duration_ms;
1978
- else
1979
- delay = 0;
1980
-
1981
- queue_delayed_work(cm_wq, &cm->fullbatt_vchk_work,
1982
- msecs_to_jiffies(delay));
1983
- }
19841730 device_set_wakeup_capable(cm->dev, false);
19851731 }
19861732
....@@ -2004,6 +1750,9 @@
20041750 static int __init charger_manager_init(void)
20051751 {
20061752 cm_wq = create_freezable_workqueue("charger_manager");
1753
+ if (unlikely(!cm_wq))
1754
+ return -ENOMEM;
1755
+
20071756 INIT_DELAYED_WORK(&cm_monitor_work, cm_monitor_poller);
20081757
20091758 return platform_driver_register(&charger_manager_driver);
....@@ -2018,56 +1767,6 @@
20181767 platform_driver_unregister(&charger_manager_driver);
20191768 }
20201769 module_exit(charger_manager_cleanup);
2021
-
2022
-/**
2023
- * cm_notify_event - charger driver notify Charger Manager of charger event
2024
- * @psy: pointer to instance of charger's power_supply
2025
- * @type: type of charger event
2026
- * @msg: optional message passed to uevent_notify fuction
2027
- */
2028
-void cm_notify_event(struct power_supply *psy, enum cm_event_types type,
2029
- char *msg)
2030
-{
2031
- struct charger_manager *cm;
2032
- bool found_power_supply = false;
2033
-
2034
- if (psy == NULL)
2035
- return;
2036
-
2037
- mutex_lock(&cm_list_mtx);
2038
- list_for_each_entry(cm, &cm_list, entry) {
2039
- if (match_string(cm->desc->psy_charger_stat, -1,
2040
- psy->desc->name) >= 0) {
2041
- found_power_supply = true;
2042
- break;
2043
- }
2044
- }
2045
- mutex_unlock(&cm_list_mtx);
2046
-
2047
- if (!found_power_supply)
2048
- return;
2049
-
2050
- switch (type) {
2051
- case CM_EVENT_BATT_FULL:
2052
- fullbatt_handler(cm);
2053
- break;
2054
- case CM_EVENT_BATT_OUT:
2055
- battout_handler(cm);
2056
- break;
2057
- case CM_EVENT_BATT_IN:
2058
- case CM_EVENT_EXT_PWR_IN_OUT ... CM_EVENT_CHG_START_STOP:
2059
- misc_event_handler(cm, type);
2060
- break;
2061
- case CM_EVENT_UNKNOWN:
2062
- case CM_EVENT_OTHERS:
2063
- uevent_notify(cm, msg ? msg : default_event_names[type]);
2064
- break;
2065
- default:
2066
- dev_err(cm->dev, "%s: type not specified\n", __func__);
2067
- break;
2068
- }
2069
-}
2070
-EXPORT_SYMBOL_GPL(cm_notify_event);
20711770
20721771 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
20731772 MODULE_DESCRIPTION("Charger Manager");