xref: /OK3568_Linux_fs/kernel/drivers/power/supply/cros_usbpd-charger.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Power supply driver for ChromeOS EC based USB PD Charger.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2014 - 2018 Google, Inc
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/platform_data/cros_ec_commands.h>
10*4882a593Smuzhiyun #include <linux/platform_data/cros_ec_proto.h>
11*4882a593Smuzhiyun #include <linux/platform_data/cros_usbpd_notify.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include <linux/power_supply.h>
14*4882a593Smuzhiyun #include <linux/slab.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define CHARGER_USBPD_DIR_NAME			"CROS_USBPD_CHARGER%d"
17*4882a593Smuzhiyun #define CHARGER_DEDICATED_DIR_NAME		"CROS_DEDICATED_CHARGER"
18*4882a593Smuzhiyun #define CHARGER_DIR_NAME_LENGTH		(sizeof(CHARGER_USBPD_DIR_NAME) >= \
19*4882a593Smuzhiyun 					 sizeof(CHARGER_DEDICATED_DIR_NAME) ? \
20*4882a593Smuzhiyun 					 sizeof(CHARGER_USBPD_DIR_NAME) : \
21*4882a593Smuzhiyun 					 sizeof(CHARGER_DEDICATED_DIR_NAME))
22*4882a593Smuzhiyun #define CHARGER_CACHE_UPDATE_DELAY		msecs_to_jiffies(500)
23*4882a593Smuzhiyun #define CHARGER_MANUFACTURER_MODEL_LENGTH	32
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define DRV_NAME "cros-usbpd-charger"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun struct port_data {
28*4882a593Smuzhiyun 	int port_number;
29*4882a593Smuzhiyun 	char name[CHARGER_DIR_NAME_LENGTH];
30*4882a593Smuzhiyun 	char manufacturer[CHARGER_MANUFACTURER_MODEL_LENGTH];
31*4882a593Smuzhiyun 	char model_name[CHARGER_MANUFACTURER_MODEL_LENGTH];
32*4882a593Smuzhiyun 	struct power_supply *psy;
33*4882a593Smuzhiyun 	struct power_supply_desc psy_desc;
34*4882a593Smuzhiyun 	int psy_usb_type;
35*4882a593Smuzhiyun 	int psy_online;
36*4882a593Smuzhiyun 	int psy_status;
37*4882a593Smuzhiyun 	int psy_current_max;
38*4882a593Smuzhiyun 	int psy_voltage_max_design;
39*4882a593Smuzhiyun 	int psy_voltage_now;
40*4882a593Smuzhiyun 	int psy_power_max;
41*4882a593Smuzhiyun 	struct charger_data *charger;
42*4882a593Smuzhiyun 	unsigned long last_update;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct charger_data {
46*4882a593Smuzhiyun 	struct device *dev;
47*4882a593Smuzhiyun 	struct cros_ec_dev *ec_dev;
48*4882a593Smuzhiyun 	struct cros_ec_device *ec_device;
49*4882a593Smuzhiyun 	int num_charger_ports;
50*4882a593Smuzhiyun 	int num_usbpd_ports;
51*4882a593Smuzhiyun 	int num_registered_psy;
52*4882a593Smuzhiyun 	struct port_data *ports[EC_USB_PD_MAX_PORTS];
53*4882a593Smuzhiyun 	struct notifier_block notifier;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static enum power_supply_property cros_usbpd_charger_props[] = {
57*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
58*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
59*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_ONLINE,
60*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_STATUS,
61*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CURRENT_MAX,
62*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
63*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
64*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_MODEL_NAME,
65*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_MANUFACTURER,
66*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_USB_TYPE
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
70*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_ONLINE,
71*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_STATUS,
72*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
76*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_UNKNOWN,
77*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_SDP,
78*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_DCP,
79*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_CDP,
80*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_C,
81*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_PD,
82*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_PD_DRP,
83*4882a593Smuzhiyun 	POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun /* Input voltage/current limit in mV/mA. Default to none. */
87*4882a593Smuzhiyun static u16 input_voltage_limit = EC_POWER_LIMIT_NONE;
88*4882a593Smuzhiyun static u16 input_current_limit = EC_POWER_LIMIT_NONE;
89*4882a593Smuzhiyun 
cros_usbpd_charger_port_is_dedicated(struct port_data * port)90*4882a593Smuzhiyun static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	return port->port_number >= port->charger->num_usbpd_ports;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
cros_usbpd_charger_ec_command(struct charger_data * charger,unsigned int version,unsigned int command,void * outdata,unsigned int outsize,void * indata,unsigned int insize)95*4882a593Smuzhiyun static int cros_usbpd_charger_ec_command(struct charger_data *charger,
96*4882a593Smuzhiyun 					 unsigned int version,
97*4882a593Smuzhiyun 					 unsigned int command,
98*4882a593Smuzhiyun 					 void *outdata,
99*4882a593Smuzhiyun 					 unsigned int outsize,
100*4882a593Smuzhiyun 					 void *indata,
101*4882a593Smuzhiyun 					 unsigned int insize)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct cros_ec_dev *ec_dev = charger->ec_dev;
104*4882a593Smuzhiyun 	struct cros_ec_command *msg;
105*4882a593Smuzhiyun 	int ret;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
108*4882a593Smuzhiyun 	if (!msg)
109*4882a593Smuzhiyun 		return -ENOMEM;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	msg->version = version;
112*4882a593Smuzhiyun 	msg->command = ec_dev->cmd_offset + command;
113*4882a593Smuzhiyun 	msg->outsize = outsize;
114*4882a593Smuzhiyun 	msg->insize = insize;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	if (outsize)
117*4882a593Smuzhiyun 		memcpy(msg->data, outdata, outsize);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	ret = cros_ec_cmd_xfer_status(charger->ec_device, msg);
120*4882a593Smuzhiyun 	if (ret >= 0 && insize)
121*4882a593Smuzhiyun 		memcpy(indata, msg->data, insize);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	kfree(msg);
124*4882a593Smuzhiyun 	return ret;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
cros_usbpd_charger_get_num_ports(struct charger_data * charger)127*4882a593Smuzhiyun static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct ec_response_charge_port_count resp;
130*4882a593Smuzhiyun 	int ret;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	ret = cros_usbpd_charger_ec_command(charger, 0,
133*4882a593Smuzhiyun 					    EC_CMD_CHARGE_PORT_COUNT,
134*4882a593Smuzhiyun 					    NULL, 0, &resp, sizeof(resp));
135*4882a593Smuzhiyun 	if (ret < 0)
136*4882a593Smuzhiyun 		return ret;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return resp.port_count;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
cros_usbpd_charger_get_usbpd_num_ports(struct charger_data * charger)141*4882a593Smuzhiyun static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct ec_response_usb_pd_ports resp;
144*4882a593Smuzhiyun 	int ret;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	ret = cros_usbpd_charger_ec_command(charger, 0, EC_CMD_USB_PD_PORTS,
147*4882a593Smuzhiyun 					    NULL, 0, &resp, sizeof(resp));
148*4882a593Smuzhiyun 	if (ret < 0)
149*4882a593Smuzhiyun 		return ret;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return resp.num_ports;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
cros_usbpd_charger_get_discovery_info(struct port_data * port)154*4882a593Smuzhiyun static int cros_usbpd_charger_get_discovery_info(struct port_data *port)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	struct charger_data *charger = port->charger;
157*4882a593Smuzhiyun 	struct ec_params_usb_pd_discovery_entry resp;
158*4882a593Smuzhiyun 	struct ec_params_usb_pd_info_request req;
159*4882a593Smuzhiyun 	int ret;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	req.port = port->port_number;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	ret = cros_usbpd_charger_ec_command(charger, 0,
164*4882a593Smuzhiyun 					    EC_CMD_USB_PD_DISCOVERY,
165*4882a593Smuzhiyun 					    &req, sizeof(req),
166*4882a593Smuzhiyun 					    &resp, sizeof(resp));
167*4882a593Smuzhiyun 	if (ret < 0) {
168*4882a593Smuzhiyun 		dev_err(charger->dev,
169*4882a593Smuzhiyun 			"Unable to query discovery info (err:0x%x)\n", ret);
170*4882a593Smuzhiyun 		return ret;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	dev_dbg(charger->dev, "Port %d: VID = 0x%x, PID=0x%x, PTYPE=0x%x\n",
174*4882a593Smuzhiyun 		port->port_number, resp.vid, resp.pid, resp.ptype);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	snprintf(port->manufacturer, sizeof(port->manufacturer), "%x",
177*4882a593Smuzhiyun 		 resp.vid);
178*4882a593Smuzhiyun 	snprintf(port->model_name, sizeof(port->model_name), "%x", resp.pid);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
cros_usbpd_charger_get_power_info(struct port_data * port)183*4882a593Smuzhiyun static int cros_usbpd_charger_get_power_info(struct port_data *port)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	struct charger_data *charger = port->charger;
186*4882a593Smuzhiyun 	struct ec_response_usb_pd_power_info resp;
187*4882a593Smuzhiyun 	struct ec_params_usb_pd_power_info req;
188*4882a593Smuzhiyun 	int last_psy_status, last_psy_usb_type;
189*4882a593Smuzhiyun 	struct device *dev = charger->dev;
190*4882a593Smuzhiyun 	int ret;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	req.port = port->port_number;
193*4882a593Smuzhiyun 	ret = cros_usbpd_charger_ec_command(charger, 0,
194*4882a593Smuzhiyun 					    EC_CMD_USB_PD_POWER_INFO,
195*4882a593Smuzhiyun 					    &req, sizeof(req),
196*4882a593Smuzhiyun 					    &resp, sizeof(resp));
197*4882a593Smuzhiyun 	if (ret < 0) {
198*4882a593Smuzhiyun 		dev_err(dev, "Unable to query PD power info (err:0x%x)\n", ret);
199*4882a593Smuzhiyun 		return ret;
200*4882a593Smuzhiyun 	}
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	last_psy_status = port->psy_status;
203*4882a593Smuzhiyun 	last_psy_usb_type = port->psy_usb_type;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	switch (resp.role) {
206*4882a593Smuzhiyun 	case USB_PD_PORT_POWER_DISCONNECTED:
207*4882a593Smuzhiyun 		port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
208*4882a593Smuzhiyun 		port->psy_online = 0;
209*4882a593Smuzhiyun 		break;
210*4882a593Smuzhiyun 	case USB_PD_PORT_POWER_SOURCE:
211*4882a593Smuzhiyun 		port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
212*4882a593Smuzhiyun 		port->psy_online = 0;
213*4882a593Smuzhiyun 		break;
214*4882a593Smuzhiyun 	case USB_PD_PORT_POWER_SINK:
215*4882a593Smuzhiyun 		port->psy_status = POWER_SUPPLY_STATUS_CHARGING;
216*4882a593Smuzhiyun 		port->psy_online = 1;
217*4882a593Smuzhiyun 		break;
218*4882a593Smuzhiyun 	case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
219*4882a593Smuzhiyun 		port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
220*4882a593Smuzhiyun 		port->psy_online = 1;
221*4882a593Smuzhiyun 		break;
222*4882a593Smuzhiyun 	default:
223*4882a593Smuzhiyun 		dev_err(dev, "Unknown role %d\n", resp.role);
224*4882a593Smuzhiyun 		break;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	port->psy_voltage_max_design = resp.meas.voltage_max;
228*4882a593Smuzhiyun 	port->psy_voltage_now = resp.meas.voltage_now;
229*4882a593Smuzhiyun 	port->psy_current_max = resp.meas.current_max;
230*4882a593Smuzhiyun 	port->psy_power_max = resp.max_power;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	switch (resp.type) {
233*4882a593Smuzhiyun 	case USB_CHG_TYPE_BC12_SDP:
234*4882a593Smuzhiyun 	case USB_CHG_TYPE_VBUS:
235*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
236*4882a593Smuzhiyun 		break;
237*4882a593Smuzhiyun 	case USB_CHG_TYPE_NONE:
238*4882a593Smuzhiyun 		/*
239*4882a593Smuzhiyun 		 * For dual-role devices when we are a source, the firmware
240*4882a593Smuzhiyun 		 * reports the type as NONE. Report such chargers as type
241*4882a593Smuzhiyun 		 * USB_PD_DRP.
242*4882a593Smuzhiyun 		 */
243*4882a593Smuzhiyun 		if (resp.role == USB_PD_PORT_POWER_SOURCE && resp.dualrole)
244*4882a593Smuzhiyun 			port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
245*4882a593Smuzhiyun 		else
246*4882a593Smuzhiyun 			port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
247*4882a593Smuzhiyun 		break;
248*4882a593Smuzhiyun 	case USB_CHG_TYPE_OTHER:
249*4882a593Smuzhiyun 	case USB_CHG_TYPE_PROPRIETARY:
250*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID;
251*4882a593Smuzhiyun 		break;
252*4882a593Smuzhiyun 	case USB_CHG_TYPE_C:
253*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_C;
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 	case USB_CHG_TYPE_BC12_DCP:
256*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP;
257*4882a593Smuzhiyun 		break;
258*4882a593Smuzhiyun 	case USB_CHG_TYPE_BC12_CDP:
259*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP;
260*4882a593Smuzhiyun 		break;
261*4882a593Smuzhiyun 	case USB_CHG_TYPE_PD:
262*4882a593Smuzhiyun 		if (resp.dualrole)
263*4882a593Smuzhiyun 			port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
264*4882a593Smuzhiyun 		else
265*4882a593Smuzhiyun 			port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD;
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	case USB_CHG_TYPE_UNKNOWN:
268*4882a593Smuzhiyun 		/*
269*4882a593Smuzhiyun 		 * While the EC is trying to determine the type of charger that
270*4882a593Smuzhiyun 		 * has been plugged in, it will report the charger type as
271*4882a593Smuzhiyun 		 * unknown. Additionally since the power capabilities are
272*4882a593Smuzhiyun 		 * unknown, report the max current and voltage as zero.
273*4882a593Smuzhiyun 		 */
274*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
275*4882a593Smuzhiyun 		port->psy_voltage_max_design = 0;
276*4882a593Smuzhiyun 		port->psy_current_max = 0;
277*4882a593Smuzhiyun 		break;
278*4882a593Smuzhiyun 	default:
279*4882a593Smuzhiyun 		dev_err(dev, "Port %d: default case!\n", port->port_number);
280*4882a593Smuzhiyun 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
281*4882a593Smuzhiyun 	}
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	if (cros_usbpd_charger_port_is_dedicated(port))
284*4882a593Smuzhiyun 		port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
285*4882a593Smuzhiyun 	else
286*4882a593Smuzhiyun 		port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	dev_dbg(dev,
289*4882a593Smuzhiyun 		"Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n",
290*4882a593Smuzhiyun 		port->port_number, resp.type, resp.meas.voltage_max,
291*4882a593Smuzhiyun 		resp.meas.voltage_now, resp.meas.current_max,
292*4882a593Smuzhiyun 		resp.meas.current_lim, resp.max_power);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	/*
295*4882a593Smuzhiyun 	 * If power supply type or status changed, explicitly call
296*4882a593Smuzhiyun 	 * power_supply_changed. This results in udev event getting generated
297*4882a593Smuzhiyun 	 * and allows user mode apps to react quicker instead of waiting for
298*4882a593Smuzhiyun 	 * their next poll of power supply status.
299*4882a593Smuzhiyun 	 */
300*4882a593Smuzhiyun 	if (last_psy_usb_type != port->psy_usb_type ||
301*4882a593Smuzhiyun 	    last_psy_status != port->psy_status)
302*4882a593Smuzhiyun 		power_supply_changed(port->psy);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return 0;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
cros_usbpd_charger_get_port_status(struct port_data * port,bool ratelimit)307*4882a593Smuzhiyun static int cros_usbpd_charger_get_port_status(struct port_data *port,
308*4882a593Smuzhiyun 					      bool ratelimit)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	int ret;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (ratelimit &&
313*4882a593Smuzhiyun 	    time_is_after_jiffies(port->last_update +
314*4882a593Smuzhiyun 				  CHARGER_CACHE_UPDATE_DELAY))
315*4882a593Smuzhiyun 		return 0;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	ret = cros_usbpd_charger_get_power_info(port);
318*4882a593Smuzhiyun 	if (ret < 0)
319*4882a593Smuzhiyun 		return ret;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	if (!cros_usbpd_charger_port_is_dedicated(port))
322*4882a593Smuzhiyun 		ret = cros_usbpd_charger_get_discovery_info(port);
323*4882a593Smuzhiyun 	port->last_update = jiffies;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	return ret;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
cros_usbpd_charger_set_ext_power_limit(struct charger_data * charger,u16 current_lim,u16 voltage_lim)328*4882a593Smuzhiyun static int cros_usbpd_charger_set_ext_power_limit(struct charger_data *charger,
329*4882a593Smuzhiyun 						  u16 current_lim,
330*4882a593Smuzhiyun 						  u16 voltage_lim)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	struct ec_params_external_power_limit_v1 req;
333*4882a593Smuzhiyun 	int ret;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	req.current_lim = current_lim;
336*4882a593Smuzhiyun 	req.voltage_lim = voltage_lim;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	ret = cros_usbpd_charger_ec_command(charger, 0,
339*4882a593Smuzhiyun 					    EC_CMD_EXTERNAL_POWER_LIMIT,
340*4882a593Smuzhiyun 					    &req, sizeof(req), NULL, 0);
341*4882a593Smuzhiyun 	if (ret < 0)
342*4882a593Smuzhiyun 		dev_err(charger->dev,
343*4882a593Smuzhiyun 			"Unable to set the 'External Power Limit': %d\n", ret);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return ret;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
cros_usbpd_charger_power_changed(struct power_supply * psy)348*4882a593Smuzhiyun static void cros_usbpd_charger_power_changed(struct power_supply *psy)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct port_data *port = power_supply_get_drvdata(psy);
351*4882a593Smuzhiyun 	struct charger_data *charger = port->charger;
352*4882a593Smuzhiyun 	int i;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	for (i = 0; i < charger->num_registered_psy; i++)
355*4882a593Smuzhiyun 		cros_usbpd_charger_get_port_status(charger->ports[i], false);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
cros_usbpd_charger_get_prop(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)358*4882a593Smuzhiyun static int cros_usbpd_charger_get_prop(struct power_supply *psy,
359*4882a593Smuzhiyun 				       enum power_supply_property psp,
360*4882a593Smuzhiyun 				       union power_supply_propval *val)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	struct port_data *port = power_supply_get_drvdata(psy);
363*4882a593Smuzhiyun 	struct charger_data *charger = port->charger;
364*4882a593Smuzhiyun 	struct cros_ec_device *ec_device = charger->ec_device;
365*4882a593Smuzhiyun 	struct device *dev = charger->dev;
366*4882a593Smuzhiyun 	int ret;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/* Only refresh ec_port_status for dynamic properties */
369*4882a593Smuzhiyun 	switch (psp) {
370*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
371*4882a593Smuzhiyun 		/*
372*4882a593Smuzhiyun 		 * If mkbp_event_supported, then we can be assured that
373*4882a593Smuzhiyun 		 * the driver's state for the online property is consistent
374*4882a593Smuzhiyun 		 * with the hardware. However, if we aren't event driven,
375*4882a593Smuzhiyun 		 * the optimization before to skip an ec_port_status get
376*4882a593Smuzhiyun 		 * and only returned cached values of the online property will
377*4882a593Smuzhiyun 		 * cause a delay in detecting a cable attach until one of the
378*4882a593Smuzhiyun 		 * other properties are read.
379*4882a593Smuzhiyun 		 *
380*4882a593Smuzhiyun 		 * Allow an ec_port_status refresh for online property check
381*4882a593Smuzhiyun 		 * if we're not already online to check for plug events if
382*4882a593Smuzhiyun 		 * not mkbp_event_supported.
383*4882a593Smuzhiyun 		 */
384*4882a593Smuzhiyun 		if (ec_device->mkbp_event_supported || port->psy_online)
385*4882a593Smuzhiyun 			break;
386*4882a593Smuzhiyun 		fallthrough;
387*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CURRENT_MAX:
388*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
389*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
390*4882a593Smuzhiyun 		ret = cros_usbpd_charger_get_port_status(port, true);
391*4882a593Smuzhiyun 		if (ret < 0) {
392*4882a593Smuzhiyun 			dev_err(dev, "Failed to get port status (err:0x%x)\n",
393*4882a593Smuzhiyun 				ret);
394*4882a593Smuzhiyun 			return -EINVAL;
395*4882a593Smuzhiyun 		}
396*4882a593Smuzhiyun 		break;
397*4882a593Smuzhiyun 	default:
398*4882a593Smuzhiyun 		break;
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	switch (psp) {
402*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
403*4882a593Smuzhiyun 		val->intval = port->psy_online;
404*4882a593Smuzhiyun 		break;
405*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_STATUS:
406*4882a593Smuzhiyun 		val->intval = port->psy_status;
407*4882a593Smuzhiyun 		break;
408*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CURRENT_MAX:
409*4882a593Smuzhiyun 		val->intval = port->psy_current_max * 1000;
410*4882a593Smuzhiyun 		break;
411*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
412*4882a593Smuzhiyun 		val->intval = port->psy_voltage_max_design * 1000;
413*4882a593Smuzhiyun 		break;
414*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
415*4882a593Smuzhiyun 		val->intval = port->psy_voltage_now * 1000;
416*4882a593Smuzhiyun 		break;
417*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_USB_TYPE:
418*4882a593Smuzhiyun 		val->intval = port->psy_usb_type;
419*4882a593Smuzhiyun 		break;
420*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
421*4882a593Smuzhiyun 		if (input_current_limit == EC_POWER_LIMIT_NONE)
422*4882a593Smuzhiyun 			val->intval = -1;
423*4882a593Smuzhiyun 		else
424*4882a593Smuzhiyun 			val->intval = input_current_limit * 1000;
425*4882a593Smuzhiyun 		break;
426*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
427*4882a593Smuzhiyun 		if (input_voltage_limit == EC_POWER_LIMIT_NONE)
428*4882a593Smuzhiyun 			val->intval = -1;
429*4882a593Smuzhiyun 		else
430*4882a593Smuzhiyun 			val->intval = input_voltage_limit * 1000;
431*4882a593Smuzhiyun 		break;
432*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_MODEL_NAME:
433*4882a593Smuzhiyun 		val->strval = port->model_name;
434*4882a593Smuzhiyun 		break;
435*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_MANUFACTURER:
436*4882a593Smuzhiyun 		val->strval = port->manufacturer;
437*4882a593Smuzhiyun 		break;
438*4882a593Smuzhiyun 	default:
439*4882a593Smuzhiyun 		return -EINVAL;
440*4882a593Smuzhiyun 	}
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	return 0;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun 
cros_usbpd_charger_set_prop(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)445*4882a593Smuzhiyun static int cros_usbpd_charger_set_prop(struct power_supply *psy,
446*4882a593Smuzhiyun 				       enum power_supply_property psp,
447*4882a593Smuzhiyun 				       const union power_supply_propval *val)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	struct port_data *port = power_supply_get_drvdata(psy);
450*4882a593Smuzhiyun 	struct charger_data *charger = port->charger;
451*4882a593Smuzhiyun 	struct device *dev = charger->dev;
452*4882a593Smuzhiyun 	u16 intval;
453*4882a593Smuzhiyun 	int ret;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	/* U16_MAX in mV/mA is the maximum supported value */
456*4882a593Smuzhiyun 	if (val->intval >= U16_MAX * 1000)
457*4882a593Smuzhiyun 		return -EINVAL;
458*4882a593Smuzhiyun 	/* A negative number is used to clear the limit */
459*4882a593Smuzhiyun 	if (val->intval < 0)
460*4882a593Smuzhiyun 		intval = EC_POWER_LIMIT_NONE;
461*4882a593Smuzhiyun 	else	/* Convert from uA/uV to mA/mV */
462*4882a593Smuzhiyun 		intval = val->intval / 1000;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	switch (psp) {
465*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
466*4882a593Smuzhiyun 		ret = cros_usbpd_charger_set_ext_power_limit(charger, intval,
467*4882a593Smuzhiyun 							input_voltage_limit);
468*4882a593Smuzhiyun 		if (ret < 0)
469*4882a593Smuzhiyun 			break;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 		input_current_limit = intval;
472*4882a593Smuzhiyun 		if (input_current_limit == EC_POWER_LIMIT_NONE)
473*4882a593Smuzhiyun 			dev_info(dev,
474*4882a593Smuzhiyun 			  "External Current Limit cleared for all ports\n");
475*4882a593Smuzhiyun 		else
476*4882a593Smuzhiyun 			dev_info(dev,
477*4882a593Smuzhiyun 			  "External Current Limit set to %dmA for all ports\n",
478*4882a593Smuzhiyun 			  input_current_limit);
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
481*4882a593Smuzhiyun 		ret = cros_usbpd_charger_set_ext_power_limit(charger,
482*4882a593Smuzhiyun 							input_current_limit,
483*4882a593Smuzhiyun 							intval);
484*4882a593Smuzhiyun 		if (ret < 0)
485*4882a593Smuzhiyun 			break;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 		input_voltage_limit = intval;
488*4882a593Smuzhiyun 		if (input_voltage_limit == EC_POWER_LIMIT_NONE)
489*4882a593Smuzhiyun 			dev_info(dev,
490*4882a593Smuzhiyun 			  "External Voltage Limit cleared for all ports\n");
491*4882a593Smuzhiyun 		else
492*4882a593Smuzhiyun 			dev_info(dev,
493*4882a593Smuzhiyun 			  "External Voltage Limit set to %dmV for all ports\n",
494*4882a593Smuzhiyun 			  input_voltage_limit);
495*4882a593Smuzhiyun 		break;
496*4882a593Smuzhiyun 	default:
497*4882a593Smuzhiyun 		ret = -EINVAL;
498*4882a593Smuzhiyun 	}
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	return ret;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun 
cros_usbpd_charger_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)503*4882a593Smuzhiyun static int cros_usbpd_charger_property_is_writeable(struct power_supply *psy,
504*4882a593Smuzhiyun 						enum power_supply_property psp)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	int ret;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	switch (psp) {
509*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
510*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
511*4882a593Smuzhiyun 		ret = 1;
512*4882a593Smuzhiyun 		break;
513*4882a593Smuzhiyun 	default:
514*4882a593Smuzhiyun 		ret = 0;
515*4882a593Smuzhiyun 	}
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	return ret;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
cros_usbpd_charger_ec_event(struct notifier_block * nb,unsigned long host_event,void * _notify)520*4882a593Smuzhiyun static int cros_usbpd_charger_ec_event(struct notifier_block *nb,
521*4882a593Smuzhiyun 				       unsigned long host_event,
522*4882a593Smuzhiyun 				       void *_notify)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun 	struct charger_data *charger = container_of(nb, struct charger_data,
525*4882a593Smuzhiyun 						    notifier);
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	cros_usbpd_charger_power_changed(charger->ports[0]->psy);
528*4882a593Smuzhiyun 	return NOTIFY_OK;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
cros_usbpd_charger_unregister_notifier(void * data)531*4882a593Smuzhiyun static void cros_usbpd_charger_unregister_notifier(void *data)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	struct charger_data *charger = data;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	cros_usbpd_unregister_notify(&charger->notifier);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun 
cros_usbpd_charger_probe(struct platform_device * pd)538*4882a593Smuzhiyun static int cros_usbpd_charger_probe(struct platform_device *pd)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun 	struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
541*4882a593Smuzhiyun 	struct cros_ec_device *ec_device = ec_dev->ec_dev;
542*4882a593Smuzhiyun 	struct power_supply_desc *psy_desc;
543*4882a593Smuzhiyun 	struct device *dev = &pd->dev;
544*4882a593Smuzhiyun 	struct charger_data *charger;
545*4882a593Smuzhiyun 	struct power_supply *psy;
546*4882a593Smuzhiyun 	struct port_data *port;
547*4882a593Smuzhiyun 	int ret = -EINVAL;
548*4882a593Smuzhiyun 	int i;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	charger = devm_kzalloc(dev, sizeof(struct charger_data),
551*4882a593Smuzhiyun 			       GFP_KERNEL);
552*4882a593Smuzhiyun 	if (!charger)
553*4882a593Smuzhiyun 		return -ENOMEM;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	charger->dev = dev;
556*4882a593Smuzhiyun 	charger->ec_dev = ec_dev;
557*4882a593Smuzhiyun 	charger->ec_device = ec_device;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	platform_set_drvdata(pd, charger);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	/*
562*4882a593Smuzhiyun 	 * We need to know the number of USB PD ports in order to know whether
563*4882a593Smuzhiyun 	 * there is a dedicated port. The dedicated port will always be
564*4882a593Smuzhiyun 	 * after the USB PD ports, and there should be only one.
565*4882a593Smuzhiyun 	 */
566*4882a593Smuzhiyun 	charger->num_usbpd_ports =
567*4882a593Smuzhiyun 		cros_usbpd_charger_get_usbpd_num_ports(charger);
568*4882a593Smuzhiyun 	if (charger->num_usbpd_ports <= 0) {
569*4882a593Smuzhiyun 		/*
570*4882a593Smuzhiyun 		 * This can happen on a system that doesn't support USB PD.
571*4882a593Smuzhiyun 		 * Log a message, but no need to warn.
572*4882a593Smuzhiyun 		 */
573*4882a593Smuzhiyun 		dev_info(dev, "No USB PD charging ports found\n");
574*4882a593Smuzhiyun 	}
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger);
577*4882a593Smuzhiyun 	if (charger->num_charger_ports < 0) {
578*4882a593Smuzhiyun 		/*
579*4882a593Smuzhiyun 		 * This can happen on a system that doesn't support USB PD.
580*4882a593Smuzhiyun 		 * Log a message, but no need to warn.
581*4882a593Smuzhiyun 		 * Older ECs do not support the above command, in that case
582*4882a593Smuzhiyun 		 * let's set up the number of charger ports equal to the number
583*4882a593Smuzhiyun 		 * of USB PD ports
584*4882a593Smuzhiyun 		 */
585*4882a593Smuzhiyun 		dev_info(dev, "Could not get charger port count\n");
586*4882a593Smuzhiyun 		charger->num_charger_ports = charger->num_usbpd_ports;
587*4882a593Smuzhiyun 	}
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	if (charger->num_charger_ports <= 0) {
590*4882a593Smuzhiyun 		/*
591*4882a593Smuzhiyun 		 * This can happen on a system that doesn't support USB PD and
592*4882a593Smuzhiyun 		 * doesn't have a dedicated port.
593*4882a593Smuzhiyun 		 * Log a message, but no need to warn.
594*4882a593Smuzhiyun 		 */
595*4882a593Smuzhiyun 		dev_info(dev, "No charging ports found\n");
596*4882a593Smuzhiyun 		ret = -ENODEV;
597*4882a593Smuzhiyun 		goto fail_nowarn;
598*4882a593Smuzhiyun 	}
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	/*
601*4882a593Smuzhiyun 	 * Sanity checks on the number of ports:
602*4882a593Smuzhiyun 	 *  there should be at most 1 dedicated port
603*4882a593Smuzhiyun 	 */
604*4882a593Smuzhiyun 	if (charger->num_charger_ports < charger->num_usbpd_ports ||
605*4882a593Smuzhiyun 	    charger->num_charger_ports > (charger->num_usbpd_ports + 1)) {
606*4882a593Smuzhiyun 		dev_err(dev, "Unexpected number of charge port count\n");
607*4882a593Smuzhiyun 		ret = -EPROTO;
608*4882a593Smuzhiyun 		goto fail_nowarn;
609*4882a593Smuzhiyun 	}
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	for (i = 0; i < charger->num_charger_ports; i++) {
612*4882a593Smuzhiyun 		struct power_supply_config psy_cfg = {};
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 		port = devm_kzalloc(dev, sizeof(struct port_data), GFP_KERNEL);
615*4882a593Smuzhiyun 		if (!port) {
616*4882a593Smuzhiyun 			ret = -ENOMEM;
617*4882a593Smuzhiyun 			goto fail;
618*4882a593Smuzhiyun 		}
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 		port->charger = charger;
621*4882a593Smuzhiyun 		port->port_number = i;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 		psy_desc = &port->psy_desc;
624*4882a593Smuzhiyun 		psy_desc->get_property = cros_usbpd_charger_get_prop;
625*4882a593Smuzhiyun 		psy_desc->set_property = cros_usbpd_charger_set_prop;
626*4882a593Smuzhiyun 		psy_desc->property_is_writeable =
627*4882a593Smuzhiyun 				cros_usbpd_charger_property_is_writeable;
628*4882a593Smuzhiyun 		psy_desc->external_power_changed =
629*4882a593Smuzhiyun 					cros_usbpd_charger_power_changed;
630*4882a593Smuzhiyun 		psy_cfg.drv_data = port;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 		if (cros_usbpd_charger_port_is_dedicated(port)) {
633*4882a593Smuzhiyun 			sprintf(port->name, CHARGER_DEDICATED_DIR_NAME);
634*4882a593Smuzhiyun 			psy_desc->type = POWER_SUPPLY_TYPE_MAINS;
635*4882a593Smuzhiyun 			psy_desc->properties =
636*4882a593Smuzhiyun 				cros_usbpd_dedicated_charger_props;
637*4882a593Smuzhiyun 			psy_desc->num_properties =
638*4882a593Smuzhiyun 				ARRAY_SIZE(cros_usbpd_dedicated_charger_props);
639*4882a593Smuzhiyun 		} else {
640*4882a593Smuzhiyun 			sprintf(port->name, CHARGER_USBPD_DIR_NAME, i);
641*4882a593Smuzhiyun 			psy_desc->type = POWER_SUPPLY_TYPE_USB;
642*4882a593Smuzhiyun 			psy_desc->properties = cros_usbpd_charger_props;
643*4882a593Smuzhiyun 			psy_desc->num_properties =
644*4882a593Smuzhiyun 				ARRAY_SIZE(cros_usbpd_charger_props);
645*4882a593Smuzhiyun 			psy_desc->usb_types = cros_usbpd_charger_usb_types;
646*4882a593Smuzhiyun 			psy_desc->num_usb_types =
647*4882a593Smuzhiyun 				ARRAY_SIZE(cros_usbpd_charger_usb_types);
648*4882a593Smuzhiyun 		}
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 		psy_desc->name = port->name;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 		psy = devm_power_supply_register_no_ws(dev, psy_desc,
653*4882a593Smuzhiyun 						       &psy_cfg);
654*4882a593Smuzhiyun 		if (IS_ERR(psy)) {
655*4882a593Smuzhiyun 			dev_err(dev, "Failed to register power supply\n");
656*4882a593Smuzhiyun 			continue;
657*4882a593Smuzhiyun 		}
658*4882a593Smuzhiyun 		port->psy = psy;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 		charger->ports[charger->num_registered_psy++] = port;
661*4882a593Smuzhiyun 	}
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	if (!charger->num_registered_psy) {
664*4882a593Smuzhiyun 		ret = -ENODEV;
665*4882a593Smuzhiyun 		dev_err(dev, "No power supplies registered\n");
666*4882a593Smuzhiyun 		goto fail;
667*4882a593Smuzhiyun 	}
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	/* Get PD events from the EC */
670*4882a593Smuzhiyun 	charger->notifier.notifier_call = cros_usbpd_charger_ec_event;
671*4882a593Smuzhiyun 	ret = cros_usbpd_register_notify(&charger->notifier);
672*4882a593Smuzhiyun 	if (ret < 0) {
673*4882a593Smuzhiyun 		dev_warn(dev, "failed to register notifier\n");
674*4882a593Smuzhiyun 	} else {
675*4882a593Smuzhiyun 		ret = devm_add_action_or_reset(dev,
676*4882a593Smuzhiyun 				cros_usbpd_charger_unregister_notifier,
677*4882a593Smuzhiyun 				charger);
678*4882a593Smuzhiyun 		if (ret < 0)
679*4882a593Smuzhiyun 			goto fail;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return 0;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun fail:
685*4882a593Smuzhiyun 	WARN(1, "%s: Failing probe (err:0x%x)\n", dev_name(dev), ret);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun fail_nowarn:
688*4882a593Smuzhiyun 	dev_info(dev, "Failing probe (err:0x%x)\n", ret);
689*4882a593Smuzhiyun 	return ret;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
cros_usbpd_charger_resume(struct device * dev)693*4882a593Smuzhiyun static int cros_usbpd_charger_resume(struct device *dev)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun 	struct charger_data *charger = dev_get_drvdata(dev);
696*4882a593Smuzhiyun 	int i;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	if (!charger)
699*4882a593Smuzhiyun 		return 0;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	for (i = 0; i < charger->num_registered_psy; i++) {
702*4882a593Smuzhiyun 		power_supply_changed(charger->ports[i]->psy);
703*4882a593Smuzhiyun 		charger->ports[i]->last_update =
704*4882a593Smuzhiyun 				jiffies - CHARGER_CACHE_UPDATE_DELAY;
705*4882a593Smuzhiyun 	}
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	return 0;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun #endif
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL,
712*4882a593Smuzhiyun 			 cros_usbpd_charger_resume);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun static struct platform_driver cros_usbpd_charger_driver = {
715*4882a593Smuzhiyun 	.driver = {
716*4882a593Smuzhiyun 		.name = DRV_NAME,
717*4882a593Smuzhiyun 		.pm = &cros_usbpd_charger_pm_ops,
718*4882a593Smuzhiyun 	},
719*4882a593Smuzhiyun 	.probe = cros_usbpd_charger_probe
720*4882a593Smuzhiyun };
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun module_platform_driver(cros_usbpd_charger_driver);
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun MODULE_LICENSE("GPL");
725*4882a593Smuzhiyun MODULE_DESCRIPTION("ChromeOS EC USBPD charger");
726*4882a593Smuzhiyun MODULE_ALIAS("platform:" DRV_NAME);
727