From a2a05df5c5c45dce786b23d22700befddd0439ea Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 21 Nov 2019 11:22:20 +0100 Subject: usb: Add function to register otg dev We have two drivers in the tree which register an "otg" device to configure the host/peripheral switching. Before introducing a third driver create a common function for it. Signed-off-by: Sascha Hauer --- drivers/usb/otg/Kconfig | 4 +++ drivers/usb/otg/Makefile | 2 +- drivers/usb/otg/otgdev.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ include/usb/usb.h | 3 +++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/otg/otgdev.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2c9fb46e4d..2c094452b6 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -6,3 +6,7 @@ config USB_ULPI config USB_TWL4030 depends on MFD_TWL4030 bool "TWL4030 Transceiver support" + +config USB_OTGDEV + bool + diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 465a7f098c..49c2491e58 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_TWL4030) += twl4030.o - +obj-$(CONFIG_USB_OTGDEV) += otgdev.o diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c new file mode 100644 index 0000000000..7017796e8c --- /dev/null +++ b/drivers/usb/otg/otgdev.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +static int (*set_mode_callback)(void *ctx, enum usb_dr_mode mode); +static unsigned int otg_mode; + +static int otg_set_mode(struct param_d *param, void *ctx) +{ + static int cur_mode = USB_DR_MODE_OTG; + int ret; + + if (otg_mode == USB_DR_MODE_UNKNOWN) + return -EINVAL; + + if (otg_mode == cur_mode) + return 0; + + if (cur_mode != USB_DR_MODE_OTG) + return -EBUSY; + + ret = set_mode_callback(ctx, otg_mode); + if (ret) + return ret; + + cur_mode = otg_mode; + + return 0; +} + +static const char *otg_mode_names[] = { + [USB_DR_MODE_UNKNOWN] = "unknown", + [USB_DR_MODE_HOST] = "host", + [USB_DR_MODE_PERIPHERAL] = "peripheral", + [USB_DR_MODE_OTG] = "otg", +}; + +static struct device_d otg_device = { + .name = "otg", + .id = DEVICE_ID_SINGLE, +}; + +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx) +{ + int ret; + struct param_d *param_mode; + + if (otg_device.parent) + return -EBUSY; + + otg_device.parent = parent; + set_mode_callback = set_mode; + otg_mode = USB_DR_MODE_OTG; + + ret = register_device(&otg_device); + if (ret) + return ret; + + param_mode = dev_add_param_enum(&otg_device, "mode", + otg_set_mode, NULL, &otg_mode, + otg_mode_names, ARRAY_SIZE(otg_mode_names), ctx); + if (IS_ERR(param_mode)) + return PTR_ERR(param_mode); + + return 0; +} diff --git a/include/usb/usb.h b/include/usb/usb.h index 0045608d64..d39de71aff 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -444,6 +444,9 @@ enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, const char *propname); +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx); + extern struct list_head usb_device_list; #endif /*_USB_H_ */ -- cgit v1.2.3