* [v3 PATCH 0/6] add USB Type-B GPIO connector driver
@ 2019-04-03 2:09 Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 1/6] dt-bindings: connector: add optional properties for Type-B Chunfeng Yun
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Because the USB Connector is introduced and the requirement of
usb-connector.txt binding, the old way using extcon to support
USB Dual-Role switch is now deprecated, meanwhile there is no
available common driver when use Type-B connector, typically
using an input GPIO to detect USB ID pin.
This patch series introduce a Type-B GPIO connector driver and try
to replace the function provided by extcon-usb-gpio driver.
v3 changes:
1. add GPIO direction, and use fixed-regulator for GPIO controlled
VBUS regulator suggested by Rob;
2. rebuild fwnode_usb_role_switch_get() suggested by Andy and Heikki
3. treat the type-B connector as a virtual device;
4. change file name of driver again
5. select USB_ROLE_SWITCH in mtu3/Kconfig suggested by Heikki
6. rename ssusb_mode_manual_switch() to ssusb_mode_switch()
v2 changes:
1. make binding clear, and add a extra compatible suggested by Hans
Chunfeng Yun (6):
dt-bindings: connector: add optional properties for Type-B
dt-bindings: usb: add binding for Type-B GPIO connector driver
dt-bindings: usb: mtu3: add properties about USB Role Switch
usb: roles: add API to get usb_role_switch by node
usb: roles: add USB Type-B GPIO connector driver
usb: mtu3: register a USB Role Switch for dual role mode
.../bindings/connector/usb-connector.txt | 14 +
.../devicetree/bindings/usb/mediatek,mtu3.txt | 10 +-
.../bindings/usb/typeb-conn-gpio.txt | 49 +++
drivers/usb/mtu3/Kconfig | 1 +
drivers/usb/mtu3/mtu3.h | 5 +
drivers/usb/mtu3/mtu3_debugfs.c | 4 +-
drivers/usb/mtu3/mtu3_dr.c | 47 ++-
drivers/usb/mtu3/mtu3_dr.h | 6 +-
drivers/usb/mtu3/mtu3_plat.c | 3 +-
drivers/usb/roles/Kconfig | 11 +
drivers/usb/roles/Makefile | 1 +
drivers/usb/roles/class.c | 31 ++
drivers/usb/roles/typeb-conn-gpio.c | 301 ++++++++++++++++++
include/linux/usb/role.h | 2 +
14 files changed, 476 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
create mode 100644 drivers/usb/roles/typeb-conn-gpio.c
--
2.20.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [v3 PATCH 1/6] dt-bindings: connector: add optional properties for Type-B
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver Chunfeng Yun
` (4 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
usb-b-connector
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3 changes:
1. add GPIO direction, and use fixed-regulator for GPIO controlled
VBUS regulator suggested by Rob;
v2 changes:
1. describe more clear for vbus-gpios and vbus-supply suggested by Hans
---
.../bindings/connector/usb-connector.txt | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt
index a9a2f2fc44f2..e8f9e854fd11 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.txt
+++ b/Documentation/devicetree/bindings/connector/usb-connector.txt
@@ -17,6 +17,20 @@ Optional properties:
- self-powered: Set this property if the usb device that has its own power
source.
+Optional properties for usb-b-connector:
+- id-gpios: an input gpio for USB ID pin.
+- vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of
+ VBUS 5V.
+ see gpio/gpio.txt.
+- vbus-supply: a phandle to the regulator for USB VBUS if needed when host
+ mode or dual role mode is supported.
+ Particularly, if use an output GPIO to control a VBUS regulator, should
+ model it as a regulator.
+ see regulator/fixed-regulator.yaml
+- pinctrl-names : a pinctrl state named "default" is optional
+- pinctrl-0 : pin control group
+ see pinctrl/pinctrl-bindings.txt
+
Optional properties for usb-c-connector:
- power-role: should be one of "source", "sink" or "dual"(DRP) if typec
connector has power support.
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [v3 PATCH 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 1/6] dt-bindings: connector: add optional properties for Type-B Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch Chunfeng Yun
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
It's used to support dual role switch via GPIO when use Type-B
receptacle, typically the USB ID pin is connected to an input
GPIO pin
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3 changes:
1. treat type-B connector as a virtual device, but not child device of
USB controller's
v2 changes:
1. new patch to make binding clear suggested by Hans
---
.../bindings/usb/typeb-conn-gpio.txt | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
diff --git a/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
new file mode 100644
index 000000000000..d2e1c4e01b6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
@@ -0,0 +1,49 @@
+USB Type-B GPIO Connector
+
+This is a virtual device used to switch dual role mode from the USB ID pin
+connected to an input GPIO pin.
+
+Required properties:
+- compatible : Should be "linux,typeb-conn-gpio"
+
+Sub-nodes:
+- connector : should be present.
+ - compatible : should be "usb-b-connector".
+ - id-gpios, vbus-gpios : either one of them must be present,
+ and both can be present as well.
+ - vbus-supply : can be present if needed when supports dual role mode.
+ see connector/usb-connector.txt
+
+- port : should be present.
+ see graph.txt
+
+Example:
+
+rsw_iddig: role_sw_iddig {
+ compatible = "linux,typeb-conn-gpio";
+ status = "okay";
+
+ connector {
+ compatible = "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
+ vbus-supply = <&usb_p0_vbus>;
+ };
+
+ port {
+ bconn_ep: endpoint@0 {
+ remote-endpoint = <&usb_role_sw>;
+ };
+ };
+};
+
+&mtu3 {
+ status = "okay";
+
+ port {
+ usb_role_sw: endpoint@0 {
+ remote-endpoint = <&bconn_ep>;
+ };
+ };
+};
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [v3 PATCH 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 1/6] dt-bindings: connector: add optional properties for Type-B Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node Chunfeng Yun
` (2 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Now the USB Role Switch is supported, so add properties about it
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3: no changes
v2 changes:
1. fix typo
2. refer new binding about connector property
---
.../devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index 3382b5cb471d..6e004c4a89af 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -27,7 +27,9 @@ Optional properties:
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
- extcon : external connector for vbus and idpin changes detection, needed
- when supports dual-role mode.
+ when supports dual-role mode; it's consiedered valid for compatibility
+ reasons, and not allowed for new bindings, use the property
+ usb-role-switch instead.
- vbus-supply : reference to the VBUS regulator, needed when supports
dual-role mode.
- pinctrl-names : a pinctrl state named "default" is optional, and need be
@@ -36,7 +38,8 @@ Optional properties:
is not set.
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
-
+ - usb-role-switch : use USB Role Switch to support dual-role switch, but
+ not extcon
- maximum-speed : valid arguments are "super-speed", "high-speed" and
"full-speed"; refer to usb/generic.txt
- enable-manual-drd : supports manual dual-role switch via debugfs; usually
@@ -61,6 +64,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example
if host mode is enabled. The DT binding details of xhci can be found in:
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+The port would be added as subnode if use usb-role-switch property
+ see graph.txt
+
Example:
ssusb: usb@11271000 {
compatible = "mediatek,mt8173-mtu3";
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
` (2 preceding siblings ...)
2019-04-03 2:09 ` [v3 PATCH 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-10 10:22 ` Heikki Krogerus
2019-04-03 2:09 ` [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode Chunfeng Yun
5 siblings, 1 reply; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Add fwnode_usb_role_switch_get() to make easier to get
usb_role_switch by fwnode which register it.
It's useful when there is not device_connection registered
between two drivers and only knows the fwnode which register
usb_role_switch.
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3 changes:
1. use fwnodes instead of node suggested by Andy
2. rebuild the API suggested by Heikki
v2 no changes
---
drivers/usb/roles/class.c | 31 +++++++++++++++++++++++++++++++
include/linux/usb/role.h | 2 ++
2 files changed, 33 insertions(+)
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index f45d8df5cfb8..5ecb57f8960b 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/slab.h>
static struct class *role_class;
@@ -135,6 +136,36 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
}
EXPORT_SYMBOL_GPL(usb_role_switch_get);
+static int __switch_match_fwnode(struct device *dev, const void *fwnode)
+{
+ return dev_fwnode(dev->parent) == (const struct fwnode_handle *)fwnode;
+}
+
+/**
+ * fwnode_usb_role_switch_get - Find USB role switch by it's parent fwnode
+ * @fwnode: The fwnode that register USB role switch
+ *
+ * Finds and returns role switch registered by @fwnode. The reference count
+ * for the found switch is incremented.
+ */
+struct usb_role_switch *
+fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
+{
+ struct usb_role_switch *sw;
+ struct device *dev;
+
+ dev = class_find_device(role_class, NULL, fwnode,
+ __switch_match_fwnode);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ sw = to_role_switch(dev);
+ WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
+
+ return sw;
+}
+EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
+
/**
* usb_role_switch_put - Release handle to a switch
* @sw: USB Role Switch
diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h
index c05ffa6abda9..d21cd55d9e45 100644
--- a/include/linux/usb/role.h
+++ b/include/linux/usb/role.h
@@ -46,6 +46,8 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role);
enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw);
struct usb_role_switch *usb_role_switch_get(struct device *dev);
void usb_role_switch_put(struct usb_role_switch *sw);
+struct usb_role_switch *
+fwnode_usb_role_switch_get(struct fwnode_handle *fwnode);
struct usb_role_switch *
usb_role_switch_register(struct device *parent,
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
` (3 preceding siblings ...)
2019-04-03 2:09 ` [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-04 16:35 ` Linus Walleij
2019-04-03 2:09 ` [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode Chunfeng Yun
5 siblings, 1 reply; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Due to the requirement of usb-connector.txt binding, the old way
using extcon to support USB Dual-Role switch is now deprecated
when use Type-B connector.
This patch introduces a driver of Type-B connector which typically
uses an input GPIO to detect USB ID pin, and try to replace the
function provided by extcon-usb-gpio driver
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3 changes:
1. treat bype-B connector as a virtual device;
2. change file name again
v2 changes:
1. file name is changed
2. use new compatible
---
drivers/usb/roles/Kconfig | 11 +
drivers/usb/roles/Makefile | 1 +
drivers/usb/roles/typeb-conn-gpio.c | 301 ++++++++++++++++++++++++++++
3 files changed, 313 insertions(+)
create mode 100644 drivers/usb/roles/typeb-conn-gpio.c
diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig
index f8b31aa67526..d1156e18a81a 100644
--- a/drivers/usb/roles/Kconfig
+++ b/drivers/usb/roles/Kconfig
@@ -26,4 +26,15 @@ config USB_ROLES_INTEL_XHCI
To compile the driver as a module, choose M here: the module will
be called intel-xhci-usb-role-switch.
+config TYPEB_CONN_GPIO
+ tristate "USB Type-B GPIO Connector"
+ depends on GPIOLIB
+ help
+ The driver supports USB role switch between host and device via GPIO
+ based USB cable detection, used typically if an input GPIO is used
+ to detect USB ID pin.
+
+ To compile the driver as a module, choose M here: the module will
+ be called typeb-conn-gpio.ko
+
endif # USB_ROLE_SWITCH
diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile
index 757a7d2797eb..5d5620d9d113 100644
--- a/drivers/usb/roles/Makefile
+++ b/drivers/usb/roles/Makefile
@@ -3,3 +3,4 @@
obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o
roles-y := class.o
obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o
+obj-$(CONFIG_TYPEB_CONN_GPIO) += typeb-conn-gpio.o
diff --git a/drivers/usb/roles/typeb-conn-gpio.c b/drivers/usb/roles/typeb-conn-gpio.c
new file mode 100644
index 000000000000..83804141ab9e
--- /dev/null
+++ b/drivers/usb/roles/typeb-conn-gpio.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-B GPIO Connector Driver
+ *
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
+ */
+
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/role.h>
+
+#define USB_GPIO_DEB_MS 20 /* ms */
+#define USB_GPIO_DEB_US ((USB_GPIO_DEB_MS) * 1000) /* us */
+
+#define USB_CONN_IRQF \
+ (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT)
+
+struct usb_conn_info {
+ struct device *dev;
+ struct usb_role_switch *role_sw;
+ enum usb_role last_role;
+ struct regulator *vbus;
+ struct delayed_work dw_det;
+ unsigned long debounce_jiffies;
+
+ struct gpio_desc *id_gpiod;
+ struct gpio_desc *vbus_gpiod;
+ int id_irq;
+ int vbus_irq;
+};
+
+/**
+ * "DEVICE" = VBUS and "HOST" = !ID, so we have:
+ * Both "DEVICE" and "HOST" can't be set as active at the same time
+ * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive
+ * even if VBUS is on.
+ *
+ * Role | ID | VBUS
+ * ------------------------------------
+ * [1] DEVICE | H | H
+ * [2] NONE | H | L
+ * [3] HOST | L | H
+ * [4] HOST | L | L
+ *
+ * In case we have only one of these signals:
+ * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1
+ * - ID only - we want to distinguish between [1] and [4], so VBUS = ID
+ */
+static void usb_conn_detect_cable(struct work_struct *work)
+{
+ struct usb_conn_info *info;
+ enum usb_role role;
+ int id, vbus, ret;
+
+ info = container_of(to_delayed_work(work),
+ struct usb_conn_info, dw_det);
+
+ /* check ID and VBUS */
+ id = info->id_gpiod ?
+ gpiod_get_value_cansleep(info->id_gpiod) : 1;
+ vbus = info->vbus_gpiod ?
+ gpiod_get_value_cansleep(info->vbus_gpiod) : id;
+
+ if (!id)
+ role = USB_ROLE_HOST;
+ else if (vbus)
+ role = USB_ROLE_DEVICE;
+ else
+ role = USB_ROLE_NONE;
+
+ dev_dbg(info->dev, "role %d/%d, gpios: id %d, vbus %d\n",
+ info->last_role, role, id, vbus);
+
+ if (info->last_role == role) {
+ dev_warn(info->dev, "repeated role: %d\n", role);
+ return;
+ }
+
+ if (info->last_role == USB_ROLE_HOST)
+ regulator_disable(info->vbus);
+
+ ret = usb_role_switch_set_role(info->role_sw, role);
+ if (ret)
+ dev_err(info->dev, "failed to set role: %d\n", ret);
+
+ if (role == USB_ROLE_HOST) {
+ ret = regulator_enable(info->vbus);
+ if (ret)
+ dev_err(info->dev, "enable vbus regulator failed\n");
+ }
+
+ info->last_role = role;
+
+ dev_dbg(info->dev, "vbus regulator is %s\n",
+ regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
+}
+
+static void usb_conn_queue_dwork(struct usb_conn_info *info,
+ unsigned long delay)
+{
+ queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
+}
+
+static irqreturn_t usb_conn_isr(int irq, void *dev_id)
+{
+ struct usb_conn_info *info = dev_id;
+
+ usb_conn_queue_dwork(info, info->debounce_jiffies);
+
+ return IRQ_HANDLED;
+}
+
+static int usb_conn_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *parent;
+ struct device_node *child;
+ struct usb_conn_info *info;
+ int ret = 0;
+
+ if (!np)
+ return -EINVAL;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = dev;
+
+ child = of_get_child_by_name(np, "connector");
+ if (!child) {
+ dev_err(dev, "failed to find connector node\n");
+ return -ENODEV;
+ }
+
+ info->id_gpiod = devm_gpiod_get_from_of_node(
+ dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
+ if (IS_ERR(info->id_gpiod))
+ return PTR_ERR(info->id_gpiod);
+
+ info->vbus_gpiod = devm_gpiod_get_from_of_node(
+ dev, child, "vbus-gpios", 0, GPIOD_IN,
+ "vbuspin");
+ if (IS_ERR(info->vbus_gpiod))
+ return PTR_ERR(info->vbus_gpiod);
+
+ if (!info->id_gpiod && !info->vbus_gpiod) {
+ dev_err(dev, "failed to get gpios\n");
+ return -ENODEV;
+ }
+
+ of_node_put(child);
+
+ if (info->id_gpiod)
+ ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
+ if (!ret && info->vbus_gpiod)
+ ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
+ if (ret < 0)
+ info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
+
+ INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
+
+ info->vbus = devm_regulator_get(dev, "vbus");
+ if (IS_ERR(info->vbus)) {
+ dev_err(dev, "failed to get vbus\n");
+ return PTR_ERR(info->vbus);
+ }
+
+ child = of_graph_get_endpoint_by_regs(np, -1, 0);
+ parent = of_graph_get_remote_port_parent(child);
+ info->role_sw = fwnode_usb_role_switch_get(of_fwnode_handle(parent));
+ if (IS_ERR_OR_NULL(info->role_sw)) {
+ dev_err(dev, "failed to get role switch\n");
+ return PTR_ERR(info->role_sw);
+ }
+
+ of_node_put(child);
+ of_node_put(parent);
+
+ if (info->id_gpiod) {
+ info->id_irq = gpiod_to_irq(info->id_gpiod);
+ if (info->id_irq < 0) {
+ dev_err(dev, "failed to get ID IRQ\n");
+ return info->id_irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+ usb_conn_isr, USB_CONN_IRQF,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request ID IRQ\n");
+ return ret;
+ }
+ }
+
+ if (info->vbus_gpiod) {
+ info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+ if (info->vbus_irq < 0) {
+ dev_err(dev, "failed to get VBUS IRQ\n");
+ return info->vbus_irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+ usb_conn_isr, USB_CONN_IRQF,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request VBUS IRQ\n");
+ return ret;
+ }
+ }
+
+ platform_set_drvdata(pdev, info);
+
+ /* Perform initial detection */
+ usb_conn_queue_dwork(info, 0);
+
+ return 0;
+}
+
+static int usb_conn_remove(struct platform_device *pdev)
+{
+ struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&info->dw_det);
+
+ if (info->last_role == USB_ROLE_HOST)
+ regulator_disable(info->vbus);
+
+ usb_role_switch_put(info->role_sw);
+
+ return 0;
+}
+
+static int __maybe_unused usb_conn_suspend(struct device *dev)
+{
+ struct usb_conn_info *info = dev_get_drvdata(dev);
+
+ if (info->id_gpiod)
+ disable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ disable_irq(info->vbus_irq);
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int __maybe_unused usb_conn_resume(struct device *dev)
+{
+ struct usb_conn_info *info = dev_get_drvdata(dev);
+
+ pinctrl_pm_select_default_state(dev);
+
+ if (info->id_gpiod)
+ enable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ enable_irq(info->vbus_irq);
+
+ usb_conn_queue_dwork(info, 0);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
+ usb_conn_suspend, usb_conn_resume);
+
+#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &usb_conn_pm_ops : NULL)
+
+static const struct of_device_id usb_conn_dt_match[] = {
+ { .compatible = "linux,typeb-conn-gpio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
+
+static struct platform_driver usb_conn_driver = {
+ .probe = usb_conn_probe,
+ .remove = usb_conn_remove,
+ .driver = {
+ .name = "typeb-conn-gpio",
+ .pm = DEV_PMS_OPS,
+ .of_match_table = usb_conn_dt_match,
+ },
+};
+
+module_platform_driver(usb_conn_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
+MODULE_LICENSE("GPL v2");
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
` (4 preceding siblings ...)
2019-04-03 2:09 ` [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver Chunfeng Yun
@ 2019-04-03 2:09 ` Chunfeng Yun
2019-04-10 10:24 ` Heikki Krogerus
5 siblings, 1 reply; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-03 2:09 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
Min Guo, Alan Stern, devicetree, linux-kernel, linux-usb,
linux-arm-kernel, linux-mediatek
Because extcon is not allowed for new bindings, and the
dual role switch is supported by USB Role Switch,
especially for Type-C drivers, so register a USB Role
Switch to support the new way
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v3 changes:
1. select USB_ROLE_SWITCH in Kconfig suggested by Heikki
2. rename ssusb_mode_manual_switch() to ssusb_mode_switch()
v2 no change
---
drivers/usb/mtu3/Kconfig | 1 +
drivers/usb/mtu3/mtu3.h | 5 ++++
drivers/usb/mtu3/mtu3_debugfs.c | 4 +--
drivers/usb/mtu3/mtu3_dr.c | 47 ++++++++++++++++++++++++++++++++-
drivers/usb/mtu3/mtu3_dr.h | 6 ++---
drivers/usb/mtu3/mtu3_plat.c | 3 ++-
6 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index bcc23486c4ed..88e3db7b3016 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -43,6 +43,7 @@ config USB_MTU3_DUAL_ROLE
bool "Dual Role mode"
depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3))
depends on (EXTCON=y || EXTCON=USB_MTU3)
+ select USB_ROLE_SWITCH
help
This is the default mode of working of MTU3 controller where
both host and gadget features are enabled.
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 76ecf12fdf62..6087be236a35 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -199,6 +199,9 @@ struct mtu3_gpd_ring {
* @id_nb : notifier for iddig(idpin) detection
* @id_work : work of iddig detection notifier
* @id_event : event of iddig detecion notifier
+* @role_sw : use USB Role Switch to support dual-role switch, can't use
+* extcon at the same time, and extcon is deprecated.
+* @role_sw_used : true when the USB Role Switch is used.
* @is_u3_drd: whether port0 supports usb3.0 dual-role device or not
* @manual_drd_enabled: it's true when supports dual-role device by debugfs
* to switch host/device modes depending on user input.
@@ -212,6 +215,8 @@ struct otg_switch_mtk {
struct notifier_block id_nb;
struct work_struct id_work;
unsigned long id_event;
+ struct usb_role_switch *role_sw;
+ bool role_sw_used;
bool is_u3_drd;
bool manual_drd_enabled;
};
diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c
index 62c57ddc554e..c96e5dab0a48 100644
--- a/drivers/usb/mtu3/mtu3_debugfs.c
+++ b/drivers/usb/mtu3/mtu3_debugfs.c
@@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf,
return -EFAULT;
if (!strncmp(buf, "host", 4) && !ssusb->is_host) {
- ssusb_mode_manual_switch(ssusb, 1);
+ ssusb_mode_switch(ssusb, 1);
} else if (!strncmp(buf, "device", 6) && ssusb->is_host) {
- ssusb_mode_manual_switch(ssusb, 0);
+ ssusb_mode_switch(ssusb, 0);
} else {
dev_err(ssusb->dev, "wrong or duplicated setting\n");
return -EINVAL;
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c
index 5fcb71af875a..5f20141dd57f 100644
--- a/drivers/usb/mtu3/mtu3_dr.c
+++ b/drivers/usb/mtu3/mtu3_dr.c
@@ -7,6 +7,8 @@
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
*/
+#include <linux/usb/role.h>
+
#include "mtu3.h"
#include "mtu3_dr.h"
#include "mtu3_debug.h"
@@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx)
* This is useful in special cases, such as uses TYPE-A receptacle but also
* wants to support dual-role mode.
*/
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
{
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
@@ -318,6 +320,46 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
}
+static int ssusb_role_sw_set(struct device *dev, enum usb_role role)
+{
+ struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
+ bool to_host = false;
+
+ if (role == USB_ROLE_HOST)
+ to_host = true;
+
+ if (to_host ^ ssusb->is_host)
+ ssusb_mode_switch(ssusb, to_host);
+
+ return 0;
+}
+
+static enum usb_role ssusb_role_sw_get(struct device *dev)
+{
+ struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
+ enum usb_role role;
+
+ role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
+
+ return role;
+}
+
+static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
+{
+ struct usb_role_switch_desc role_sx_desc = { 0 };
+ struct ssusb_mtk *ssusb =
+ container_of(otg_sx, struct ssusb_mtk, otg_switch);
+
+ if (!otg_sx->role_sw_used)
+ return 0;
+
+ role_sx_desc.set = ssusb_role_sw_set;
+ role_sx_desc.get = ssusb_role_sw_get;
+ otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc);
+
+ return PTR_ERR_OR_ZERO(otg_sx->role_sw);
+}
+
int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
{
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
@@ -328,6 +370,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
if (otg_sx->manual_drd_enabled)
ssusb_dr_debugfs_init(ssusb);
+ else if (otg_sx->role_sw_used)
+ ret = ssusb_role_sw_register(otg_sx);
else
ret = ssusb_extcon_register(otg_sx);
@@ -340,4 +384,5 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
cancel_work_sync(&otg_sx->id_work);
cancel_work_sync(&otg_sx->vbus_work);
+ usb_role_switch_unregister(otg_sx->role_sw);
}
diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ba6fe357ce29..5e58c4dbd54a 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
#if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host);
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host);
int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
enum mtu3_dr_force_mode mode);
@@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
{}
-static inline void
-ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {}
+static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
+{}
static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
{
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index fd0f6c5dfbc1..9c256ea3cdf5 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
otg_sx->manual_drd_enabled =
of_property_read_bool(node, "enable-manual-drd");
+ otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
- if (of_property_read_bool(node, "extcon")) {
+ if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
if (IS_ERR(otg_sx->edev)) {
dev_err(ssusb->dev, "couldn't get extcon device\n");
--
2.20.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver
2019-04-03 2:09 ` [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver Chunfeng Yun
@ 2019-04-04 16:35 ` Linus Walleij
2019-04-08 8:14 ` Chunfeng Yun
0 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2019-04-04 16:35 UTC (permalink / raw)
To: Chunfeng Yun
Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
Hans de Goede, Andy Shevchenko, Min Guo, Alan Stern,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel, linux-usb, Linux ARM,
moderated list:ARM/Mediatek SoC support
On Wed, Apr 3, 2019 at 9:09 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
> Due to the requirement of usb-connector.txt binding, the old way
> using extcon to support USB Dual-Role switch is now deprecated
> when use Type-B connector.
> This patch introduces a driver of Type-B connector which typically
> uses an input GPIO to detect USB ID pin, and try to replace the
> function provided by extcon-usb-gpio driver
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
(...)
> +#include <linux/gpio.h>
If you need this include in a consumer, something is wrong. Just delete it,
> + info->id_gpiod = devm_gpiod_get_from_of_node(
> + dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
This is OK if the child does not have any Linux device (struct platform_device
etc) created from it. Is this the case?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver
2019-04-04 16:35 ` Linus Walleij
@ 2019-04-08 8:14 ` Chunfeng Yun
0 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-08 8:14 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
Hans de Goede, Andy Shevchenko, Min Guo, Alan Stern,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel, linux-usb, Linux ARM,
moderated list:ARM/Mediatek SoC support
Hi,
On Thu, 2019-04-04 at 23:35 +0700, Linus Walleij wrote:
> On Wed, Apr 3, 2019 at 9:09 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> > Due to the requirement of usb-connector.txt binding, the old way
> > using extcon to support USB Dual-Role switch is now deprecated
> > when use Type-B connector.
> > This patch introduces a driver of Type-B connector which typically
> > uses an input GPIO to detect USB ID pin, and try to replace the
> > function provided by extcon-usb-gpio driver
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> (...)
> > +#include <linux/gpio.h>
>
> If you need this include in a consumer, something is wrong. Just delete it,
Ok
>
> > + info->id_gpiod = devm_gpiod_get_from_of_node(
> > + dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
>
> This is OK if the child does not have any Linux device (struct platform_device
> etc) created from it. Is this the case?
Yes, it is.
Thanks
>
> Yours,
> Linus Walleij
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node
2019-04-03 2:09 ` [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node Chunfeng Yun
@ 2019-04-10 10:22 ` Heikki Krogerus
2019-04-11 3:11 ` Chunfeng Yun
0 siblings, 1 reply; 13+ messages in thread
From: Heikki Krogerus @ 2019-04-10 10:22 UTC (permalink / raw)
To: Chunfeng Yun
Cc: Rob Herring, Greg Kroah-Hartman, Mark Rutland, Matthias Brugger,
Adam Thomson, Li Jun, Badhri Jagan Sridharan, Hans de Goede,
Andy Shevchenko, Min Guo, Alan Stern, devicetree, linux-kernel,
linux-usb, linux-arm-kernel, linux-mediatek
On Wed, Apr 03, 2019 at 10:09:12AM +0800, Chunfeng Yun wrote:
> Add fwnode_usb_role_switch_get() to make easier to get
> usb_role_switch by fwnode which register it.
> It's useful when there is not device_connection registered
> between two drivers and only knows the fwnode which register
> usb_role_switch.
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> v3 changes:
> 1. use fwnodes instead of node suggested by Andy
> 2. rebuild the API suggested by Heikki
>
> v2 no changes
> ---
> drivers/usb/roles/class.c | 31 +++++++++++++++++++++++++++++++
> include/linux/usb/role.h | 2 ++
> 2 files changed, 33 insertions(+)
>
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
> index f45d8df5cfb8..5ecb57f8960b 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -12,6 +12,7 @@
> #include <linux/device.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/of.h>
> #include <linux/slab.h>
>
> static struct class *role_class;
> @@ -135,6 +136,36 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(usb_role_switch_get);
>
> +static int __switch_match_fwnode(struct device *dev, const void *fwnode)
> +{
> + return dev_fwnode(dev->parent) == (const struct fwnode_handle *)fwnode;
> +}
I don't think this is actually needed. Why not just assign the
parent's fwnode for the mux as well?
I'll add an example to the patch 6/6 in this series.
> +/**
> + * fwnode_usb_role_switch_get - Find USB role switch by it's parent fwnode
> + * @fwnode: The fwnode that register USB role switch
> + *
> + * Finds and returns role switch registered by @fwnode. The reference count
> + * for the found switch is incremented.
> + */
> +struct usb_role_switch *
> +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
> +{
> + struct usb_role_switch *sw;
> + struct device *dev;
> +
> + dev = class_find_device(role_class, NULL, fwnode,
> + __switch_match_fwnode);
So here you can then reuse switch_fwnode_match():
dev = class_find_device(role_class, NULL, fwnode, switch_fwnode_match);
> + if (!dev)
> + return ERR_PTR(-EPROBE_DEFER);
> +
> + sw = to_role_switch(dev);
> + WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
> +
> + return sw;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
> +
> /**
> * usb_role_switch_put - Release handle to a switch
> * @sw: USB Role Switch
> diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h
> index c05ffa6abda9..d21cd55d9e45 100644
> --- a/include/linux/usb/role.h
> +++ b/include/linux/usb/role.h
> @@ -46,6 +46,8 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role);
> enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw);
> struct usb_role_switch *usb_role_switch_get(struct device *dev);
> void usb_role_switch_put(struct usb_role_switch *sw);
> +struct usb_role_switch *
> +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode);
>
> struct usb_role_switch *
> usb_role_switch_register(struct device *parent,
> --
> 2.20.1
thanks,
--
heikki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode
2019-04-03 2:09 ` [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode Chunfeng Yun
@ 2019-04-10 10:24 ` Heikki Krogerus
2019-04-11 1:05 ` Chunfeng Yun
0 siblings, 1 reply; 13+ messages in thread
From: Heikki Krogerus @ 2019-04-10 10:24 UTC (permalink / raw)
To: Chunfeng Yun
Cc: Rob Herring, Greg Kroah-Hartman, Mark Rutland, Matthias Brugger,
Adam Thomson, Li Jun, Badhri Jagan Sridharan, Hans de Goede,
Andy Shevchenko, Min Guo, Alan Stern, devicetree, linux-kernel,
linux-usb, linux-arm-kernel, linux-mediatek
On Wed, Apr 03, 2019 at 10:09:14AM +0800, Chunfeng Yun wrote:
> +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
> +{
> + struct usb_role_switch_desc role_sx_desc = { 0 };
> + struct ssusb_mtk *ssusb =
> + container_of(otg_sx, struct ssusb_mtk, otg_switch);
> +
> + if (!otg_sx->role_sw_used)
> + return 0;
> +
> + role_sx_desc.set = ssusb_role_sw_set;
> + role_sx_desc.get = ssusb_role_sw_get;
role_sw_desc.fwnode = dev_fwnode(ssusb->dev);
> + otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc);
> +
> + return PTR_ERR_OR_ZERO(otg_sx->role_sw);
> +}
thanks,
--
heikki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode
2019-04-10 10:24 ` Heikki Krogerus
@ 2019-04-11 1:05 ` Chunfeng Yun
0 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-11 1:05 UTC (permalink / raw)
To: Heikki Krogerus
Cc: Rob Herring, Greg Kroah-Hartman, Mark Rutland, Matthias Brugger,
Adam Thomson, Li Jun, Badhri Jagan Sridharan, Hans de Goede,
Andy Shevchenko, Min Guo, Alan Stern, devicetree, linux-kernel,
linux-usb, linux-arm-kernel, linux-mediatek
On Wed, 2019-04-10 at 13:24 +0300, Heikki Krogerus wrote:
> On Wed, Apr 03, 2019 at 10:09:14AM +0800, Chunfeng Yun wrote:
> > +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
> > +{
> > + struct usb_role_switch_desc role_sx_desc = { 0 };
> > + struct ssusb_mtk *ssusb =
> > + container_of(otg_sx, struct ssusb_mtk, otg_switch);
> > +
> > + if (!otg_sx->role_sw_used)
> > + return 0;
> > +
> > + role_sx_desc.set = ssusb_role_sw_set;
> > + role_sx_desc.get = ssusb_role_sw_get;
>
> role_sw_desc.fwnode = dev_fwnode(ssusb->dev);
Ok, thanks
>
> > + otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc);
> > +
> > + return PTR_ERR_OR_ZERO(otg_sx->role_sw);
> > +}
>
> thanks,
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node
2019-04-10 10:22 ` Heikki Krogerus
@ 2019-04-11 3:11 ` Chunfeng Yun
0 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun @ 2019-04-11 3:11 UTC (permalink / raw)
To: Heikki Krogerus
Cc: Rob Herring, Greg Kroah-Hartman, Mark Rutland, Matthias Brugger,
Adam Thomson, Li Jun, Badhri Jagan Sridharan, Hans de Goede,
Andy Shevchenko, Min Guo, Alan Stern, devicetree, linux-kernel,
linux-usb, linux-arm-kernel, linux-mediatek
On Wed, 2019-04-10 at 13:22 +0300, Heikki Krogerus wrote:
> On Wed, Apr 03, 2019 at 10:09:12AM +0800, Chunfeng Yun wrote:
> > Add fwnode_usb_role_switch_get() to make easier to get
> > usb_role_switch by fwnode which register it.
> > It's useful when there is not device_connection registered
> > between two drivers and only knows the fwnode which register
> > usb_role_switch.
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > v3 changes:
> > 1. use fwnodes instead of node suggested by Andy
> > 2. rebuild the API suggested by Heikki
> >
> > v2 no changes
> > ---
> > drivers/usb/roles/class.c | 31 +++++++++++++++++++++++++++++++
> > include/linux/usb/role.h | 2 ++
> > 2 files changed, 33 insertions(+)
> >
> > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
> > index f45d8df5cfb8..5ecb57f8960b 100644
> > --- a/drivers/usb/roles/class.c
> > +++ b/drivers/usb/roles/class.c
> > @@ -12,6 +12,7 @@
> > #include <linux/device.h>
> > #include <linux/module.h>
> > #include <linux/mutex.h>
> > +#include <linux/of.h>
> > #include <linux/slab.h>
> >
> > static struct class *role_class;
> > @@ -135,6 +136,36 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
> > }
> > EXPORT_SYMBOL_GPL(usb_role_switch_get);
> >
> > +static int __switch_match_fwnode(struct device *dev, const void *fwnode)
> > +{
> > + return dev_fwnode(dev->parent) == (const struct fwnode_handle *)fwnode;
> > +}
>
> I don't think this is actually needed.
Yes, you are right
> Why not just assign the
> parent's fwnode for the mux as well?
will do it in next version
>
> I'll add an example to the patch 6/6 in this series.
>
> > +/**
> > + * fwnode_usb_role_switch_get - Find USB role switch by it's parent fwnode
> > + * @fwnode: The fwnode that register USB role switch
> > + *
> > + * Finds and returns role switch registered by @fwnode. The reference count
> > + * for the found switch is incremented.
> > + */
> > +struct usb_role_switch *
> > +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
> > +{
> > + struct usb_role_switch *sw;
> > + struct device *dev;
> > +
> > + dev = class_find_device(role_class, NULL, fwnode,
> > + __switch_match_fwnode);
>
> So here you can then reuse switch_fwnode_match():
>
> dev = class_find_device(role_class, NULL, fwnode, switch_fwnode_match);
I make a fast test, it works, thanks a lot Heikki
>
> > + if (!dev)
> > + return ERR_PTR(-EPROBE_DEFER);
> > +
> > + sw = to_role_switch(dev);
> > + WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
> > +
> > + return sw;
> > +}
> > +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
> > +
> > /**
> > * usb_role_switch_put - Release handle to a switch
> > * @sw: USB Role Switch
> > diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h
> > index c05ffa6abda9..d21cd55d9e45 100644
> > --- a/include/linux/usb/role.h
> > +++ b/include/linux/usb/role.h
> > @@ -46,6 +46,8 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role);
> > enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw);
> > struct usb_role_switch *usb_role_switch_get(struct device *dev);
> > void usb_role_switch_put(struct usb_role_switch *sw);
> > +struct usb_role_switch *
> > +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode);
> >
> > struct usb_role_switch *
> > usb_role_switch_register(struct device *parent,
> > --
> > 2.20.1
>
> thanks,
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2019-04-11 3:11 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-03 2:09 [v3 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 1/6] dt-bindings: connector: add optional properties for Type-B Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 4/6] usb: roles: add API to get usb_role_switch by node Chunfeng Yun
2019-04-10 10:22 ` Heikki Krogerus
2019-04-11 3:11 ` Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 5/6] usb: roles: add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-04 16:35 ` Linus Walleij
2019-04-08 8:14 ` Chunfeng Yun
2019-04-03 2:09 ` [v3 PATCH 6/6] usb: mtu3: register a USB Role Switch for dual role mode Chunfeng Yun
2019-04-10 10:24 ` Heikki Krogerus
2019-04-11 1:05 ` Chunfeng Yun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).