Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Power supply driver for ChromeOS EC based USB PD Charger.
0004  *
0005  * Copyright (c) 2014 - 2018 Google, Inc
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/platform_data/cros_ec_commands.h>
0010 #include <linux/platform_data/cros_ec_proto.h>
0011 #include <linux/platform_data/cros_usbpd_notify.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/power_supply.h>
0014 #include <linux/slab.h>
0015 
0016 #define CHARGER_USBPD_DIR_NAME          "CROS_USBPD_CHARGER%d"
0017 #define CHARGER_DEDICATED_DIR_NAME      "CROS_DEDICATED_CHARGER"
0018 #define CHARGER_DIR_NAME_LENGTH     (sizeof(CHARGER_USBPD_DIR_NAME) >= \
0019                      sizeof(CHARGER_DEDICATED_DIR_NAME) ? \
0020                      sizeof(CHARGER_USBPD_DIR_NAME) : \
0021                      sizeof(CHARGER_DEDICATED_DIR_NAME))
0022 #define CHARGER_CACHE_UPDATE_DELAY      msecs_to_jiffies(500)
0023 #define CHARGER_MANUFACTURER_MODEL_LENGTH   32
0024 
0025 #define DRV_NAME "cros-usbpd-charger"
0026 
0027 struct port_data {
0028     int port_number;
0029     char name[CHARGER_DIR_NAME_LENGTH];
0030     char manufacturer[CHARGER_MANUFACTURER_MODEL_LENGTH];
0031     char model_name[CHARGER_MANUFACTURER_MODEL_LENGTH];
0032     struct power_supply *psy;
0033     struct power_supply_desc psy_desc;
0034     int psy_usb_type;
0035     int psy_online;
0036     int psy_status;
0037     int psy_current_max;
0038     int psy_voltage_max_design;
0039     int psy_voltage_now;
0040     int psy_power_max;
0041     struct charger_data *charger;
0042     unsigned long last_update;
0043 };
0044 
0045 struct charger_data {
0046     struct device *dev;
0047     struct cros_ec_dev *ec_dev;
0048     struct cros_ec_device *ec_device;
0049     int num_charger_ports;
0050     int num_usbpd_ports;
0051     int num_registered_psy;
0052     struct port_data *ports[EC_USB_PD_MAX_PORTS];
0053     struct notifier_block notifier;
0054 };
0055 
0056 static enum power_supply_property cros_usbpd_charger_props[] = {
0057     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
0058     POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
0059     POWER_SUPPLY_PROP_ONLINE,
0060     POWER_SUPPLY_PROP_STATUS,
0061     POWER_SUPPLY_PROP_CURRENT_MAX,
0062     POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
0063     POWER_SUPPLY_PROP_VOLTAGE_NOW,
0064     POWER_SUPPLY_PROP_MODEL_NAME,
0065     POWER_SUPPLY_PROP_MANUFACTURER,
0066     POWER_SUPPLY_PROP_USB_TYPE
0067 };
0068 
0069 static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
0070     POWER_SUPPLY_PROP_ONLINE,
0071     POWER_SUPPLY_PROP_STATUS,
0072     POWER_SUPPLY_PROP_VOLTAGE_NOW,
0073 };
0074 
0075 static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
0076     POWER_SUPPLY_USB_TYPE_UNKNOWN,
0077     POWER_SUPPLY_USB_TYPE_SDP,
0078     POWER_SUPPLY_USB_TYPE_DCP,
0079     POWER_SUPPLY_USB_TYPE_CDP,
0080     POWER_SUPPLY_USB_TYPE_C,
0081     POWER_SUPPLY_USB_TYPE_PD,
0082     POWER_SUPPLY_USB_TYPE_PD_DRP,
0083     POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
0084 };
0085 
0086 /* Input voltage/current limit in mV/mA. Default to none. */
0087 static u16 input_voltage_limit = EC_POWER_LIMIT_NONE;
0088 static u16 input_current_limit = EC_POWER_LIMIT_NONE;
0089 
0090 static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port)
0091 {
0092     return port->port_number >= port->charger->num_usbpd_ports;
0093 }
0094 
0095 static int cros_usbpd_charger_ec_command(struct charger_data *charger,
0096                      unsigned int version,
0097                      unsigned int command,
0098                      void *outdata,
0099                      unsigned int outsize,
0100                      void *indata,
0101                      unsigned int insize)
0102 {
0103     struct cros_ec_dev *ec_dev = charger->ec_dev;
0104     struct cros_ec_command *msg;
0105     int ret;
0106 
0107     msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL);
0108     if (!msg)
0109         return -ENOMEM;
0110 
0111     msg->version = version;
0112     msg->command = ec_dev->cmd_offset + command;
0113     msg->outsize = outsize;
0114     msg->insize = insize;
0115 
0116     if (outsize)
0117         memcpy(msg->data, outdata, outsize);
0118 
0119     ret = cros_ec_cmd_xfer_status(charger->ec_device, msg);
0120     if (ret >= 0 && insize)
0121         memcpy(indata, msg->data, insize);
0122 
0123     kfree(msg);
0124     return ret;
0125 }
0126 
0127 static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
0128 {
0129     struct ec_response_charge_port_count resp;
0130     int ret;
0131 
0132     ret = cros_usbpd_charger_ec_command(charger, 0,
0133                         EC_CMD_CHARGE_PORT_COUNT,
0134                         NULL, 0, &resp, sizeof(resp));
0135     if (ret < 0)
0136         return ret;
0137 
0138     return resp.port_count;
0139 }
0140 
0141 static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger)
0142 {
0143     struct ec_response_usb_pd_ports resp;
0144     int ret;
0145 
0146     ret = cros_usbpd_charger_ec_command(charger, 0, EC_CMD_USB_PD_PORTS,
0147                         NULL, 0, &resp, sizeof(resp));
0148     if (ret < 0)
0149         return ret;
0150 
0151     return resp.num_ports;
0152 }
0153 
0154 static int cros_usbpd_charger_get_discovery_info(struct port_data *port)
0155 {
0156     struct charger_data *charger = port->charger;
0157     struct ec_params_usb_pd_discovery_entry resp;
0158     struct ec_params_usb_pd_info_request req;
0159     int ret;
0160 
0161     req.port = port->port_number;
0162 
0163     ret = cros_usbpd_charger_ec_command(charger, 0,
0164                         EC_CMD_USB_PD_DISCOVERY,
0165                         &req, sizeof(req),
0166                         &resp, sizeof(resp));
0167     if (ret < 0) {
0168         dev_err(charger->dev,
0169             "Unable to query discovery info (err:0x%x)\n", ret);
0170         return ret;
0171     }
0172 
0173     dev_dbg(charger->dev, "Port %d: VID = 0x%x, PID=0x%x, PTYPE=0x%x\n",
0174         port->port_number, resp.vid, resp.pid, resp.ptype);
0175 
0176     snprintf(port->manufacturer, sizeof(port->manufacturer), "%x",
0177          resp.vid);
0178     snprintf(port->model_name, sizeof(port->model_name), "%x", resp.pid);
0179 
0180     return 0;
0181 }
0182 
0183 static int cros_usbpd_charger_get_power_info(struct port_data *port)
0184 {
0185     struct charger_data *charger = port->charger;
0186     struct ec_response_usb_pd_power_info resp;
0187     struct ec_params_usb_pd_power_info req;
0188     int last_psy_status, last_psy_usb_type;
0189     struct device *dev = charger->dev;
0190     int ret;
0191 
0192     req.port = port->port_number;
0193     ret = cros_usbpd_charger_ec_command(charger, 0,
0194                         EC_CMD_USB_PD_POWER_INFO,
0195                         &req, sizeof(req),
0196                         &resp, sizeof(resp));
0197     if (ret < 0) {
0198         dev_err(dev, "Unable to query PD power info (err:0x%x)\n", ret);
0199         return ret;
0200     }
0201 
0202     last_psy_status = port->psy_status;
0203     last_psy_usb_type = port->psy_usb_type;
0204 
0205     switch (resp.role) {
0206     case USB_PD_PORT_POWER_DISCONNECTED:
0207         port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
0208         port->psy_online = 0;
0209         break;
0210     case USB_PD_PORT_POWER_SOURCE:
0211         port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
0212         port->psy_online = 0;
0213         break;
0214     case USB_PD_PORT_POWER_SINK:
0215         port->psy_status = POWER_SUPPLY_STATUS_CHARGING;
0216         port->psy_online = 1;
0217         break;
0218     case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
0219         port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
0220         port->psy_online = 1;
0221         break;
0222     default:
0223         dev_err(dev, "Unknown role %d\n", resp.role);
0224         break;
0225     }
0226 
0227     port->psy_voltage_max_design = resp.meas.voltage_max;
0228     port->psy_voltage_now = resp.meas.voltage_now;
0229     port->psy_current_max = resp.meas.current_max;
0230     port->psy_power_max = resp.max_power;
0231 
0232     switch (resp.type) {
0233     case USB_CHG_TYPE_BC12_SDP:
0234     case USB_CHG_TYPE_VBUS:
0235         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
0236         break;
0237     case USB_CHG_TYPE_NONE:
0238         /*
0239          * For dual-role devices when we are a source, the firmware
0240          * reports the type as NONE. Report such chargers as type
0241          * USB_PD_DRP.
0242          */
0243         if (resp.role == USB_PD_PORT_POWER_SOURCE && resp.dualrole)
0244             port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
0245         else
0246             port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
0247         break;
0248     case USB_CHG_TYPE_OTHER:
0249     case USB_CHG_TYPE_PROPRIETARY:
0250         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID;
0251         break;
0252     case USB_CHG_TYPE_C:
0253         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_C;
0254         break;
0255     case USB_CHG_TYPE_BC12_DCP:
0256         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP;
0257         break;
0258     case USB_CHG_TYPE_BC12_CDP:
0259         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP;
0260         break;
0261     case USB_CHG_TYPE_PD:
0262         if (resp.dualrole)
0263             port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
0264         else
0265             port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD;
0266         break;
0267     case USB_CHG_TYPE_UNKNOWN:
0268         /*
0269          * While the EC is trying to determine the type of charger that
0270          * has been plugged in, it will report the charger type as
0271          * unknown. Additionally since the power capabilities are
0272          * unknown, report the max current and voltage as zero.
0273          */
0274         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
0275         port->psy_voltage_max_design = 0;
0276         port->psy_current_max = 0;
0277         break;
0278     default:
0279         dev_err(dev, "Port %d: default case!\n", port->port_number);
0280         port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
0281     }
0282 
0283     if (cros_usbpd_charger_port_is_dedicated(port))
0284         port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
0285     else
0286         port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
0287 
0288     dev_dbg(dev,
0289         "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n",
0290         port->port_number, resp.type, resp.meas.voltage_max,
0291         resp.meas.voltage_now, resp.meas.current_max,
0292         resp.meas.current_lim, resp.max_power);
0293 
0294     /*
0295      * If power supply type or status changed, explicitly call
0296      * power_supply_changed. This results in udev event getting generated
0297      * and allows user mode apps to react quicker instead of waiting for
0298      * their next poll of power supply status.
0299      */
0300     if (last_psy_usb_type != port->psy_usb_type ||
0301         last_psy_status != port->psy_status)
0302         power_supply_changed(port->psy);
0303 
0304     return 0;
0305 }
0306 
0307 static int cros_usbpd_charger_get_port_status(struct port_data *port,
0308                           bool ratelimit)
0309 {
0310     int ret;
0311 
0312     if (ratelimit &&
0313         time_is_after_jiffies(port->last_update +
0314                   CHARGER_CACHE_UPDATE_DELAY))
0315         return 0;
0316 
0317     ret = cros_usbpd_charger_get_power_info(port);
0318     if (ret < 0)
0319         return ret;
0320 
0321     if (!cros_usbpd_charger_port_is_dedicated(port))
0322         ret = cros_usbpd_charger_get_discovery_info(port);
0323     port->last_update = jiffies;
0324 
0325     return ret;
0326 }
0327 
0328 static int cros_usbpd_charger_set_ext_power_limit(struct charger_data *charger,
0329                           u16 current_lim,
0330                           u16 voltage_lim)
0331 {
0332     struct ec_params_external_power_limit_v1 req;
0333     int ret;
0334 
0335     req.current_lim = current_lim;
0336     req.voltage_lim = voltage_lim;
0337 
0338     ret = cros_usbpd_charger_ec_command(charger, 0,
0339                         EC_CMD_EXTERNAL_POWER_LIMIT,
0340                         &req, sizeof(req), NULL, 0);
0341     if (ret < 0)
0342         dev_err(charger->dev,
0343             "Unable to set the 'External Power Limit': %d\n", ret);
0344 
0345     return ret;
0346 }
0347 
0348 static void cros_usbpd_charger_power_changed(struct power_supply *psy)
0349 {
0350     struct port_data *port = power_supply_get_drvdata(psy);
0351     struct charger_data *charger = port->charger;
0352     int i;
0353 
0354     for (i = 0; i < charger->num_registered_psy; i++)
0355         cros_usbpd_charger_get_port_status(charger->ports[i], false);
0356 }
0357 
0358 static int cros_usbpd_charger_get_prop(struct power_supply *psy,
0359                        enum power_supply_property psp,
0360                        union power_supply_propval *val)
0361 {
0362     struct port_data *port = power_supply_get_drvdata(psy);
0363     struct charger_data *charger = port->charger;
0364     struct cros_ec_device *ec_device = charger->ec_device;
0365     struct device *dev = charger->dev;
0366     int ret;
0367 
0368     /* Only refresh ec_port_status for dynamic properties */
0369     switch (psp) {
0370     case POWER_SUPPLY_PROP_ONLINE:
0371         /*
0372          * If mkbp_event_supported, then we can be assured that
0373          * the driver's state for the online property is consistent
0374          * with the hardware. However, if we aren't event driven,
0375          * the optimization before to skip an ec_port_status get
0376          * and only returned cached values of the online property will
0377          * cause a delay in detecting a cable attach until one of the
0378          * other properties are read.
0379          *
0380          * Allow an ec_port_status refresh for online property check
0381          * if we're not already online to check for plug events if
0382          * not mkbp_event_supported.
0383          */
0384         if (ec_device->mkbp_event_supported || port->psy_online)
0385             break;
0386         fallthrough;
0387     case POWER_SUPPLY_PROP_CURRENT_MAX:
0388     case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
0389     case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0390         ret = cros_usbpd_charger_get_port_status(port, true);
0391         if (ret < 0) {
0392             dev_err(dev, "Failed to get port status (err:0x%x)\n",
0393                 ret);
0394             return -EINVAL;
0395         }
0396         break;
0397     default:
0398         break;
0399     }
0400 
0401     switch (psp) {
0402     case POWER_SUPPLY_PROP_ONLINE:
0403         val->intval = port->psy_online;
0404         break;
0405     case POWER_SUPPLY_PROP_STATUS:
0406         val->intval = port->psy_status;
0407         break;
0408     case POWER_SUPPLY_PROP_CURRENT_MAX:
0409         val->intval = port->psy_current_max * 1000;
0410         break;
0411     case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
0412         val->intval = port->psy_voltage_max_design * 1000;
0413         break;
0414     case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0415         val->intval = port->psy_voltage_now * 1000;
0416         break;
0417     case POWER_SUPPLY_PROP_USB_TYPE:
0418         val->intval = port->psy_usb_type;
0419         break;
0420     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0421         if (input_current_limit == EC_POWER_LIMIT_NONE)
0422             val->intval = -1;
0423         else
0424             val->intval = input_current_limit * 1000;
0425         break;
0426     case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
0427         if (input_voltage_limit == EC_POWER_LIMIT_NONE)
0428             val->intval = -1;
0429         else
0430             val->intval = input_voltage_limit * 1000;
0431         break;
0432     case POWER_SUPPLY_PROP_MODEL_NAME:
0433         val->strval = port->model_name;
0434         break;
0435     case POWER_SUPPLY_PROP_MANUFACTURER:
0436         val->strval = port->manufacturer;
0437         break;
0438     default:
0439         return -EINVAL;
0440     }
0441 
0442     return 0;
0443 }
0444 
0445 static int cros_usbpd_charger_set_prop(struct power_supply *psy,
0446                        enum power_supply_property psp,
0447                        const union power_supply_propval *val)
0448 {
0449     struct port_data *port = power_supply_get_drvdata(psy);
0450     struct charger_data *charger = port->charger;
0451     struct device *dev = charger->dev;
0452     u16 intval;
0453     int ret;
0454 
0455     /* U16_MAX in mV/mA is the maximum supported value */
0456     if (val->intval >= U16_MAX * 1000)
0457         return -EINVAL;
0458     /* A negative number is used to clear the limit */
0459     if (val->intval < 0)
0460         intval = EC_POWER_LIMIT_NONE;
0461     else    /* Convert from uA/uV to mA/mV */
0462         intval = val->intval / 1000;
0463 
0464     switch (psp) {
0465     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0466         ret = cros_usbpd_charger_set_ext_power_limit(charger, intval,
0467                             input_voltage_limit);
0468         if (ret < 0)
0469             break;
0470 
0471         input_current_limit = intval;
0472         if (input_current_limit == EC_POWER_LIMIT_NONE)
0473             dev_info(dev,
0474               "External Current Limit cleared for all ports\n");
0475         else
0476             dev_info(dev,
0477               "External Current Limit set to %dmA for all ports\n",
0478               input_current_limit);
0479         break;
0480     case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
0481         ret = cros_usbpd_charger_set_ext_power_limit(charger,
0482                             input_current_limit,
0483                             intval);
0484         if (ret < 0)
0485             break;
0486 
0487         input_voltage_limit = intval;
0488         if (input_voltage_limit == EC_POWER_LIMIT_NONE)
0489             dev_info(dev,
0490               "External Voltage Limit cleared for all ports\n");
0491         else
0492             dev_info(dev,
0493               "External Voltage Limit set to %dmV for all ports\n",
0494               input_voltage_limit);
0495         break;
0496     default:
0497         ret = -EINVAL;
0498     }
0499 
0500     return ret;
0501 }
0502 
0503 static int cros_usbpd_charger_property_is_writeable(struct power_supply *psy,
0504                         enum power_supply_property psp)
0505 {
0506     int ret;
0507 
0508     switch (psp) {
0509     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0510     case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
0511         ret = 1;
0512         break;
0513     default:
0514         ret = 0;
0515     }
0516 
0517     return ret;
0518 }
0519 
0520 static int cros_usbpd_charger_ec_event(struct notifier_block *nb,
0521                        unsigned long host_event,
0522                        void *_notify)
0523 {
0524     struct charger_data *charger = container_of(nb, struct charger_data,
0525                             notifier);
0526 
0527     cros_usbpd_charger_power_changed(charger->ports[0]->psy);
0528     return NOTIFY_OK;
0529 }
0530 
0531 static void cros_usbpd_charger_unregister_notifier(void *data)
0532 {
0533     struct charger_data *charger = data;
0534 
0535     cros_usbpd_unregister_notify(&charger->notifier);
0536 }
0537 
0538 static int cros_usbpd_charger_probe(struct platform_device *pd)
0539 {
0540     struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
0541     struct cros_ec_device *ec_device = ec_dev->ec_dev;
0542     struct power_supply_desc *psy_desc;
0543     struct device *dev = &pd->dev;
0544     struct charger_data *charger;
0545     struct power_supply *psy;
0546     struct port_data *port;
0547     int ret = -EINVAL;
0548     int i;
0549 
0550     charger = devm_kzalloc(dev, sizeof(struct charger_data),
0551                    GFP_KERNEL);
0552     if (!charger)
0553         return -ENOMEM;
0554 
0555     charger->dev = dev;
0556     charger->ec_dev = ec_dev;
0557     charger->ec_device = ec_device;
0558 
0559     platform_set_drvdata(pd, charger);
0560 
0561     /*
0562      * We need to know the number of USB PD ports in order to know whether
0563      * there is a dedicated port. The dedicated port will always be
0564      * after the USB PD ports, and there should be only one.
0565      */
0566     charger->num_usbpd_ports =
0567         cros_usbpd_charger_get_usbpd_num_ports(charger);
0568     if (charger->num_usbpd_ports <= 0) {
0569         /*
0570          * This can happen on a system that doesn't support USB PD.
0571          * Log a message, but no need to warn.
0572          */
0573         dev_info(dev, "No USB PD charging ports found\n");
0574     }
0575 
0576     charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger);
0577     if (charger->num_charger_ports < 0) {
0578         /*
0579          * This can happen on a system that doesn't support USB PD.
0580          * Log a message, but no need to warn.
0581          * Older ECs do not support the above command, in that case
0582          * let's set up the number of charger ports equal to the number
0583          * of USB PD ports
0584          */
0585         dev_info(dev, "Could not get charger port count\n");
0586         charger->num_charger_ports = charger->num_usbpd_ports;
0587     }
0588 
0589     if (charger->num_charger_ports <= 0) {
0590         /*
0591          * This can happen on a system that doesn't support USB PD and
0592          * doesn't have a dedicated port.
0593          * Log a message, but no need to warn.
0594          */
0595         dev_info(dev, "No charging ports found\n");
0596         ret = -ENODEV;
0597         goto fail_nowarn;
0598     }
0599 
0600     /*
0601      * Sanity checks on the number of ports:
0602      *  there should be at most 1 dedicated port
0603      */
0604     if (charger->num_charger_ports < charger->num_usbpd_ports ||
0605         charger->num_charger_ports > (charger->num_usbpd_ports + 1)) {
0606         dev_err(dev, "Unexpected number of charge port count\n");
0607         ret = -EPROTO;
0608         goto fail_nowarn;
0609     }
0610 
0611     for (i = 0; i < charger->num_charger_ports; i++) {
0612         struct power_supply_config psy_cfg = {};
0613 
0614         port = devm_kzalloc(dev, sizeof(struct port_data), GFP_KERNEL);
0615         if (!port) {
0616             ret = -ENOMEM;
0617             goto fail;
0618         }
0619 
0620         port->charger = charger;
0621         port->port_number = i;
0622 
0623         psy_desc = &port->psy_desc;
0624         psy_desc->get_property = cros_usbpd_charger_get_prop;
0625         psy_desc->set_property = cros_usbpd_charger_set_prop;
0626         psy_desc->property_is_writeable =
0627                 cros_usbpd_charger_property_is_writeable;
0628         psy_desc->external_power_changed =
0629                     cros_usbpd_charger_power_changed;
0630         psy_cfg.drv_data = port;
0631 
0632         if (cros_usbpd_charger_port_is_dedicated(port)) {
0633             sprintf(port->name, CHARGER_DEDICATED_DIR_NAME);
0634             psy_desc->type = POWER_SUPPLY_TYPE_MAINS;
0635             psy_desc->properties =
0636                 cros_usbpd_dedicated_charger_props;
0637             psy_desc->num_properties =
0638                 ARRAY_SIZE(cros_usbpd_dedicated_charger_props);
0639         } else {
0640             sprintf(port->name, CHARGER_USBPD_DIR_NAME, i);
0641             psy_desc->type = POWER_SUPPLY_TYPE_USB;
0642             psy_desc->properties = cros_usbpd_charger_props;
0643             psy_desc->num_properties =
0644                 ARRAY_SIZE(cros_usbpd_charger_props);
0645             psy_desc->usb_types = cros_usbpd_charger_usb_types;
0646             psy_desc->num_usb_types =
0647                 ARRAY_SIZE(cros_usbpd_charger_usb_types);
0648         }
0649 
0650         psy_desc->name = port->name;
0651 
0652         psy = devm_power_supply_register_no_ws(dev, psy_desc,
0653                                &psy_cfg);
0654         if (IS_ERR(psy)) {
0655             dev_err(dev, "Failed to register power supply\n");
0656             continue;
0657         }
0658         port->psy = psy;
0659 
0660         charger->ports[charger->num_registered_psy++] = port;
0661     }
0662 
0663     if (!charger->num_registered_psy) {
0664         ret = -ENODEV;
0665         dev_err(dev, "No power supplies registered\n");
0666         goto fail;
0667     }
0668 
0669     /* Get PD events from the EC */
0670     charger->notifier.notifier_call = cros_usbpd_charger_ec_event;
0671     ret = cros_usbpd_register_notify(&charger->notifier);
0672     if (ret < 0) {
0673         dev_warn(dev, "failed to register notifier\n");
0674     } else {
0675         ret = devm_add_action_or_reset(dev,
0676                 cros_usbpd_charger_unregister_notifier,
0677                 charger);
0678         if (ret < 0)
0679             goto fail;
0680     }
0681 
0682     return 0;
0683 
0684 fail:
0685     WARN(1, "%s: Failing probe (err:0x%x)\n", dev_name(dev), ret);
0686 
0687 fail_nowarn:
0688     dev_info(dev, "Failing probe (err:0x%x)\n", ret);
0689     return ret;
0690 }
0691 
0692 #ifdef CONFIG_PM_SLEEP
0693 static int cros_usbpd_charger_resume(struct device *dev)
0694 {
0695     struct charger_data *charger = dev_get_drvdata(dev);
0696     int i;
0697 
0698     if (!charger)
0699         return 0;
0700 
0701     for (i = 0; i < charger->num_registered_psy; i++) {
0702         power_supply_changed(charger->ports[i]->psy);
0703         charger->ports[i]->last_update =
0704                 jiffies - CHARGER_CACHE_UPDATE_DELAY;
0705     }
0706 
0707     return 0;
0708 }
0709 #endif
0710 
0711 static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL,
0712              cros_usbpd_charger_resume);
0713 
0714 static struct platform_driver cros_usbpd_charger_driver = {
0715     .driver = {
0716         .name = DRV_NAME,
0717         .pm = &cros_usbpd_charger_pm_ops,
0718     },
0719     .probe = cros_usbpd_charger_probe
0720 };
0721 
0722 module_platform_driver(cros_usbpd_charger_driver);
0723 
0724 MODULE_LICENSE("GPL");
0725 MODULE_DESCRIPTION("ChromeOS EC USBPD charger");
0726 MODULE_ALIAS("platform:" DRV_NAME);