xref: /openbmc/linux/drivers/usb/typec/mux.c (revision cbdc0f54)
1bdecb33aSHeikki Krogerus // SPDX-License-Identifier: GPL-2.0
22d686c73SRandy Dunlap /*
3bdecb33aSHeikki Krogerus  * USB Type-C Multiplexer/DeMultiplexer Switch support
4bdecb33aSHeikki Krogerus  *
5bdecb33aSHeikki Krogerus  * Copyright (C) 2018 Intel Corporation
6bdecb33aSHeikki Krogerus  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
7bdecb33aSHeikki Krogerus  *         Hans de Goede <hdegoede@redhat.com>
8bdecb33aSHeikki Krogerus  */
9bdecb33aSHeikki Krogerus 
10bdecb33aSHeikki Krogerus #include <linux/device.h>
11bdecb33aSHeikki Krogerus #include <linux/list.h>
123e3b8196SHeikki Krogerus #include <linux/module.h>
13bdecb33aSHeikki Krogerus #include <linux/mutex.h>
1496a6d031SHeikki Krogerus #include <linux/property.h>
1596a6d031SHeikki Krogerus #include <linux/slab.h>
16bdecb33aSHeikki Krogerus #include <linux/usb/typec_mux.h>
17bdecb33aSHeikki Krogerus 
183370db35SHeikki Krogerus #include "bus.h"
193370db35SHeikki Krogerus 
203370db35SHeikki Krogerus static bool dev_name_ends_with(struct device *dev, const char *suffix)
213370db35SHeikki Krogerus {
223370db35SHeikki Krogerus 	const char *name = dev_name(dev);
233370db35SHeikki Krogerus 	const int name_len = strlen(name);
243370db35SHeikki Krogerus 	const int suffix_len = strlen(suffix);
253370db35SHeikki Krogerus 
263370db35SHeikki Krogerus 	if (suffix_len > name_len)
273370db35SHeikki Krogerus 		return false;
283370db35SHeikki Krogerus 
293370db35SHeikki Krogerus 	return strcmp(name + (name_len - suffix_len), suffix) == 0;
303370db35SHeikki Krogerus }
313370db35SHeikki Krogerus 
323370db35SHeikki Krogerus static int switch_fwnode_match(struct device *dev, const void *fwnode)
333370db35SHeikki Krogerus {
343370db35SHeikki Krogerus 	return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-switch");
353370db35SHeikki Krogerus }
36bdecb33aSHeikki Krogerus 
37f5514c91SHeikki Krogerus static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id,
38bdecb33aSHeikki Krogerus 				void *data)
39bdecb33aSHeikki Krogerus {
403370db35SHeikki Krogerus 	struct device *dev;
41bdecb33aSHeikki Krogerus 
42f5514c91SHeikki Krogerus 	if (id && !fwnode_property_present(fwnode, id))
4396a6d031SHeikki Krogerus 		return NULL;
4496a6d031SHeikki Krogerus 
45f5514c91SHeikki Krogerus 	dev = class_find_device(&typec_mux_class, NULL, fwnode,
463370db35SHeikki Krogerus 				switch_fwnode_match);
4796a6d031SHeikki Krogerus 
483370db35SHeikki Krogerus 	return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
49bdecb33aSHeikki Krogerus }
50bdecb33aSHeikki Krogerus 
51bdecb33aSHeikki Krogerus /**
52d1c6a769SHeikki Krogerus  * fwnode_typec_switch_get - Find USB Type-C orientation switch
53d1c6a769SHeikki Krogerus  * @fwnode: The caller device node
54bdecb33aSHeikki Krogerus  *
55bdecb33aSHeikki Krogerus  * Finds a switch linked with @dev. Returns a reference to the switch on
56bdecb33aSHeikki Krogerus  * success, NULL if no matching connection was found, or
57bdecb33aSHeikki Krogerus  * ERR_PTR(-EPROBE_DEFER) when a connection was found but the switch
58bdecb33aSHeikki Krogerus  * has not been enumerated yet.
59bdecb33aSHeikki Krogerus  */
60d1c6a769SHeikki Krogerus struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
61bdecb33aSHeikki Krogerus {
62bdecb33aSHeikki Krogerus 	struct typec_switch *sw;
63bdecb33aSHeikki Krogerus 
64d1c6a769SHeikki Krogerus 	sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL,
65bdecb33aSHeikki Krogerus 					  typec_switch_match);
663370db35SHeikki Krogerus 	if (!IS_ERR_OR_NULL(sw))
673370db35SHeikki Krogerus 		WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
68bdecb33aSHeikki Krogerus 
69bdecb33aSHeikki Krogerus 	return sw;
70bdecb33aSHeikki Krogerus }
71d1c6a769SHeikki Krogerus EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
72bdecb33aSHeikki Krogerus 
73bdecb33aSHeikki Krogerus /**
74cbdc0f54SMauro Carvalho Chehab  * typec_switch_put - Release USB Type-C orientation switch
75bdecb33aSHeikki Krogerus  * @sw: USB Type-C orientation switch
76bdecb33aSHeikki Krogerus  *
77bdecb33aSHeikki Krogerus  * Decrement reference count for @sw.
78bdecb33aSHeikki Krogerus  */
79bdecb33aSHeikki Krogerus void typec_switch_put(struct typec_switch *sw)
80bdecb33aSHeikki Krogerus {
813e3b8196SHeikki Krogerus 	if (!IS_ERR_OR_NULL(sw)) {
823370db35SHeikki Krogerus 		module_put(sw->dev.parent->driver->owner);
833370db35SHeikki Krogerus 		put_device(&sw->dev);
84bdecb33aSHeikki Krogerus 	}
853e3b8196SHeikki Krogerus }
86bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_put);
87bdecb33aSHeikki Krogerus 
883370db35SHeikki Krogerus static void typec_switch_release(struct device *dev)
893370db35SHeikki Krogerus {
903370db35SHeikki Krogerus 	kfree(to_typec_switch(dev));
913370db35SHeikki Krogerus }
923370db35SHeikki Krogerus 
933370db35SHeikki Krogerus static const struct device_type typec_switch_dev_type = {
943370db35SHeikki Krogerus 	.name = "orientation_switch",
953370db35SHeikki Krogerus 	.release = typec_switch_release,
963370db35SHeikki Krogerus };
973370db35SHeikki Krogerus 
98bdecb33aSHeikki Krogerus /**
99bdecb33aSHeikki Krogerus  * typec_switch_register - Register USB Type-C orientation switch
1003370db35SHeikki Krogerus  * @parent: Parent device
1013370db35SHeikki Krogerus  * @desc: Orientation switch description
102bdecb33aSHeikki Krogerus  *
103bdecb33aSHeikki Krogerus  * This function registers a switch that can be used for routing the correct
104bdecb33aSHeikki Krogerus  * data pairs depending on the cable plug orientation from the USB Type-C
105bdecb33aSHeikki Krogerus  * connector to the USB controllers. USB Type-C plugs can be inserted
106bdecb33aSHeikki Krogerus  * right-side-up or upside-down.
107bdecb33aSHeikki Krogerus  */
1083370db35SHeikki Krogerus struct typec_switch *
1093370db35SHeikki Krogerus typec_switch_register(struct device *parent,
1103370db35SHeikki Krogerus 		      const struct typec_switch_desc *desc)
111bdecb33aSHeikki Krogerus {
1123370db35SHeikki Krogerus 	struct typec_switch *sw;
1133370db35SHeikki Krogerus 	int ret;
114bdecb33aSHeikki Krogerus 
1153370db35SHeikki Krogerus 	if (!desc || !desc->set)
1163370db35SHeikki Krogerus 		return ERR_PTR(-EINVAL);
1173370db35SHeikki Krogerus 
1183370db35SHeikki Krogerus 	sw = kzalloc(sizeof(*sw), GFP_KERNEL);
1193370db35SHeikki Krogerus 	if (!sw)
1203370db35SHeikki Krogerus 		return ERR_PTR(-ENOMEM);
1213370db35SHeikki Krogerus 
1223370db35SHeikki Krogerus 	sw->set = desc->set;
1233370db35SHeikki Krogerus 
1243370db35SHeikki Krogerus 	device_initialize(&sw->dev);
1253370db35SHeikki Krogerus 	sw->dev.parent = parent;
1263370db35SHeikki Krogerus 	sw->dev.fwnode = desc->fwnode;
1273370db35SHeikki Krogerus 	sw->dev.class = &typec_mux_class;
1283370db35SHeikki Krogerus 	sw->dev.type = &typec_switch_dev_type;
1293370db35SHeikki Krogerus 	sw->dev.driver_data = desc->drvdata;
130ef441dd6SHeikki Krogerus 	dev_set_name(&sw->dev, "%s-switch",
131ef441dd6SHeikki Krogerus 		     desc->name ? desc->name : dev_name(parent));
1323370db35SHeikki Krogerus 
1333370db35SHeikki Krogerus 	ret = device_add(&sw->dev);
1343370db35SHeikki Krogerus 	if (ret) {
1353370db35SHeikki Krogerus 		dev_err(parent, "failed to register switch (%d)\n", ret);
1363370db35SHeikki Krogerus 		put_device(&sw->dev);
1373370db35SHeikki Krogerus 		return ERR_PTR(ret);
1383370db35SHeikki Krogerus 	}
1393370db35SHeikki Krogerus 
1403370db35SHeikki Krogerus 	return sw;
141bdecb33aSHeikki Krogerus }
142bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_register);
143bdecb33aSHeikki Krogerus 
144774a9df6SHeikki Krogerus int typec_switch_set(struct typec_switch *sw,
145774a9df6SHeikki Krogerus 		     enum typec_orientation orientation)
146774a9df6SHeikki Krogerus {
147774a9df6SHeikki Krogerus 	if (IS_ERR_OR_NULL(sw))
148774a9df6SHeikki Krogerus 		return 0;
149774a9df6SHeikki Krogerus 
150774a9df6SHeikki Krogerus 	return sw->set(sw, orientation);
151774a9df6SHeikki Krogerus }
152774a9df6SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_set);
153774a9df6SHeikki Krogerus 
154bdecb33aSHeikki Krogerus /**
155bdecb33aSHeikki Krogerus  * typec_switch_unregister - Unregister USB Type-C orientation switch
156bdecb33aSHeikki Krogerus  * @sw: USB Type-C orientation switch
157bdecb33aSHeikki Krogerus  *
158bdecb33aSHeikki Krogerus  * Unregister switch that was registered with typec_switch_register().
159bdecb33aSHeikki Krogerus  */
160bdecb33aSHeikki Krogerus void typec_switch_unregister(struct typec_switch *sw)
161bdecb33aSHeikki Krogerus {
1623370db35SHeikki Krogerus 	if (!IS_ERR_OR_NULL(sw))
1633370db35SHeikki Krogerus 		device_unregister(&sw->dev);
164bdecb33aSHeikki Krogerus }
165bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_unregister);
166bdecb33aSHeikki Krogerus 
1673370db35SHeikki Krogerus void typec_switch_set_drvdata(struct typec_switch *sw, void *data)
1683370db35SHeikki Krogerus {
1693370db35SHeikki Krogerus 	dev_set_drvdata(&sw->dev, data);
1703370db35SHeikki Krogerus }
1713370db35SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_set_drvdata);
1723370db35SHeikki Krogerus 
1733370db35SHeikki Krogerus void *typec_switch_get_drvdata(struct typec_switch *sw)
1743370db35SHeikki Krogerus {
1753370db35SHeikki Krogerus 	return dev_get_drvdata(&sw->dev);
1763370db35SHeikki Krogerus }
1773370db35SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_switch_get_drvdata);
1783370db35SHeikki Krogerus 
179bdecb33aSHeikki Krogerus /* ------------------------------------------------------------------------- */
180bdecb33aSHeikki Krogerus 
1813370db35SHeikki Krogerus static int mux_fwnode_match(struct device *dev, const void *fwnode)
1823370db35SHeikki Krogerus {
1833370db35SHeikki Krogerus 	return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-mux");
1843370db35SHeikki Krogerus }
1853370db35SHeikki Krogerus 
186f5514c91SHeikki Krogerus static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id,
187f5514c91SHeikki Krogerus 			     void *data)
188bdecb33aSHeikki Krogerus {
18996a6d031SHeikki Krogerus 	const struct typec_altmode_desc *desc = data;
1903370db35SHeikki Krogerus 	struct device *dev;
19196a6d031SHeikki Krogerus 	bool match;
1923370db35SHeikki Krogerus 	int nval;
19396a6d031SHeikki Krogerus 	u16 *val;
19496a6d031SHeikki Krogerus 	int i;
195bdecb33aSHeikki Krogerus 
196bdecb33aSHeikki Krogerus 	/*
19796a6d031SHeikki Krogerus 	 * Check has the identifier already been "consumed". If it
19896a6d031SHeikki Krogerus 	 * has, no need to do any extra connection identification.
199bdecb33aSHeikki Krogerus 	 */
200f5514c91SHeikki Krogerus 	match = !id;
20196a6d031SHeikki Krogerus 	if (match)
20296a6d031SHeikki Krogerus 		goto find_mux;
20396a6d031SHeikki Krogerus 
20496a6d031SHeikki Krogerus 	/* Accessory Mode muxes */
20596a6d031SHeikki Krogerus 	if (!desc) {
206f5514c91SHeikki Krogerus 		match = fwnode_property_present(fwnode, "accessory");
20796a6d031SHeikki Krogerus 		if (match)
20896a6d031SHeikki Krogerus 			goto find_mux;
20996a6d031SHeikki Krogerus 		return NULL;
21096a6d031SHeikki Krogerus 	}
21196a6d031SHeikki Krogerus 
21296a6d031SHeikki Krogerus 	/* Alternate Mode muxes */
213f5514c91SHeikki Krogerus 	nval = fwnode_property_count_u16(fwnode, "svid");
21496a6d031SHeikki Krogerus 	if (nval <= 0)
21596a6d031SHeikki Krogerus 		return NULL;
21696a6d031SHeikki Krogerus 
21796a6d031SHeikki Krogerus 	val = kcalloc(nval, sizeof(*val), GFP_KERNEL);
21896a6d031SHeikki Krogerus 	if (!val)
21996a6d031SHeikki Krogerus 		return ERR_PTR(-ENOMEM);
22096a6d031SHeikki Krogerus 
221f5514c91SHeikki Krogerus 	nval = fwnode_property_read_u16_array(fwnode, "svid", val, nval);
22296a6d031SHeikki Krogerus 	if (nval < 0) {
22396a6d031SHeikki Krogerus 		kfree(val);
22496a6d031SHeikki Krogerus 		return ERR_PTR(nval);
22596a6d031SHeikki Krogerus 	}
22696a6d031SHeikki Krogerus 
22796a6d031SHeikki Krogerus 	for (i = 0; i < nval; i++) {
22896a6d031SHeikki Krogerus 		match = val[i] == desc->svid;
22996a6d031SHeikki Krogerus 		if (match) {
23096a6d031SHeikki Krogerus 			kfree(val);
23196a6d031SHeikki Krogerus 			goto find_mux;
23296a6d031SHeikki Krogerus 		}
23396a6d031SHeikki Krogerus 	}
23496a6d031SHeikki Krogerus 	kfree(val);
23596a6d031SHeikki Krogerus 	return NULL;
23696a6d031SHeikki Krogerus 
23796a6d031SHeikki Krogerus find_mux:
238f5514c91SHeikki Krogerus 	dev = class_find_device(&typec_mux_class, NULL, fwnode,
2393370db35SHeikki Krogerus 				mux_fwnode_match);
24096a6d031SHeikki Krogerus 
2413370db35SHeikki Krogerus 	return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
242bdecb33aSHeikki Krogerus }
243bdecb33aSHeikki Krogerus 
244bdecb33aSHeikki Krogerus /**
245d1c6a769SHeikki Krogerus  * fwnode_typec_mux_get - Find USB Type-C Multiplexer
246d1c6a769SHeikki Krogerus  * @fwnode: The caller device node
247540bfab7SHeikki Krogerus  * @desc: Alt Mode description
248bdecb33aSHeikki Krogerus  *
249bdecb33aSHeikki Krogerus  * Finds a mux linked to the caller. This function is primarily meant for the
250bdecb33aSHeikki Krogerus  * Type-C drivers. Returns a reference to the mux on success, NULL if no
251bdecb33aSHeikki Krogerus  * matching connection was found, or ERR_PTR(-EPROBE_DEFER) when a connection
252bdecb33aSHeikki Krogerus  * was found but the mux has not been enumerated yet.
253bdecb33aSHeikki Krogerus  */
254d1c6a769SHeikki Krogerus struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
255540bfab7SHeikki Krogerus 				       const struct typec_altmode_desc *desc)
256bdecb33aSHeikki Krogerus {
257bdecb33aSHeikki Krogerus 	struct typec_mux *mux;
258bdecb33aSHeikki Krogerus 
259d1c6a769SHeikki Krogerus 	mux = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc,
260540bfab7SHeikki Krogerus 					   typec_mux_match);
2613370db35SHeikki Krogerus 	if (!IS_ERR_OR_NULL(mux))
2623370db35SHeikki Krogerus 		WARN_ON(!try_module_get(mux->dev.parent->driver->owner));
263bdecb33aSHeikki Krogerus 
264bdecb33aSHeikki Krogerus 	return mux;
265bdecb33aSHeikki Krogerus }
266d1c6a769SHeikki Krogerus EXPORT_SYMBOL_GPL(fwnode_typec_mux_get);
267bdecb33aSHeikki Krogerus 
268bdecb33aSHeikki Krogerus /**
269bdecb33aSHeikki Krogerus  * typec_mux_put - Release handle to a Multiplexer
270bdecb33aSHeikki Krogerus  * @mux: USB Type-C Connector Multiplexer/DeMultiplexer
271bdecb33aSHeikki Krogerus  *
272bdecb33aSHeikki Krogerus  * Decrements reference count for @mux.
273bdecb33aSHeikki Krogerus  */
274bdecb33aSHeikki Krogerus void typec_mux_put(struct typec_mux *mux)
275bdecb33aSHeikki Krogerus {
2763e3b8196SHeikki Krogerus 	if (!IS_ERR_OR_NULL(mux)) {
2773370db35SHeikki Krogerus 		module_put(mux->dev.parent->driver->owner);
2783370db35SHeikki Krogerus 		put_device(&mux->dev);
279bdecb33aSHeikki Krogerus 	}
2803e3b8196SHeikki Krogerus }
281bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_put);
282bdecb33aSHeikki Krogerus 
283774a9df6SHeikki Krogerus int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
284774a9df6SHeikki Krogerus {
285774a9df6SHeikki Krogerus 	if (IS_ERR_OR_NULL(mux))
286774a9df6SHeikki Krogerus 		return 0;
287774a9df6SHeikki Krogerus 
288774a9df6SHeikki Krogerus 	return mux->set(mux, state);
289774a9df6SHeikki Krogerus }
290774a9df6SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_set);
291774a9df6SHeikki Krogerus 
2923370db35SHeikki Krogerus static void typec_mux_release(struct device *dev)
2933370db35SHeikki Krogerus {
2943370db35SHeikki Krogerus 	kfree(to_typec_mux(dev));
2953370db35SHeikki Krogerus }
2963370db35SHeikki Krogerus 
2973370db35SHeikki Krogerus static const struct device_type typec_mux_dev_type = {
2983370db35SHeikki Krogerus 	.name = "mode_switch",
2993370db35SHeikki Krogerus 	.release = typec_mux_release,
3003370db35SHeikki Krogerus };
3013370db35SHeikki Krogerus 
302bdecb33aSHeikki Krogerus /**
303bdecb33aSHeikki Krogerus  * typec_mux_register - Register Multiplexer routing USB Type-C pins
3043370db35SHeikki Krogerus  * @parent: Parent device
3053370db35SHeikki Krogerus  * @desc: Multiplexer description
306bdecb33aSHeikki Krogerus  *
307bdecb33aSHeikki Krogerus  * USB Type-C connectors can be used for alternate modes of operation besides
308bdecb33aSHeikki Krogerus  * USB when Accessory/Alternate Modes are supported. With some of those modes,
309bdecb33aSHeikki Krogerus  * the pins on the connector need to be reconfigured. This function registers
310bdecb33aSHeikki Krogerus  * multiplexer switches routing the pins on the connector.
311bdecb33aSHeikki Krogerus  */
3123370db35SHeikki Krogerus struct typec_mux *
3133370db35SHeikki Krogerus typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
314bdecb33aSHeikki Krogerus {
3153370db35SHeikki Krogerus 	struct typec_mux *mux;
3163370db35SHeikki Krogerus 	int ret;
317bdecb33aSHeikki Krogerus 
3183370db35SHeikki Krogerus 	if (!desc || !desc->set)
3193370db35SHeikki Krogerus 		return ERR_PTR(-EINVAL);
3203370db35SHeikki Krogerus 
3213370db35SHeikki Krogerus 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
3223370db35SHeikki Krogerus 	if (!mux)
3233370db35SHeikki Krogerus 		return ERR_PTR(-ENOMEM);
3243370db35SHeikki Krogerus 
3253370db35SHeikki Krogerus 	mux->set = desc->set;
3263370db35SHeikki Krogerus 
3273370db35SHeikki Krogerus 	device_initialize(&mux->dev);
3283370db35SHeikki Krogerus 	mux->dev.parent = parent;
3293370db35SHeikki Krogerus 	mux->dev.fwnode = desc->fwnode;
3303370db35SHeikki Krogerus 	mux->dev.class = &typec_mux_class;
3313370db35SHeikki Krogerus 	mux->dev.type = &typec_mux_dev_type;
3323370db35SHeikki Krogerus 	mux->dev.driver_data = desc->drvdata;
333ef441dd6SHeikki Krogerus 	dev_set_name(&mux->dev, "%s-mux",
334ef441dd6SHeikki Krogerus 		     desc->name ? desc->name : dev_name(parent));
3353370db35SHeikki Krogerus 
3363370db35SHeikki Krogerus 	ret = device_add(&mux->dev);
3373370db35SHeikki Krogerus 	if (ret) {
3383370db35SHeikki Krogerus 		dev_err(parent, "failed to register mux (%d)\n", ret);
3393370db35SHeikki Krogerus 		put_device(&mux->dev);
3403370db35SHeikki Krogerus 		return ERR_PTR(ret);
3413370db35SHeikki Krogerus 	}
3423370db35SHeikki Krogerus 
3433370db35SHeikki Krogerus 	return mux;
344bdecb33aSHeikki Krogerus }
345bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_register);
346bdecb33aSHeikki Krogerus 
347bdecb33aSHeikki Krogerus /**
348bdecb33aSHeikki Krogerus  * typec_mux_unregister - Unregister Multiplexer Switch
34974789aedSHeikki Krogerus  * @mux: USB Type-C Connector Multiplexer/DeMultiplexer
350bdecb33aSHeikki Krogerus  *
351bdecb33aSHeikki Krogerus  * Unregister mux that was registered with typec_mux_register().
352bdecb33aSHeikki Krogerus  */
353bdecb33aSHeikki Krogerus void typec_mux_unregister(struct typec_mux *mux)
354bdecb33aSHeikki Krogerus {
3553370db35SHeikki Krogerus 	if (!IS_ERR_OR_NULL(mux))
3563370db35SHeikki Krogerus 		device_unregister(&mux->dev);
357bdecb33aSHeikki Krogerus }
358bdecb33aSHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_unregister);
3593370db35SHeikki Krogerus 
3603370db35SHeikki Krogerus void typec_mux_set_drvdata(struct typec_mux *mux, void *data)
3613370db35SHeikki Krogerus {
3623370db35SHeikki Krogerus 	dev_set_drvdata(&mux->dev, data);
3633370db35SHeikki Krogerus }
3643370db35SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_set_drvdata);
3653370db35SHeikki Krogerus 
3663370db35SHeikki Krogerus void *typec_mux_get_drvdata(struct typec_mux *mux)
3673370db35SHeikki Krogerus {
3683370db35SHeikki Krogerus 	return dev_get_drvdata(&mux->dev);
3693370db35SHeikki Krogerus }
3703370db35SHeikki Krogerus EXPORT_SYMBOL_GPL(typec_mux_get_drvdata);
3713370db35SHeikki Krogerus 
3723370db35SHeikki Krogerus struct class typec_mux_class = {
3733370db35SHeikki Krogerus 	.name = "typec_mux",
3743370db35SHeikki Krogerus 	.owner = THIS_MODULE,
3753370db35SHeikki Krogerus };
376