diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-power-wilco | 30 | ||||
-rw-r--r-- | drivers/power/supply/Kconfig | 9 | ||||
-rw-r--r-- | drivers/power/supply/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/supply/wilco-charger.c | 187 |
4 files changed, 227 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-power-wilco b/Documentation/ABI/testing/sysfs-class-power-wilco new file mode 100644 index 000000000000..da1d6ffe5e3c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-power-wilco | |||
@@ -0,0 +1,30 @@ | |||
1 | What: /sys/class/power_supply/wilco-charger/charge_type | ||
2 | Date: April 2019 | ||
3 | KernelVersion: 5.2 | ||
4 | Description: | ||
5 | What charging algorithm to use: | ||
6 | |||
7 | Standard: Fully charges battery at a standard rate. | ||
8 | Adaptive: Battery settings adaptively optimized based on | ||
9 | typical battery usage pattern. | ||
10 | Fast: Battery charges over a shorter period. | ||
11 | Trickle: Extends battery lifespan, intended for users who | ||
12 | primarily use their Chromebook while connected to AC. | ||
13 | Custom: A low and high threshold percentage is specified. | ||
14 | Charging begins when level drops below | ||
15 | charge_control_start_threshold, and ceases when | ||
16 | level is above charge_control_end_threshold. | ||
17 | |||
18 | What: /sys/class/power_supply/wilco-charger/charge_control_start_threshold | ||
19 | Date: April 2019 | ||
20 | KernelVersion: 5.2 | ||
21 | Description: | ||
22 | Used when charge_type="Custom", as described above. Measured in | ||
23 | percentages. The valid range is [50, 95]. | ||
24 | |||
25 | What: /sys/class/power_supply/wilco-charger/charge_control_end_threshold | ||
26 | Date: April 2019 | ||
27 | KernelVersion: 5.2 | ||
28 | Description: | ||
29 | Used when charge_type="Custom", as described above. Measured in | ||
30 | percentages. The valid range is [55, 100]. | ||
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 1f2252cb95fd..4c01598f5ccb 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig | |||
@@ -702,4 +702,13 @@ config CHARGER_UCS1002 | |||
702 | Say Y to enable support for Microchip UCS1002 Programmable | 702 | Say Y to enable support for Microchip UCS1002 Programmable |
703 | USB Port Power Controller with Charger Emulation. | 703 | USB Port Power Controller with Charger Emulation. |
704 | 704 | ||
705 | config CHARGER_WILCO | ||
706 | tristate "Wilco EC based charger for ChromeOS" | ||
707 | depends on WILCO_EC | ||
708 | help | ||
709 | Say Y here to enable control of the charging routines performed | ||
710 | by the Embedded Controller on the Chromebook named Wilco. Further | ||
711 | information can be found in | ||
712 | Documentation/ABI/testing/sysfs-class-power-wilco | ||
713 | |||
705 | endif # POWER_SUPPLY | 714 | endif # POWER_SUPPLY |
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index c47e88ba16b9..d2263e1e2b6f 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile | |||
@@ -91,3 +91,4 @@ obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o | |||
91 | obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o | 91 | obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o |
92 | obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o | 92 | obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o |
93 | obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o | 93 | obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o |
94 | obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o | ||
diff --git a/drivers/power/supply/wilco-charger.c b/drivers/power/supply/wilco-charger.c new file mode 100644 index 000000000000..b3c6d7cdd731 --- /dev/null +++ b/drivers/power/supply/wilco-charger.c | |||
@@ -0,0 +1,187 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Charging control driver for the Wilco EC | ||
4 | * | ||
5 | * Copyright 2019 Google LLC | ||
6 | * | ||
7 | * See Documentation/ABI/testing/sysfs-class-power and | ||
8 | * Documentation/ABI/testing/sysfs-class-power-wilco for userspace interface | ||
9 | * and other info. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/platform_data/wilco-ec.h> | ||
15 | #include <linux/power_supply.h> | ||
16 | |||
17 | #define DRV_NAME "wilco-charger" | ||
18 | |||
19 | /* Property IDs and related EC constants */ | ||
20 | #define PID_CHARGE_MODE 0x0710 | ||
21 | #define PID_CHARGE_LOWER_LIMIT 0x0711 | ||
22 | #define PID_CHARGE_UPPER_LIMIT 0x0712 | ||
23 | |||
24 | enum charge_mode { | ||
25 | CHARGE_MODE_STD = 1, /* Used for Standard */ | ||
26 | CHARGE_MODE_EXP = 2, /* Express Charge, used for Fast */ | ||
27 | CHARGE_MODE_AC = 3, /* Mostly AC use, used for Trickle */ | ||
28 | CHARGE_MODE_AUTO = 4, /* Used for Adaptive */ | ||
29 | CHARGE_MODE_CUSTOM = 5, /* Used for Custom */ | ||
30 | }; | ||
31 | |||
32 | #define CHARGE_LOWER_LIMIT_MIN 50 | ||
33 | #define CHARGE_LOWER_LIMIT_MAX 95 | ||
34 | #define CHARGE_UPPER_LIMIT_MIN 55 | ||
35 | #define CHARGE_UPPER_LIMIT_MAX 100 | ||
36 | |||
37 | /* Convert from POWER_SUPPLY_PROP_CHARGE_TYPE value to the EC's charge mode */ | ||
38 | static int psp_val_to_charge_mode(int psp_val) | ||
39 | { | ||
40 | switch (psp_val) { | ||
41 | case POWER_SUPPLY_CHARGE_TYPE_TRICKLE: | ||
42 | return CHARGE_MODE_AC; | ||
43 | case POWER_SUPPLY_CHARGE_TYPE_FAST: | ||
44 | return CHARGE_MODE_EXP; | ||
45 | case POWER_SUPPLY_CHARGE_TYPE_STANDARD: | ||
46 | return CHARGE_MODE_STD; | ||
47 | case POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE: | ||
48 | return CHARGE_MODE_AUTO; | ||
49 | case POWER_SUPPLY_CHARGE_TYPE_CUSTOM: | ||
50 | return CHARGE_MODE_CUSTOM; | ||
51 | default: | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /* Convert from EC's charge mode to POWER_SUPPLY_PROP_CHARGE_TYPE value */ | ||
57 | static int charge_mode_to_psp_val(enum charge_mode mode) | ||
58 | { | ||
59 | switch (mode) { | ||
60 | case CHARGE_MODE_AC: | ||
61 | return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; | ||
62 | case CHARGE_MODE_EXP: | ||
63 | return POWER_SUPPLY_CHARGE_TYPE_FAST; | ||
64 | case CHARGE_MODE_STD: | ||
65 | return POWER_SUPPLY_CHARGE_TYPE_STANDARD; | ||
66 | case CHARGE_MODE_AUTO: | ||
67 | return POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE; | ||
68 | case CHARGE_MODE_CUSTOM: | ||
69 | return POWER_SUPPLY_CHARGE_TYPE_CUSTOM; | ||
70 | default: | ||
71 | return -EINVAL; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static enum power_supply_property wilco_charge_props[] = { | ||
76 | POWER_SUPPLY_PROP_CHARGE_TYPE, | ||
77 | POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, | ||
78 | POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, | ||
79 | }; | ||
80 | |||
81 | static int wilco_charge_get_property(struct power_supply *psy, | ||
82 | enum power_supply_property psp, | ||
83 | union power_supply_propval *val) | ||
84 | { | ||
85 | struct wilco_ec_device *ec = power_supply_get_drvdata(psy); | ||
86 | u32 property_id; | ||
87 | int ret; | ||
88 | u8 raw; | ||
89 | |||
90 | switch (psp) { | ||
91 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
92 | property_id = PID_CHARGE_MODE; | ||
93 | break; | ||
94 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: | ||
95 | property_id = PID_CHARGE_LOWER_LIMIT; | ||
96 | break; | ||
97 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: | ||
98 | property_id = PID_CHARGE_UPPER_LIMIT; | ||
99 | break; | ||
100 | default: | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | ret = wilco_ec_get_byte_property(ec, property_id, &raw); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | if (property_id == PID_CHARGE_MODE) { | ||
108 | ret = charge_mode_to_psp_val(raw); | ||
109 | if (ret < 0) | ||
110 | return -EBADMSG; | ||
111 | raw = ret; | ||
112 | } | ||
113 | val->intval = raw; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int wilco_charge_set_property(struct power_supply *psy, | ||
119 | enum power_supply_property psp, | ||
120 | const union power_supply_propval *val) | ||
121 | { | ||
122 | struct wilco_ec_device *ec = power_supply_get_drvdata(psy); | ||
123 | int mode; | ||
124 | |||
125 | switch (psp) { | ||
126 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
127 | mode = psp_val_to_charge_mode(val->intval); | ||
128 | if (mode < 0) | ||
129 | return -EINVAL; | ||
130 | return wilco_ec_set_byte_property(ec, PID_CHARGE_MODE, mode); | ||
131 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: | ||
132 | if (val->intval < CHARGE_LOWER_LIMIT_MIN || | ||
133 | val->intval > CHARGE_LOWER_LIMIT_MAX) | ||
134 | return -EINVAL; | ||
135 | return wilco_ec_set_byte_property(ec, PID_CHARGE_LOWER_LIMIT, | ||
136 | val->intval); | ||
137 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: | ||
138 | if (val->intval < CHARGE_UPPER_LIMIT_MIN || | ||
139 | val->intval > CHARGE_UPPER_LIMIT_MAX) | ||
140 | return -EINVAL; | ||
141 | return wilco_ec_set_byte_property(ec, PID_CHARGE_UPPER_LIMIT, | ||
142 | val->intval); | ||
143 | default: | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static int wilco_charge_property_is_writeable(struct power_supply *psy, | ||
149 | enum power_supply_property psp) | ||
150 | { | ||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | static const struct power_supply_desc wilco_ps_desc = { | ||
155 | .properties = wilco_charge_props, | ||
156 | .num_properties = ARRAY_SIZE(wilco_charge_props), | ||
157 | .get_property = wilco_charge_get_property, | ||
158 | .set_property = wilco_charge_set_property, | ||
159 | .property_is_writeable = wilco_charge_property_is_writeable, | ||
160 | .name = DRV_NAME, | ||
161 | .type = POWER_SUPPLY_TYPE_MAINS, | ||
162 | }; | ||
163 | |||
164 | static int wilco_charge_probe(struct platform_device *pdev) | ||
165 | { | ||
166 | struct wilco_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | ||
167 | struct power_supply_config psy_cfg = {}; | ||
168 | struct power_supply *psy; | ||
169 | |||
170 | psy_cfg.drv_data = ec; | ||
171 | psy = devm_power_supply_register(&pdev->dev, &wilco_ps_desc, &psy_cfg); | ||
172 | |||
173 | return PTR_ERR_OR_ZERO(psy); | ||
174 | } | ||
175 | |||
176 | static struct platform_driver wilco_charge_driver = { | ||
177 | .probe = wilco_charge_probe, | ||
178 | .driver = { | ||
179 | .name = DRV_NAME, | ||
180 | } | ||
181 | }; | ||
182 | module_platform_driver(wilco_charge_driver); | ||
183 | |||
184 | MODULE_ALIAS("platform:" DRV_NAME); | ||
185 | MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
187 | MODULE_DESCRIPTION("Wilco EC charge control driver"); | ||