[PATCH v2 2/3] power: supply: cros: add support for dedicated port

2018-08-10 Thread Fabien Parent
ChromeOS devices can have one optional dedicated port.
The Dedicated port is unique and similar to the USB PD ports
except that it doesn't support as many properties.

The presence of a dedicated port is determined from whether the
EC's charger port count is equal to 'number of USB PD port' + 1.
The dedicated port ID is always the last valid port ID.

This commit keeps compatibility with Embedded Controllers that do not
support the new EC_CMD_CHARGE_PORT_COUNT command by setting
the number of charger port to be equal to the number of USB PD port
when this command fails.

Signed-off-by: Fabien Parent 
---

V1 -> V2:
  * Rebased

---
 drivers/power/supply/cros_usbpd-charger.c | 115 +++---
 1 file changed, 101 insertions(+), 14 deletions(-)

diff --git a/drivers/power/supply/cros_usbpd-charger.c 
b/drivers/power/supply/cros_usbpd-charger.c
index 688a16bacfbb..fe1502715e46 100644
--- a/drivers/power/supply/cros_usbpd-charger.c
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -12,8 +12,12 @@
 #include 
 #include 
 
-#define CHARGER_DIR_NAME   "CROS_USBPD_CHARGER%d"
-#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+#define CHARGER_USBPD_DIR_NAME "CROS_USBPD_CHARGER%d"
+#define CHARGER_DEDICATED_DIR_NAME "CROS_DEDICATED_CHARGER"
+#define CHARGER_DIR_NAME_LENGTH(sizeof(CHARGER_USBPD_DIR_NAME) 
>= \
+sizeof(CHARGER_DEDICATED_DIR_NAME) ? \
+sizeof(CHARGER_USBPD_DIR_NAME) : \
+sizeof(CHARGER_DEDICATED_DIR_NAME))
 #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
 #define CHARGER_MANUFACTURER_MODEL_LENGTH  32
 
@@ -42,6 +46,7 @@ struct charger_data {
struct cros_ec_dev *ec_dev;
struct cros_ec_device *ec_device;
int num_charger_ports;
+   int num_usbpd_ports;
int num_registered_psy;
struct port_data *ports[EC_USB_PD_MAX_PORTS];
struct notifier_block notifier;
@@ -58,6 +63,12 @@ static enum power_supply_property cros_usbpd_charger_props[] 
= {
POWER_SUPPLY_PROP_USB_TYPE
 };
 
+static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POWER_SUPPLY_PROP_STATUS,
+   POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
 static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
@@ -69,6 +80,11 @@ static enum power_supply_usb_type 
cros_usbpd_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
 };
 
+static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port)
+{
+   return port->port_number >= port->charger->num_usbpd_ports;
+}
+
 static int cros_usbpd_charger_ec_command(struct charger_data *charger,
 unsigned int version,
 unsigned int command,
@@ -102,6 +118,23 @@ static int cros_usbpd_charger_ec_command(struct 
charger_data *charger,
 }
 
 static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
+{
+   struct ec_response_charge_port_count resp;
+   int ret;
+
+   ret = cros_usbpd_charger_ec_command(charger, 0,
+   EC_CMD_CHARGE_PORT_COUNT,
+   NULL, 0, , sizeof(resp));
+   if (ret < 0) {
+   dev_err(charger->dev,
+   "Unable to get the number of ports (err:0x%x)\n", ret);
+   return ret;
+   }
+
+   return resp.port_count;
+}
+
+static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger)
 {
struct ec_response_usb_pd_ports resp;
int ret;
@@ -246,7 +279,10 @@ static int cros_usbpd_charger_get_power_info(struct 
port_data *port)
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
}
 
-   port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+   if (cros_usbpd_charger_port_is_dedicated(port))
+   port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
+   else
+   port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
 
dev_dbg(dev,
"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,
if (ret < 0)
return ret;
 
-   ret = cros_usbpd_charger_get_discovery_info(port);
+   if (!cros_usbpd_charger_port_is_dedicated(port))
+   ret = cros_usbpd_charger_get_discovery_info(port);
port->last_update = jiffies;
 
return ret;
@@ -426,17 +463,56 @@ static int cros_usbpd_charger_probe(struct 
platform_device *pd)
 
platform_set_drvdata(pd, charger);
 
+   /*
+* We need to know the number of USB PD ports in order to know whether
+* there is a dedicated 

[PATCH v2 2/3] power: supply: cros: add support for dedicated port

2018-08-10 Thread Fabien Parent
ChromeOS devices can have one optional dedicated port.
The Dedicated port is unique and similar to the USB PD ports
except that it doesn't support as many properties.

The presence of a dedicated port is determined from whether the
EC's charger port count is equal to 'number of USB PD port' + 1.
The dedicated port ID is always the last valid port ID.

This commit keeps compatibility with Embedded Controllers that do not
support the new EC_CMD_CHARGE_PORT_COUNT command by setting
the number of charger port to be equal to the number of USB PD port
when this command fails.

Signed-off-by: Fabien Parent 
---

V1 -> V2:
  * Rebased

---
 drivers/power/supply/cros_usbpd-charger.c | 115 +++---
 1 file changed, 101 insertions(+), 14 deletions(-)

diff --git a/drivers/power/supply/cros_usbpd-charger.c 
b/drivers/power/supply/cros_usbpd-charger.c
index 688a16bacfbb..fe1502715e46 100644
--- a/drivers/power/supply/cros_usbpd-charger.c
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -12,8 +12,12 @@
 #include 
 #include 
 
-#define CHARGER_DIR_NAME   "CROS_USBPD_CHARGER%d"
-#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+#define CHARGER_USBPD_DIR_NAME "CROS_USBPD_CHARGER%d"
+#define CHARGER_DEDICATED_DIR_NAME "CROS_DEDICATED_CHARGER"
+#define CHARGER_DIR_NAME_LENGTH(sizeof(CHARGER_USBPD_DIR_NAME) 
>= \
+sizeof(CHARGER_DEDICATED_DIR_NAME) ? \
+sizeof(CHARGER_USBPD_DIR_NAME) : \
+sizeof(CHARGER_DEDICATED_DIR_NAME))
 #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
 #define CHARGER_MANUFACTURER_MODEL_LENGTH  32
 
@@ -42,6 +46,7 @@ struct charger_data {
struct cros_ec_dev *ec_dev;
struct cros_ec_device *ec_device;
int num_charger_ports;
+   int num_usbpd_ports;
int num_registered_psy;
struct port_data *ports[EC_USB_PD_MAX_PORTS];
struct notifier_block notifier;
@@ -58,6 +63,12 @@ static enum power_supply_property cros_usbpd_charger_props[] 
= {
POWER_SUPPLY_PROP_USB_TYPE
 };
 
+static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POWER_SUPPLY_PROP_STATUS,
+   POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
 static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
@@ -69,6 +80,11 @@ static enum power_supply_usb_type 
cros_usbpd_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
 };
 
+static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port)
+{
+   return port->port_number >= port->charger->num_usbpd_ports;
+}
+
 static int cros_usbpd_charger_ec_command(struct charger_data *charger,
 unsigned int version,
 unsigned int command,
@@ -102,6 +118,23 @@ static int cros_usbpd_charger_ec_command(struct 
charger_data *charger,
 }
 
 static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
+{
+   struct ec_response_charge_port_count resp;
+   int ret;
+
+   ret = cros_usbpd_charger_ec_command(charger, 0,
+   EC_CMD_CHARGE_PORT_COUNT,
+   NULL, 0, , sizeof(resp));
+   if (ret < 0) {
+   dev_err(charger->dev,
+   "Unable to get the number of ports (err:0x%x)\n", ret);
+   return ret;
+   }
+
+   return resp.port_count;
+}
+
+static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger)
 {
struct ec_response_usb_pd_ports resp;
int ret;
@@ -246,7 +279,10 @@ static int cros_usbpd_charger_get_power_info(struct 
port_data *port)
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
}
 
-   port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+   if (cros_usbpd_charger_port_is_dedicated(port))
+   port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
+   else
+   port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
 
dev_dbg(dev,
"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,
if (ret < 0)
return ret;
 
-   ret = cros_usbpd_charger_get_discovery_info(port);
+   if (!cros_usbpd_charger_port_is_dedicated(port))
+   ret = cros_usbpd_charger_get_discovery_info(port);
port->last_update = jiffies;
 
return ret;
@@ -426,17 +463,56 @@ static int cros_usbpd_charger_probe(struct 
platform_device *pd)
 
platform_set_drvdata(pd, charger);
 
+   /*
+* We need to know the number of USB PD ports in order to know whether
+* there is a dedicated