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