diff options
author | Sebastian Reichel <sebastian.reichel@collabora.com> | 2018-09-16 07:10:37 -0400 |
---|---|---|
committer | Sebastian Reichel <sebastian.reichel@collabora.com> | 2018-09-16 07:10:37 -0400 |
commit | 782853cf9b1bd349ed726390a6fbe40f745931b7 (patch) | |
tree | 19a0d88136ab6a06e0e85a7f1d1020b0a9726c48 | |
parent | 2e04dd441a2ecc049505b2cbfabc355a48115b59 (diff) | |
parent | 3af15cfacd1eef7f223802d49a88cae23c509183 (diff) |
Merge tag 'psy-mfd-cros-immutable-for-v4.20-signed' into psy-next
Immutable branch for mfd and power-supply for v4.20
Immutable branch between mfd and power-supply for driver
changes in CROS USBPD charger driver.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
-rw-r--r-- | drivers/power/supply/cros_usbpd-charger.c | 115 | ||||
-rw-r--r-- | include/linux/mfd/cros_ec_commands.h | 10 |
2 files changed, 111 insertions, 14 deletions
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c index f2b8de502b82..7e9c3984ef6a 100644 --- a/drivers/power/supply/cros_usbpd-charger.c +++ b/drivers/power/supply/cros_usbpd-charger.c | |||
@@ -12,8 +12,12 @@ | |||
12 | #include <linux/power_supply.h> | 12 | #include <linux/power_supply.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | 14 | ||
15 | #define CHARGER_DIR_NAME "CROS_USBPD_CHARGER%d" | 15 | #define CHARGER_USBPD_DIR_NAME "CROS_USBPD_CHARGER%d" |
16 | #define CHARGER_DIR_NAME_LENGTH sizeof(CHARGER_DIR_NAME) | 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)) | ||
17 | #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500) | 21 | #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500) |
18 | #define CHARGER_MANUFACTURER_MODEL_LENGTH 32 | 22 | #define CHARGER_MANUFACTURER_MODEL_LENGTH 32 |
19 | 23 | ||
@@ -42,6 +46,7 @@ struct charger_data { | |||
42 | struct cros_ec_dev *ec_dev; | 46 | struct cros_ec_dev *ec_dev; |
43 | struct cros_ec_device *ec_device; | 47 | struct cros_ec_device *ec_device; |
44 | int num_charger_ports; | 48 | int num_charger_ports; |
49 | int num_usbpd_ports; | ||
45 | int num_registered_psy; | 50 | int num_registered_psy; |
46 | struct port_data *ports[EC_USB_PD_MAX_PORTS]; | 51 | struct port_data *ports[EC_USB_PD_MAX_PORTS]; |
47 | struct notifier_block notifier; | 52 | struct notifier_block notifier; |
@@ -58,6 +63,12 @@ static enum power_supply_property cros_usbpd_charger_props[] = { | |||
58 | POWER_SUPPLY_PROP_USB_TYPE | 63 | POWER_SUPPLY_PROP_USB_TYPE |
59 | }; | 64 | }; |
60 | 65 | ||
66 | static enum power_supply_property cros_usbpd_dedicated_charger_props[] = { | ||
67 | POWER_SUPPLY_PROP_ONLINE, | ||
68 | POWER_SUPPLY_PROP_STATUS, | ||
69 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
70 | }; | ||
71 | |||
61 | static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { | 72 | static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { |
62 | POWER_SUPPLY_USB_TYPE_UNKNOWN, | 73 | POWER_SUPPLY_USB_TYPE_UNKNOWN, |
63 | POWER_SUPPLY_USB_TYPE_SDP, | 74 | POWER_SUPPLY_USB_TYPE_SDP, |
@@ -69,6 +80,11 @@ static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { | |||
69 | POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID | 80 | POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID |
70 | }; | 81 | }; |
71 | 82 | ||
83 | static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port) | ||
84 | { | ||
85 | return port->port_number >= port->charger->num_usbpd_ports; | ||
86 | } | ||
87 | |||
72 | static int cros_usbpd_charger_ec_command(struct charger_data *charger, | 88 | static int cros_usbpd_charger_ec_command(struct charger_data *charger, |
73 | unsigned int version, | 89 | unsigned int version, |
74 | unsigned int command, | 90 | unsigned int command, |
@@ -103,6 +119,23 @@ static int cros_usbpd_charger_ec_command(struct charger_data *charger, | |||
103 | 119 | ||
104 | static int cros_usbpd_charger_get_num_ports(struct charger_data *charger) | 120 | static int cros_usbpd_charger_get_num_ports(struct charger_data *charger) |
105 | { | 121 | { |
122 | struct ec_response_charge_port_count resp; | ||
123 | int ret; | ||
124 | |||
125 | ret = cros_usbpd_charger_ec_command(charger, 0, | ||
126 | EC_CMD_CHARGE_PORT_COUNT, | ||
127 | NULL, 0, &resp, sizeof(resp)); | ||
128 | if (ret < 0) { | ||
129 | dev_err(charger->dev, | ||
130 | "Unable to get the number of ports (err:0x%x)\n", ret); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | return resp.port_count; | ||
135 | } | ||
136 | |||
137 | static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger) | ||
138 | { | ||
106 | struct ec_response_usb_pd_ports resp; | 139 | struct ec_response_usb_pd_ports resp; |
107 | int ret; | 140 | int ret; |
108 | 141 | ||
@@ -246,7 +279,10 @@ static int cros_usbpd_charger_get_power_info(struct port_data *port) | |||
246 | port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; | 279 | port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; |
247 | } | 280 | } |
248 | 281 | ||
249 | port->psy_desc.type = POWER_SUPPLY_TYPE_USB; | 282 | if (cros_usbpd_charger_port_is_dedicated(port)) |
283 | port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS; | ||
284 | else | ||
285 | port->psy_desc.type = POWER_SUPPLY_TYPE_USB; | ||
250 | 286 | ||
251 | dev_dbg(dev, | 287 | dev_dbg(dev, |
252 | "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n", | 288 | "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n", |
@@ -281,7 +317,8 @@ static int cros_usbpd_charger_get_port_status(struct port_data *port, | |||
281 | if (ret < 0) | 317 | if (ret < 0) |
282 | return ret; | 318 | return ret; |
283 | 319 | ||
284 | ret = cros_usbpd_charger_get_discovery_info(port); | 320 | if (!cros_usbpd_charger_port_is_dedicated(port)) |
321 | ret = cros_usbpd_charger_get_discovery_info(port); | ||
285 | port->last_update = jiffies; | 322 | port->last_update = jiffies; |
286 | 323 | ||
287 | return ret; | 324 | return ret; |
@@ -424,17 +461,56 @@ static int cros_usbpd_charger_probe(struct platform_device *pd) | |||
424 | 461 | ||
425 | platform_set_drvdata(pd, charger); | 462 | platform_set_drvdata(pd, charger); |
426 | 463 | ||
464 | /* | ||
465 | * We need to know the number of USB PD ports in order to know whether | ||
466 | * there is a dedicated port. The dedicated port will always be | ||
467 | * after the USB PD ports, and there should be only one. | ||
468 | */ | ||
469 | charger->num_usbpd_ports = | ||
470 | cros_usbpd_charger_get_usbpd_num_ports(charger); | ||
471 | if (charger->num_usbpd_ports <= 0) { | ||
472 | /* | ||
473 | * This can happen on a system that doesn't support USB PD. | ||
474 | * Log a message, but no need to warn. | ||
475 | */ | ||
476 | dev_info(dev, "No USB PD charging ports found\n"); | ||
477 | } | ||
478 | |||
427 | charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger); | 479 | charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger); |
428 | if (charger->num_charger_ports <= 0) { | 480 | if (charger->num_charger_ports < 0) { |
429 | /* | 481 | /* |
430 | * This can happen on a system that doesn't support USB PD. | 482 | * This can happen on a system that doesn't support USB PD. |
431 | * Log a message, but no need to warn. | 483 | * Log a message, but no need to warn. |
484 | * Older ECs do not support the above command, in that case | ||
485 | * let's set up the number of charger ports equal to the number | ||
486 | * of USB PD ports | ||
487 | */ | ||
488 | dev_info(dev, "Could not get charger port count\n"); | ||
489 | charger->num_charger_ports = charger->num_usbpd_ports; | ||
490 | } | ||
491 | |||
492 | if (charger->num_charger_ports <= 0) { | ||
493 | /* | ||
494 | * This can happen on a system that doesn't support USB PD and | ||
495 | * doesn't have a dedicated port. | ||
496 | * Log a message, but no need to warn. | ||
432 | */ | 497 | */ |
433 | dev_info(dev, "No charging ports found\n"); | 498 | dev_info(dev, "No charging ports found\n"); |
434 | ret = -ENODEV; | 499 | ret = -ENODEV; |
435 | goto fail_nowarn; | 500 | goto fail_nowarn; |
436 | } | 501 | } |
437 | 502 | ||
503 | /* | ||
504 | * Sanity checks on the number of ports: | ||
505 | * there should be at most 1 dedicated port | ||
506 | */ | ||
507 | if (charger->num_charger_ports < charger->num_usbpd_ports || | ||
508 | charger->num_charger_ports > (charger->num_usbpd_ports + 1)) { | ||
509 | dev_err(dev, "Unexpected number of charge port count\n"); | ||
510 | ret = -EPROTO; | ||
511 | goto fail_nowarn; | ||
512 | } | ||
513 | |||
438 | for (i = 0; i < charger->num_charger_ports; i++) { | 514 | for (i = 0; i < charger->num_charger_ports; i++) { |
439 | struct power_supply_config psy_cfg = {}; | 515 | struct power_supply_config psy_cfg = {}; |
440 | 516 | ||
@@ -446,22 +522,33 @@ static int cros_usbpd_charger_probe(struct platform_device *pd) | |||
446 | 522 | ||
447 | port->charger = charger; | 523 | port->charger = charger; |
448 | port->port_number = i; | 524 | port->port_number = i; |
449 | sprintf(port->name, CHARGER_DIR_NAME, i); | ||
450 | 525 | ||
451 | psy_desc = &port->psy_desc; | 526 | psy_desc = &port->psy_desc; |
452 | psy_desc->name = port->name; | ||
453 | psy_desc->type = POWER_SUPPLY_TYPE_USB; | ||
454 | psy_desc->get_property = cros_usbpd_charger_get_prop; | 527 | psy_desc->get_property = cros_usbpd_charger_get_prop; |
455 | psy_desc->external_power_changed = | 528 | psy_desc->external_power_changed = |
456 | cros_usbpd_charger_power_changed; | 529 | cros_usbpd_charger_power_changed; |
457 | psy_desc->properties = cros_usbpd_charger_props; | ||
458 | psy_desc->num_properties = | ||
459 | ARRAY_SIZE(cros_usbpd_charger_props); | ||
460 | psy_desc->usb_types = cros_usbpd_charger_usb_types; | ||
461 | psy_desc->num_usb_types = | ||
462 | ARRAY_SIZE(cros_usbpd_charger_usb_types); | ||
463 | psy_cfg.drv_data = port; | 530 | psy_cfg.drv_data = port; |
464 | 531 | ||
532 | if (cros_usbpd_charger_port_is_dedicated(port)) { | ||
533 | sprintf(port->name, CHARGER_DEDICATED_DIR_NAME); | ||
534 | psy_desc->type = POWER_SUPPLY_TYPE_MAINS; | ||
535 | psy_desc->properties = | ||
536 | cros_usbpd_dedicated_charger_props; | ||
537 | psy_desc->num_properties = | ||
538 | ARRAY_SIZE(cros_usbpd_dedicated_charger_props); | ||
539 | } else { | ||
540 | sprintf(port->name, CHARGER_USBPD_DIR_NAME, i); | ||
541 | psy_desc->type = POWER_SUPPLY_TYPE_USB; | ||
542 | psy_desc->properties = cros_usbpd_charger_props; | ||
543 | psy_desc->num_properties = | ||
544 | ARRAY_SIZE(cros_usbpd_charger_props); | ||
545 | psy_desc->usb_types = cros_usbpd_charger_usb_types; | ||
546 | psy_desc->num_usb_types = | ||
547 | ARRAY_SIZE(cros_usbpd_charger_usb_types); | ||
548 | } | ||
549 | |||
550 | psy_desc->name = port->name; | ||
551 | |||
465 | psy = devm_power_supply_register_no_ws(dev, psy_desc, | 552 | psy = devm_power_supply_register_no_ws(dev, psy_desc, |
466 | &psy_cfg); | 553 | &psy_cfg); |
467 | if (IS_ERR(psy)) { | 554 | if (IS_ERR(psy)) { |
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 6e1ab9bead28..20ee71f10865 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h | |||
@@ -3102,6 +3102,16 @@ struct ec_params_usb_pd_info_request { | |||
3102 | uint8_t port; | 3102 | uint8_t port; |
3103 | } __packed; | 3103 | } __packed; |
3104 | 3104 | ||
3105 | /* | ||
3106 | * This command will return the number of USB PD charge port + the number | ||
3107 | * of dedicated port present. | ||
3108 | * EC_CMD_USB_PD_PORTS does NOT include the dedicated ports | ||
3109 | */ | ||
3110 | #define EC_CMD_CHARGE_PORT_COUNT 0x0105 | ||
3111 | struct ec_response_charge_port_count { | ||
3112 | uint8_t port_count; | ||
3113 | } __packed; | ||
3114 | |||
3105 | /* Read USB-PD Device discovery info */ | 3115 | /* Read USB-PD Device discovery info */ |
3106 | #define EC_CMD_USB_PD_DISCOVERY 0x0113 | 3116 | #define EC_CMD_USB_PD_DISCOVERY 0x0113 |
3107 | struct ec_params_usb_pd_discovery_entry { | 3117 | struct ec_params_usb_pd_discovery_entry { |