Re: [PATCH 3/3] usb: typec: fusb302: Always provide fwnode for the port

From: Guenter Roeck
Date: Wed Aug 14 2019 - 09:37:44 EST


On Wed, Aug 14, 2019 at 04:24:19PM +0300, Heikki Krogerus wrote:
> By registering a software fwnode for the port when the
> firmware does not supply one, we can always provide tcpm the
> connector capabilities by using the common USB connector
> device properties instead of using tcpc_config platform data.
>
> Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>

Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx>

> ---
> drivers/usb/typec/tcpm/fusb302.c | 70 +++++++++++++++++++-------------
> 1 file changed, 41 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> index 074fbb17fa8b..93244d6c4bff 100644
> --- a/drivers/usb/typec/tcpm/fusb302.c
> +++ b/drivers/usb/typec/tcpm/fusb302.c
> @@ -75,7 +75,6 @@ struct fusb302_chip {
> struct i2c_client *i2c_client;
> struct tcpm_port *tcpm_port;
> struct tcpc_dev tcpc_dev;
> - struct tcpc_config tcpc_config;
>
> struct regulator *vbus;
>
> @@ -1110,23 +1109,6 @@ static void fusb302_bc_lvl_handler_work(struct work_struct *work)
> mutex_unlock(&chip->lock);
> }
>
> -#define PDO_FIXED_FLAGS \
> - (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM)
> -
> -static const u32 src_pdo[] = {
> - PDO_FIXED(5000, 400, PDO_FIXED_FLAGS),
> -};
> -
> -static const struct tcpc_config fusb302_tcpc_config = {
> - .src_pdo = src_pdo,
> - .nr_src_pdo = ARRAY_SIZE(src_pdo),
> - .operating_snk_mw = 2500,
> - .type = TYPEC_PORT_DRP,
> - .data = TYPEC_PORT_DRD,
> - .default_role = TYPEC_SINK,
> - .alt_modes = NULL,
> -};
> -
> static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev)
> {
> fusb302_tcpc_dev->init = tcpm_init;
> @@ -1670,6 +1652,38 @@ static int init_gpio(struct fusb302_chip *chip)
> return 0;
> }
>
> +#define PDO_FIXED_FLAGS \
> + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM)
> +
> +static const u32 src_pdo[] = {
> + PDO_FIXED(5000, 400, PDO_FIXED_FLAGS)
> +};
> +
> +static const u32 snk_pdo[] = {
> + PDO_FIXED(5000, 400, PDO_FIXED_FLAGS)
> +};
> +
> +static const struct property_entry port_props[] = {
> + PROPERTY_ENTRY_STRING("data-role", "dual"),
> + PROPERTY_ENTRY_STRING("power-role", "dual"),
> + PROPERTY_ENTRY_STRING("try-power-role", "sink"),
> + PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo),
> + PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo),
> + PROPERTY_ENTRY_U32("op-sink-microwatt", 2500),
> + { }
> +};
> +
> +static struct fwnode_handle *fusb302_fwnode_get(struct device *dev)
> +{
> + struct fwnode_handle *fwnode;
> +
> + fwnode = device_get_named_child_node(dev, "connector");
> + if (!fwnode)
> + fwnode = fwnode_create_software_node(port_props, NULL);
> +
> + return fwnode;
> +}
> +
> static int fusb302_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -1690,19 +1704,8 @@ static int fusb302_probe(struct i2c_client *client,
>
> chip->i2c_client = client;
> chip->dev = &client->dev;
> - chip->tcpc_config = fusb302_tcpc_config;
> - chip->tcpc_dev.config = &chip->tcpc_config;
> mutex_init(&chip->lock);
>
> - chip->tcpc_dev.fwnode =
> - device_get_named_child_node(dev, "connector");
> -
> - /* Composite sink PDO */
> - chip->snk_pdo[0] = PDO_FIXED(5000, 400, PDO_FIXED_FLAGS);
> -
> - chip->tcpc_config.nr_snk_pdo = 1;
> - chip->tcpc_config.snk_pdo = chip->snk_pdo;
> -
> /*
> * Devicetree platforms should get extcon via phandle (not yet
> * supported). On ACPI platforms, we get the name from a device prop.
> @@ -1737,8 +1740,15 @@ static int fusb302_probe(struct i2c_client *client,
> goto destroy_workqueue;
> }
>
> + chip->tcpc_dev.fwnode = fusb302_fwnode_get(dev);
> + if (IS_ERR(chip->tcpc_dev.fwnode)) {
> + ret = PTR_ERR(chip->tcpc_dev.fwnode);
> + goto destroy_workqueue;
> + }
> +
> chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev);
> if (IS_ERR(chip->tcpm_port)) {
> + fwnode_handle_put(chip->tcpc_dev.fwnode);
> ret = PTR_ERR(chip->tcpm_port);
> if (ret != -EPROBE_DEFER)
> dev_err(dev, "cannot register tcpm port, ret=%d", ret);
> @@ -1760,6 +1770,7 @@ static int fusb302_probe(struct i2c_client *client,
>
> tcpm_unregister_port:
> tcpm_unregister_port(chip->tcpm_port);
> + fwnode_handle_put(chip->tcpc_dev.fwnode);
> destroy_workqueue:
> destroy_workqueue(chip->wq);
>
> @@ -1775,6 +1786,7 @@ static int fusb302_remove(struct i2c_client *client)
> cancel_work_sync(&chip->irq_work);
> cancel_delayed_work_sync(&chip->bc_lvl_handler);
> tcpm_unregister_port(chip->tcpm_port);
> + fwnode_handle_put(chip->tcpc_dev.fwnode);
> destroy_workqueue(chip->wq);
> fusb302_debugfs_exit(chip);
>
> --
> 2.20.1
>