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.kroge...@linux.intel.com>

Reviewed-by: Guenter Roeck <li...@roeck-us.net>

> ---
>  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
> 

Reply via email to