Message ID | 20220208031944.3444-4-bjorn.andersson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | typec: mux: Introduce support for multiple TypeC muxes | expand |
On Mon, Feb 07, 2022 at 07:19:41PM -0800, Bjorn Andersson wrote: > Rather than directly exposing the implementation's representation of the > typec muxes to the controller/clients, introduce an indirection object. > > This enables the introduction of turning this relationship into a > one-to-many in the following patch. > > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > --- > > Changes sice v1: > - None > > drivers/usb/typec/bus.c | 2 +- > drivers/usb/typec/mux.c | 189 ++++++++++++++++---------- > drivers/usb/typec/mux.h | 12 +- > drivers/usb/typec/mux/intel_pmc_mux.c | 8 +- > drivers/usb/typec/mux/pi3usb30532.c | 8 +- > include/linux/usb/typec_mux.h | 22 +-- > 6 files changed, 146 insertions(+), 95 deletions(-) > > diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c > index 78e0e78954f2..26ea2fdec17d 100644 > --- a/drivers/usb/typec/bus.c > +++ b/drivers/usb/typec/bus.c > @@ -24,7 +24,7 @@ typec_altmode_set_mux(struct altmode *alt, unsigned long conf, void *data) > state.mode = conf; > state.data = data; > > - return alt->mux->set(alt->mux, &state); > + return typec_mux_set(alt->mux, &state); > } > > static int typec_altmode_set_state(struct typec_altmode *adev, > diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c > index c8340de0ed49..d0b42c297aca 100644 > --- a/drivers/usb/typec/mux.c > +++ b/drivers/usb/typec/mux.c > @@ -17,9 +17,13 @@ > #include "class.h" > #include "mux.h" > > +struct typec_switch { > + struct typec_switch_dev *sw_dev; > +}; > + > static int switch_fwnode_match(struct device *dev, const void *fwnode) > { > - if (!is_typec_switch(dev)) > + if (!is_typec_switch_dev(dev)) > return 0; > > return dev_fwnode(dev) == fwnode; > @@ -49,7 +53,7 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, > dev = class_find_device(&typec_mux_class, NULL, fwnode, > switch_fwnode_match); > > - return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); > + return dev ? to_typec_switch_dev(dev) : ERR_PTR(-EPROBE_DEFER); > } > > /** > @@ -63,12 +67,23 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, > */ > struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode) > { > + struct typec_switch_dev *sw_dev; > struct typec_switch *sw; > > - sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL, > - typec_switch_match); > - if (!IS_ERR_OR_NULL(sw)) > - WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); > + sw = kzalloc(sizeof(*sw), GFP_KERNEL); > + if (!sw) > + return ERR_PTR(-ENOMEM); > + > + sw_dev = fwnode_connection_find_match(fwnode, "orientation-switch", NULL, > + typec_switch_match); > + if (IS_ERR_OR_NULL(sw_dev)) { > + kfree(sw); > + return ERR_CAST(sw_dev); > + } > + > + WARN_ON(!try_module_get(sw_dev->dev.parent->driver->owner)); > + > + sw->sw_dev = sw_dev; > > return sw; > } > @@ -82,16 +97,22 @@ EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); > */ > void typec_switch_put(struct typec_switch *sw) > { > - if (!IS_ERR_OR_NULL(sw)) { > - module_put(sw->dev.parent->driver->owner); > - put_device(&sw->dev); > - } > + struct typec_switch_dev *sw_dev; > + > + if (IS_ERR_OR_NULL(sw)) > + return; > + > + sw_dev = sw->sw_dev; > + > + module_put(sw_dev->dev.parent->driver->owner); > + put_device(&sw_dev->dev); > + kfree(sw); > } > EXPORT_SYMBOL_GPL(typec_switch_put); > > static void typec_switch_release(struct device *dev) > { > - kfree(to_typec_switch(dev)); > + kfree(to_typec_switch_dev(dev)); > } > > const struct device_type typec_switch_dev_type = { > @@ -109,82 +130,90 @@ const struct device_type typec_switch_dev_type = { > * connector to the USB controllers. USB Type-C plugs can be inserted > * right-side-up or upside-down. > */ > -struct typec_switch * > +struct typec_switch_dev * > typec_switch_register(struct device *parent, > const struct typec_switch_desc *desc) > { > - struct typec_switch *sw; > + struct typec_switch_dev *sw_dev; > int ret; > > if (!desc || !desc->set) > return ERR_PTR(-EINVAL); > > - sw = kzalloc(sizeof(*sw), GFP_KERNEL); > - if (!sw) > + sw_dev = kzalloc(sizeof(*sw_dev), GFP_KERNEL); > + if (!sw_dev) > return ERR_PTR(-ENOMEM); > > - sw->set = desc->set; > + sw_dev->set = desc->set; > > - device_initialize(&sw->dev); > - sw->dev.parent = parent; > - sw->dev.fwnode = desc->fwnode; > - sw->dev.class = &typec_mux_class; > - sw->dev.type = &typec_switch_dev_type; > - sw->dev.driver_data = desc->drvdata; > - dev_set_name(&sw->dev, "%s-switch", > + device_initialize(&sw_dev->dev); > + sw_dev->dev.parent = parent; > + sw_dev->dev.fwnode = desc->fwnode; > + sw_dev->dev.class = &typec_mux_class; > + sw_dev->dev.type = &typec_switch_dev_type; > + sw_dev->dev.driver_data = desc->drvdata; > + dev_set_name(&sw_dev->dev, "%s-switch", > desc->name ? desc->name : dev_name(parent)); > > - ret = device_add(&sw->dev); > + ret = device_add(&sw_dev->dev); > if (ret) { > dev_err(parent, "failed to register switch (%d)\n", ret); > - put_device(&sw->dev); > + put_device(&sw_dev->dev); > return ERR_PTR(ret); > } > > - return sw; > + return sw_dev; > } > EXPORT_SYMBOL_GPL(typec_switch_register); > > int typec_switch_set(struct typec_switch *sw, > enum typec_orientation orientation) > { > + struct typec_switch_dev *sw_dev; > + > if (IS_ERR_OR_NULL(sw)) > return 0; > > - return sw->set(sw, orientation); > + sw_dev = sw->sw_dev; > + > + return sw_dev->set(sw_dev, orientation); > } > EXPORT_SYMBOL_GPL(typec_switch_set); > > /** > * typec_switch_unregister - Unregister USB Type-C orientation switch > - * @sw: USB Type-C orientation switch > + * @sw_dev: USB Type-C orientation switch > * > * Unregister switch that was registered with typec_switch_register(). > */ > -void typec_switch_unregister(struct typec_switch *sw) > +void typec_switch_unregister(struct typec_switch_dev *sw_dev) > { > - if (!IS_ERR_OR_NULL(sw)) > - device_unregister(&sw->dev); > + if (!IS_ERR_OR_NULL(sw_dev)) > + device_unregister(&sw_dev->dev); > } > EXPORT_SYMBOL_GPL(typec_switch_unregister); > > -void typec_switch_set_drvdata(struct typec_switch *sw, void *data) > +void typec_switch_set_drvdata(struct typec_switch_dev *sw_dev, void *data) > { > - dev_set_drvdata(&sw->dev, data); > + dev_set_drvdata(&sw_dev->dev, data); > } > EXPORT_SYMBOL_GPL(typec_switch_set_drvdata); > > -void *typec_switch_get_drvdata(struct typec_switch *sw) > +void *typec_switch_get_drvdata(struct typec_switch_dev *sw_dev) > { > - return dev_get_drvdata(&sw->dev); > + return dev_get_drvdata(&sw_dev->dev); > } > EXPORT_SYMBOL_GPL(typec_switch_get_drvdata); > > /* ------------------------------------------------------------------------- */ > > +struct typec_mux { > + struct typec_mux_dev *mux_dev; > +}; > + > static int mux_fwnode_match(struct device *dev, const void *fwnode) > { > - if (!is_typec_mux(dev)) > + if (!is_typec_mux_dev(dev)) > return 0; > > return dev_fwnode(dev) == fwnode; > @@ -246,7 +275,7 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, > dev = class_find_device(&typec_mux_class, NULL, fwnode, > mux_fwnode_match); > > - return dev ? to_typec_mux(dev) : ERR_PTR(-EPROBE_DEFER); > + return dev ? to_typec_mux_dev(dev) : ERR_PTR(-EPROBE_DEFER); > } > > /** > @@ -262,12 +291,23 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, > struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode, > const struct typec_altmode_desc *desc) > { > + struct typec_mux_dev *mux_dev; > struct typec_mux *mux; > > - mux = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc, > - typec_mux_match); > - if (!IS_ERR_OR_NULL(mux)) > - WARN_ON(!try_module_get(mux->dev.parent->driver->owner)); > + mux = kzalloc(sizeof(*mux), GFP_KERNEL); > + if (!mux) > + return ERR_PTR(-ENOMEM); > + > + mux_dev = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc, > + typec_mux_match); > + if (IS_ERR_OR_NULL(mux_dev)) { > + kfree(mux); > + return ERR_CAST(mux_dev); > + } > + > + WARN_ON(!try_module_get(mux_dev->dev.parent->driver->owner)); > + > + mux->mux_dev = mux_dev; > > return mux; > } > @@ -281,25 +321,34 @@ EXPORT_SYMBOL_GPL(fwnode_typec_mux_get); > */ > void typec_mux_put(struct typec_mux *mux) > { > - if (!IS_ERR_OR_NULL(mux)) { > - module_put(mux->dev.parent->driver->owner); > - put_device(&mux->dev); > - } > + struct typec_mux_dev *mux_dev; > + > + if (IS_ERR_OR_NULL(mux)) > + return; > + > + mux_dev = mux->mux_dev; > + module_put(mux_dev->dev.parent->driver->owner); > + put_device(&mux_dev->dev); > + kfree(mux); > } > EXPORT_SYMBOL_GPL(typec_mux_put); > > int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state) > { > + struct typec_mux_dev *mux_dev; > + > if (IS_ERR_OR_NULL(mux)) > return 0; > > - return mux->set(mux, state); > + mux_dev = mux->mux_dev; > + > + return mux_dev->set(mux_dev, state); > } > EXPORT_SYMBOL_GPL(typec_mux_set); > > static void typec_mux_release(struct device *dev) > { > - kfree(to_typec_mux(dev)); > + kfree(to_typec_mux_dev(dev)); > } > > const struct device_type typec_mux_dev_type = { > @@ -317,63 +366,63 @@ const struct device_type typec_mux_dev_type = { > * the pins on the connector need to be reconfigured. This function registers > * multiplexer switches routing the pins on the connector. > */ > -struct typec_mux * > +struct typec_mux_dev * > typec_mux_register(struct device *parent, const struct typec_mux_desc *desc) > { > - struct typec_mux *mux; > + struct typec_mux_dev *mux_dev; > int ret; > > if (!desc || !desc->set) > return ERR_PTR(-EINVAL); > > - mux = kzalloc(sizeof(*mux), GFP_KERNEL); > - if (!mux) > + mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL); > + if (!mux_dev) > return ERR_PTR(-ENOMEM); > > - mux->set = desc->set; > + mux_dev->set = desc->set; > > - device_initialize(&mux->dev); > - mux->dev.parent = parent; > - mux->dev.fwnode = desc->fwnode; > - mux->dev.class = &typec_mux_class; > - mux->dev.type = &typec_mux_dev_type; > - mux->dev.driver_data = desc->drvdata; > - dev_set_name(&mux->dev, "%s-mux", > + device_initialize(&mux_dev->dev); > + mux_dev->dev.parent = parent; > + mux_dev->dev.fwnode = desc->fwnode; > + mux_dev->dev.class = &typec_mux_class; > + mux_dev->dev.type = &typec_mux_dev_type; > + mux_dev->dev.driver_data = desc->drvdata; > + dev_set_name(&mux_dev->dev, "%s-mux", > desc->name ? desc->name : dev_name(parent)); > > - ret = device_add(&mux->dev); > + ret = device_add(&mux_dev->dev); > if (ret) { > dev_err(parent, "failed to register mux (%d)\n", ret); > - put_device(&mux->dev); > + put_device(&mux_dev->dev); > return ERR_PTR(ret); > } > > - return mux; > + return mux_dev; > } > EXPORT_SYMBOL_GPL(typec_mux_register); > > /** > * typec_mux_unregister - Unregister Multiplexer Switch > - * @mux: USB Type-C Connector Multiplexer/DeMultiplexer > + * @mux_dev: USB Type-C Connector Multiplexer/DeMultiplexer > * > * Unregister mux that was registered with typec_mux_register(). > */ > -void typec_mux_unregister(struct typec_mux *mux) > +void typec_mux_unregister(struct typec_mux_dev *mux_dev) > { > - if (!IS_ERR_OR_NULL(mux)) > - device_unregister(&mux->dev); > + if (!IS_ERR_OR_NULL(mux_dev)) > + device_unregister(&mux_dev->dev); > } > EXPORT_SYMBOL_GPL(typec_mux_unregister); > > -void typec_mux_set_drvdata(struct typec_mux *mux, void *data) > +void typec_mux_set_drvdata(struct typec_mux_dev *mux_dev, void *data) > { > - dev_set_drvdata(&mux->dev, data); > + dev_set_drvdata(&mux_dev->dev, data); > } > EXPORT_SYMBOL_GPL(typec_mux_set_drvdata); > > -void *typec_mux_get_drvdata(struct typec_mux *mux) > +void *typec_mux_get_drvdata(struct typec_mux_dev *mux_dev) > { > - return dev_get_drvdata(&mux->dev); > + return dev_get_drvdata(&mux_dev->dev); > } > EXPORT_SYMBOL_GPL(typec_mux_get_drvdata); > > diff --git a/drivers/usb/typec/mux.h b/drivers/usb/typec/mux.h > index b1d6e837cb74..58f0f28b6dc8 100644 > --- a/drivers/usb/typec/mux.h > +++ b/drivers/usb/typec/mux.h > @@ -5,23 +5,23 @@ > > #include <linux/usb/typec_mux.h> > > -struct typec_switch { > +struct typec_switch_dev { > struct device dev; > typec_switch_set_fn_t set; > }; > > -struct typec_mux { > +struct typec_mux_dev { > struct device dev; > typec_mux_set_fn_t set; > }; > > -#define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev) > -#define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev) > +#define to_typec_switch_dev(_dev_) container_of(_dev_, struct typec_switch_dev, dev) > +#define to_typec_mux_dev(_dev_) container_of(_dev_, struct typec_mux_dev, dev) > > extern const struct device_type typec_switch_dev_type; > extern const struct device_type typec_mux_dev_type; > > -#define is_typec_switch(dev) ((dev)->type == &typec_switch_dev_type) > -#define is_typec_mux(dev) ((dev)->type == &typec_mux_dev_type) > +#define is_typec_switch_dev(dev) ((dev)->type == &typec_switch_dev_type) > +#define is_typec_mux_dev(dev) ((dev)->type == &typec_mux_dev_type) > > #endif /* __USB_TYPEC_MUX__ */ > diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c > index 2cdd22130834..51d8f3b88128 100644 > --- a/drivers/usb/typec/mux/intel_pmc_mux.c > +++ b/drivers/usb/typec/mux/intel_pmc_mux.c > @@ -121,8 +121,8 @@ struct pmc_usb_port { > int num; > u32 iom_status; > struct pmc_usb *pmc; > - struct typec_mux *typec_mux; > - struct typec_switch *typec_sw; > + struct typec_mux_dev *typec_mux; > + struct typec_switch_dev *typec_sw; > struct usb_role_switch *usb_sw; > > enum typec_orientation orientation; > @@ -416,7 +416,7 @@ static int pmc_usb_connect(struct pmc_usb_port *port, enum usb_role role) > } > > static int > -pmc_usb_mux_set(struct typec_mux *mux, struct typec_mux_state *state) > +pmc_usb_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) > { > struct pmc_usb_port *port = typec_mux_get_drvdata(mux); > > @@ -452,7 +452,7 @@ pmc_usb_mux_set(struct typec_mux *mux, struct typec_mux_state *state) > return -EOPNOTSUPP; > } > > -static int pmc_usb_set_orientation(struct typec_switch *sw, > +static int pmc_usb_set_orientation(struct typec_switch_dev *sw, > enum typec_orientation orientation) > { > struct pmc_usb_port *port = typec_switch_get_drvdata(sw); > diff --git a/drivers/usb/typec/mux/pi3usb30532.c b/drivers/usb/typec/mux/pi3usb30532.c > index 7afe275b17d0..6ce9f282594e 100644 > --- a/drivers/usb/typec/mux/pi3usb30532.c > +++ b/drivers/usb/typec/mux/pi3usb30532.c > @@ -23,8 +23,8 @@ > struct pi3usb30532 { > struct i2c_client *client; > struct mutex lock; /* protects the cached conf register */ > - struct typec_switch *sw; > - struct typec_mux *mux; > + struct typec_switch_dev *sw; > + struct typec_mux_dev *mux; > u8 conf; > }; > > @@ -45,7 +45,7 @@ static int pi3usb30532_set_conf(struct pi3usb30532 *pi, u8 new_conf) > return 0; > } > > -static int pi3usb30532_sw_set(struct typec_switch *sw, > +static int pi3usb30532_sw_set(struct typec_switch_dev *sw, > enum typec_orientation orientation) > { > struct pi3usb30532 *pi = typec_switch_get_drvdata(sw); > @@ -74,7 +74,7 @@ static int pi3usb30532_sw_set(struct typec_switch *sw, > } > > static int > -pi3usb30532_mux_set(struct typec_mux *mux, struct typec_mux_state *state) > +pi3usb30532_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) > { > struct pi3usb30532 *pi = typec_mux_get_drvdata(mux); > u8 new_conf; > diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h > index a9d9957933dc..ee57781dcf28 100644 > --- a/include/linux/usb/typec_mux.h > +++ b/include/linux/usb/typec_mux.h > @@ -8,11 +8,13 @@ > > struct device; > struct typec_mux; > +struct typec_mux_dev; > struct typec_switch; > +struct typec_switch_dev; > struct typec_altmode; > struct fwnode_handle; > > -typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw, > +typedef int (*typec_switch_set_fn_t)(struct typec_switch_dev *sw, > enum typec_orientation orientation); > > struct typec_switch_desc { > @@ -32,13 +34,13 @@ static inline struct typec_switch *typec_switch_get(struct device *dev) > return fwnode_typec_switch_get(dev_fwnode(dev)); > } > > -struct typec_switch * > +struct typec_switch_dev * > typec_switch_register(struct device *parent, > const struct typec_switch_desc *desc); > -void typec_switch_unregister(struct typec_switch *sw); > +void typec_switch_unregister(struct typec_switch_dev *sw); > > -void typec_switch_set_drvdata(struct typec_switch *sw, void *data); > -void *typec_switch_get_drvdata(struct typec_switch *sw); > +void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data); > +void *typec_switch_get_drvdata(struct typec_switch_dev *sw); > > struct typec_mux_state { > struct typec_altmode *alt; > @@ -46,7 +48,7 @@ struct typec_mux_state { > void *data; > }; > > -typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, > +typedef int (*typec_mux_set_fn_t)(struct typec_mux_dev *mux, > struct typec_mux_state *state); > > struct typec_mux_desc { > @@ -67,11 +69,11 @@ typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc) > return fwnode_typec_mux_get(dev_fwnode(dev), desc); > } > > -struct typec_mux * > +struct typec_mux_dev * > typec_mux_register(struct device *parent, const struct typec_mux_desc *desc); > -void typec_mux_unregister(struct typec_mux *mux); > +void typec_mux_unregister(struct typec_mux_dev *mux); > > -void typec_mux_set_drvdata(struct typec_mux *mux, void *data); > -void *typec_mux_get_drvdata(struct typec_mux *mux); > +void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data); > +void *typec_mux_get_drvdata(struct typec_mux_dev *mux); > > #endif /* __USB_TYPEC_MUX */ > -- > 2.33.1
diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c index 78e0e78954f2..26ea2fdec17d 100644 --- a/drivers/usb/typec/bus.c +++ b/drivers/usb/typec/bus.c @@ -24,7 +24,7 @@ typec_altmode_set_mux(struct altmode *alt, unsigned long conf, void *data) state.mode = conf; state.data = data; - return alt->mux->set(alt->mux, &state); + return typec_mux_set(alt->mux, &state); } static int typec_altmode_set_state(struct typec_altmode *adev, diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index c8340de0ed49..d0b42c297aca 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -17,9 +17,13 @@ #include "class.h" #include "mux.h" +struct typec_switch { + struct typec_switch_dev *sw_dev; +}; + static int switch_fwnode_match(struct device *dev, const void *fwnode) { - if (!is_typec_switch(dev)) + if (!is_typec_switch_dev(dev)) return 0; return dev_fwnode(dev) == fwnode; @@ -49,7 +53,7 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, dev = class_find_device(&typec_mux_class, NULL, fwnode, switch_fwnode_match); - return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); + return dev ? to_typec_switch_dev(dev) : ERR_PTR(-EPROBE_DEFER); } /** @@ -63,12 +67,23 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, */ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode) { + struct typec_switch_dev *sw_dev; struct typec_switch *sw; - sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL, - typec_switch_match); - if (!IS_ERR_OR_NULL(sw)) - WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + sw = kzalloc(sizeof(*sw), GFP_KERNEL); + if (!sw) + return ERR_PTR(-ENOMEM); + + sw_dev = fwnode_connection_find_match(fwnode, "orientation-switch", NULL, + typec_switch_match); + if (IS_ERR_OR_NULL(sw_dev)) { + kfree(sw); + return ERR_CAST(sw_dev); + } + + WARN_ON(!try_module_get(sw_dev->dev.parent->driver->owner)); + + sw->sw_dev = sw_dev; return sw; } @@ -82,16 +97,22 @@ EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); */ void typec_switch_put(struct typec_switch *sw) { - if (!IS_ERR_OR_NULL(sw)) { - module_put(sw->dev.parent->driver->owner); - put_device(&sw->dev); - } + struct typec_switch_dev *sw_dev; + + if (IS_ERR_OR_NULL(sw)) + return; + + sw_dev = sw->sw_dev; + + module_put(sw_dev->dev.parent->driver->owner); + put_device(&sw_dev->dev); + kfree(sw); } EXPORT_SYMBOL_GPL(typec_switch_put); static void typec_switch_release(struct device *dev) { - kfree(to_typec_switch(dev)); + kfree(to_typec_switch_dev(dev)); } const struct device_type typec_switch_dev_type = { @@ -109,82 +130,90 @@ const struct device_type typec_switch_dev_type = { * connector to the USB controllers. USB Type-C plugs can be inserted * right-side-up or upside-down. */ -struct typec_switch * +struct typec_switch_dev * typec_switch_register(struct device *parent, const struct typec_switch_desc *desc) { - struct typec_switch *sw; + struct typec_switch_dev *sw_dev; int ret; if (!desc || !desc->set) return ERR_PTR(-EINVAL); - sw = kzalloc(sizeof(*sw), GFP_KERNEL); - if (!sw) + sw_dev = kzalloc(sizeof(*sw_dev), GFP_KERNEL); + if (!sw_dev) return ERR_PTR(-ENOMEM); - sw->set = desc->set; + sw_dev->set = desc->set; - device_initialize(&sw->dev); - sw->dev.parent = parent; - sw->dev.fwnode = desc->fwnode; - sw->dev.class = &typec_mux_class; - sw->dev.type = &typec_switch_dev_type; - sw->dev.driver_data = desc->drvdata; - dev_set_name(&sw->dev, "%s-switch", + device_initialize(&sw_dev->dev); + sw_dev->dev.parent = parent; + sw_dev->dev.fwnode = desc->fwnode; + sw_dev->dev.class = &typec_mux_class; + sw_dev->dev.type = &typec_switch_dev_type; + sw_dev->dev.driver_data = desc->drvdata; + dev_set_name(&sw_dev->dev, "%s-switch", desc->name ? desc->name : dev_name(parent)); - ret = device_add(&sw->dev); + ret = device_add(&sw_dev->dev); if (ret) { dev_err(parent, "failed to register switch (%d)\n", ret); - put_device(&sw->dev); + put_device(&sw_dev->dev); return ERR_PTR(ret); } - return sw; + return sw_dev; } EXPORT_SYMBOL_GPL(typec_switch_register); int typec_switch_set(struct typec_switch *sw, enum typec_orientation orientation) { + struct typec_switch_dev *sw_dev; + if (IS_ERR_OR_NULL(sw)) return 0; - return sw->set(sw, orientation); + sw_dev = sw->sw_dev; + + return sw_dev->set(sw_dev, orientation); } EXPORT_SYMBOL_GPL(typec_switch_set); /** * typec_switch_unregister - Unregister USB Type-C orientation switch - * @sw: USB Type-C orientation switch + * @sw_dev: USB Type-C orientation switch * * Unregister switch that was registered with typec_switch_register(). */ -void typec_switch_unregister(struct typec_switch *sw) +void typec_switch_unregister(struct typec_switch_dev *sw_dev) { - if (!IS_ERR_OR_NULL(sw)) - device_unregister(&sw->dev); + if (!IS_ERR_OR_NULL(sw_dev)) + device_unregister(&sw_dev->dev); } EXPORT_SYMBOL_GPL(typec_switch_unregister); -void typec_switch_set_drvdata(struct typec_switch *sw, void *data) +void typec_switch_set_drvdata(struct typec_switch_dev *sw_dev, void *data) { - dev_set_drvdata(&sw->dev, data); + dev_set_drvdata(&sw_dev->dev, data); } EXPORT_SYMBOL_GPL(typec_switch_set_drvdata); -void *typec_switch_get_drvdata(struct typec_switch *sw) +void *typec_switch_get_drvdata(struct typec_switch_dev *sw_dev) { - return dev_get_drvdata(&sw->dev); + return dev_get_drvdata(&sw_dev->dev); } EXPORT_SYMBOL_GPL(typec_switch_get_drvdata); /* ------------------------------------------------------------------------- */ +struct typec_mux { + struct typec_mux_dev *mux_dev; +}; + static int mux_fwnode_match(struct device *dev, const void *fwnode) { - if (!is_typec_mux(dev)) + if (!is_typec_mux_dev(dev)) return 0; return dev_fwnode(dev) == fwnode; @@ -246,7 +275,7 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, dev = class_find_device(&typec_mux_class, NULL, fwnode, mux_fwnode_match); - return dev ? to_typec_mux(dev) : ERR_PTR(-EPROBE_DEFER); + return dev ? to_typec_mux_dev(dev) : ERR_PTR(-EPROBE_DEFER); } /** @@ -262,12 +291,23 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode, const struct typec_altmode_desc *desc) { + struct typec_mux_dev *mux_dev; struct typec_mux *mux; - mux = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc, - typec_mux_match); - if (!IS_ERR_OR_NULL(mux)) - WARN_ON(!try_module_get(mux->dev.parent->driver->owner)); + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux_dev = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc, + typec_mux_match); + if (IS_ERR_OR_NULL(mux_dev)) { + kfree(mux); + return ERR_CAST(mux_dev); + } + + WARN_ON(!try_module_get(mux_dev->dev.parent->driver->owner)); + + mux->mux_dev = mux_dev; return mux; } @@ -281,25 +321,34 @@ EXPORT_SYMBOL_GPL(fwnode_typec_mux_get); */ void typec_mux_put(struct typec_mux *mux) { - if (!IS_ERR_OR_NULL(mux)) { - module_put(mux->dev.parent->driver->owner); - put_device(&mux->dev); - } + struct typec_mux_dev *mux_dev; + + if (IS_ERR_OR_NULL(mux)) + return; + + mux_dev = mux->mux_dev; + module_put(mux_dev->dev.parent->driver->owner); + put_device(&mux_dev->dev); + kfree(mux); } EXPORT_SYMBOL_GPL(typec_mux_put); int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state) { + struct typec_mux_dev *mux_dev; + if (IS_ERR_OR_NULL(mux)) return 0; - return mux->set(mux, state); + mux_dev = mux->mux_dev; + + return mux_dev->set(mux_dev, state); } EXPORT_SYMBOL_GPL(typec_mux_set); static void typec_mux_release(struct device *dev) { - kfree(to_typec_mux(dev)); + kfree(to_typec_mux_dev(dev)); } const struct device_type typec_mux_dev_type = { @@ -317,63 +366,63 @@ const struct device_type typec_mux_dev_type = { * the pins on the connector need to be reconfigured. This function registers * multiplexer switches routing the pins on the connector. */ -struct typec_mux * +struct typec_mux_dev * typec_mux_register(struct device *parent, const struct typec_mux_desc *desc) { - struct typec_mux *mux; + struct typec_mux_dev *mux_dev; int ret; if (!desc || !desc->set) return ERR_PTR(-EINVAL); - mux = kzalloc(sizeof(*mux), GFP_KERNEL); - if (!mux) + mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL); + if (!mux_dev) return ERR_PTR(-ENOMEM); - mux->set = desc->set; + mux_dev->set = desc->set; - device_initialize(&mux->dev); - mux->dev.parent = parent; - mux->dev.fwnode = desc->fwnode; - mux->dev.class = &typec_mux_class; - mux->dev.type = &typec_mux_dev_type; - mux->dev.driver_data = desc->drvdata; - dev_set_name(&mux->dev, "%s-mux", + device_initialize(&mux_dev->dev); + mux_dev->dev.parent = parent; + mux_dev->dev.fwnode = desc->fwnode; + mux_dev->dev.class = &typec_mux_class; + mux_dev->dev.type = &typec_mux_dev_type; + mux_dev->dev.driver_data = desc->drvdata; + dev_set_name(&mux_dev->dev, "%s-mux", desc->name ? desc->name : dev_name(parent)); - ret = device_add(&mux->dev); + ret = device_add(&mux_dev->dev); if (ret) { dev_err(parent, "failed to register mux (%d)\n", ret); - put_device(&mux->dev); + put_device(&mux_dev->dev); return ERR_PTR(ret); } - return mux; + return mux_dev; } EXPORT_SYMBOL_GPL(typec_mux_register); /** * typec_mux_unregister - Unregister Multiplexer Switch - * @mux: USB Type-C Connector Multiplexer/DeMultiplexer + * @mux_dev: USB Type-C Connector Multiplexer/DeMultiplexer * * Unregister mux that was registered with typec_mux_register(). */ -void typec_mux_unregister(struct typec_mux *mux) +void typec_mux_unregister(struct typec_mux_dev *mux_dev) { - if (!IS_ERR_OR_NULL(mux)) - device_unregister(&mux->dev); + if (!IS_ERR_OR_NULL(mux_dev)) + device_unregister(&mux_dev->dev); } EXPORT_SYMBOL_GPL(typec_mux_unregister); -void typec_mux_set_drvdata(struct typec_mux *mux, void *data) +void typec_mux_set_drvdata(struct typec_mux_dev *mux_dev, void *data) { - dev_set_drvdata(&mux->dev, data); + dev_set_drvdata(&mux_dev->dev, data); } EXPORT_SYMBOL_GPL(typec_mux_set_drvdata); -void *typec_mux_get_drvdata(struct typec_mux *mux) +void *typec_mux_get_drvdata(struct typec_mux_dev *mux_dev) { - return dev_get_drvdata(&mux->dev); + return dev_get_drvdata(&mux_dev->dev); } EXPORT_SYMBOL_GPL(typec_mux_get_drvdata); diff --git a/drivers/usb/typec/mux.h b/drivers/usb/typec/mux.h index b1d6e837cb74..58f0f28b6dc8 100644 --- a/drivers/usb/typec/mux.h +++ b/drivers/usb/typec/mux.h @@ -5,23 +5,23 @@ #include <linux/usb/typec_mux.h> -struct typec_switch { +struct typec_switch_dev { struct device dev; typec_switch_set_fn_t set; }; -struct typec_mux { +struct typec_mux_dev { struct device dev; typec_mux_set_fn_t set; }; -#define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev) -#define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev) +#define to_typec_switch_dev(_dev_) container_of(_dev_, struct typec_switch_dev, dev) +#define to_typec_mux_dev(_dev_) container_of(_dev_, struct typec_mux_dev, dev) extern const struct device_type typec_switch_dev_type; extern const struct device_type typec_mux_dev_type; -#define is_typec_switch(dev) ((dev)->type == &typec_switch_dev_type) -#define is_typec_mux(dev) ((dev)->type == &typec_mux_dev_type) +#define is_typec_switch_dev(dev) ((dev)->type == &typec_switch_dev_type) +#define is_typec_mux_dev(dev) ((dev)->type == &typec_mux_dev_type) #endif /* __USB_TYPEC_MUX__ */ diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index 2cdd22130834..51d8f3b88128 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -121,8 +121,8 @@ struct pmc_usb_port { int num; u32 iom_status; struct pmc_usb *pmc; - struct typec_mux *typec_mux; - struct typec_switch *typec_sw; + struct typec_mux_dev *typec_mux; + struct typec_switch_dev *typec_sw; struct usb_role_switch *usb_sw; enum typec_orientation orientation; @@ -416,7 +416,7 @@ static int pmc_usb_connect(struct pmc_usb_port *port, enum usb_role role) } static int -pmc_usb_mux_set(struct typec_mux *mux, struct typec_mux_state *state) +pmc_usb_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) { struct pmc_usb_port *port = typec_mux_get_drvdata(mux); @@ -452,7 +452,7 @@ pmc_usb_mux_set(struct typec_mux *mux, struct typec_mux_state *state) return -EOPNOTSUPP; } -static int pmc_usb_set_orientation(struct typec_switch *sw, +static int pmc_usb_set_orientation(struct typec_switch_dev *sw, enum typec_orientation orientation) { struct pmc_usb_port *port = typec_switch_get_drvdata(sw); diff --git a/drivers/usb/typec/mux/pi3usb30532.c b/drivers/usb/typec/mux/pi3usb30532.c index 7afe275b17d0..6ce9f282594e 100644 --- a/drivers/usb/typec/mux/pi3usb30532.c +++ b/drivers/usb/typec/mux/pi3usb30532.c @@ -23,8 +23,8 @@ struct pi3usb30532 { struct i2c_client *client; struct mutex lock; /* protects the cached conf register */ - struct typec_switch *sw; - struct typec_mux *mux; + struct typec_switch_dev *sw; + struct typec_mux_dev *mux; u8 conf; }; @@ -45,7 +45,7 @@ static int pi3usb30532_set_conf(struct pi3usb30532 *pi, u8 new_conf) return 0; } -static int pi3usb30532_sw_set(struct typec_switch *sw, +static int pi3usb30532_sw_set(struct typec_switch_dev *sw, enum typec_orientation orientation) { struct pi3usb30532 *pi = typec_switch_get_drvdata(sw); @@ -74,7 +74,7 @@ static int pi3usb30532_sw_set(struct typec_switch *sw, } static int -pi3usb30532_mux_set(struct typec_mux *mux, struct typec_mux_state *state) +pi3usb30532_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) { struct pi3usb30532 *pi = typec_mux_get_drvdata(mux); u8 new_conf; diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h index a9d9957933dc..ee57781dcf28 100644 --- a/include/linux/usb/typec_mux.h +++ b/include/linux/usb/typec_mux.h @@ -8,11 +8,13 @@ struct device; struct typec_mux; +struct typec_mux_dev; struct typec_switch; +struct typec_switch_dev; struct typec_altmode; struct fwnode_handle; -typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw, +typedef int (*typec_switch_set_fn_t)(struct typec_switch_dev *sw, enum typec_orientation orientation); struct typec_switch_desc { @@ -32,13 +34,13 @@ static inline struct typec_switch *typec_switch_get(struct device *dev) return fwnode_typec_switch_get(dev_fwnode(dev)); } -struct typec_switch * +struct typec_switch_dev * typec_switch_register(struct device *parent, const struct typec_switch_desc *desc); -void typec_switch_unregister(struct typec_switch *sw); +void typec_switch_unregister(struct typec_switch_dev *sw); -void typec_switch_set_drvdata(struct typec_switch *sw, void *data); -void *typec_switch_get_drvdata(struct typec_switch *sw); +void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data); +void *typec_switch_get_drvdata(struct typec_switch_dev *sw); struct typec_mux_state { struct typec_altmode *alt; @@ -46,7 +48,7 @@ struct typec_mux_state { void *data; }; -typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, +typedef int (*typec_mux_set_fn_t)(struct typec_mux_dev *mux, struct typec_mux_state *state); struct typec_mux_desc { @@ -67,11 +69,11 @@ typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc) return fwnode_typec_mux_get(dev_fwnode(dev), desc); } -struct typec_mux * +struct typec_mux_dev * typec_mux_register(struct device *parent, const struct typec_mux_desc *desc); -void typec_mux_unregister(struct typec_mux *mux); +void typec_mux_unregister(struct typec_mux_dev *mux); -void typec_mux_set_drvdata(struct typec_mux *mux, void *data); -void *typec_mux_get_drvdata(struct typec_mux *mux); +void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data); +void *typec_mux_get_drvdata(struct typec_mux_dev *mux); #endif /* __USB_TYPEC_MUX */
Rather than directly exposing the implementation's representation of the typec muxes to the controller/clients, introduce an indirection object. This enables the introduction of turning this relationship into a one-to-many in the following patch. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- Changes sice v1: - None drivers/usb/typec/bus.c | 2 +- drivers/usb/typec/mux.c | 189 ++++++++++++++++---------- drivers/usb/typec/mux.h | 12 +- drivers/usb/typec/mux/intel_pmc_mux.c | 8 +- drivers/usb/typec/mux/pi3usb30532.c | 8 +- include/linux/usb/typec_mux.h | 22 +-- 6 files changed, 146 insertions(+), 95 deletions(-)