* [PATCH v3 1/3] usb: gadget: udc: add USB ID signal monitoring
2017-03-30 2:16 [PATCH v3 0/3] usb: gadget: udc: renesas_usb3: add USB3.0 DRD support Yoshihiro Shimoda
@ 2017-03-30 2:16 ` Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 2/3] usb: gadget: udc: renesas_usb3: add extcon support Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap Yoshihiro Shimoda
2 siblings, 0 replies; 6+ messages in thread
From: Yoshihiro Shimoda @ 2017-03-30 2:16 UTC (permalink / raw)
To: balbi; +Cc: gregkh, linux-usb, linux-renesas-soc, Yoshihiro Shimoda
This usb 3.0 peripheral controller has a register (USB_OTG_STA) to monitor
the USB ID signal. So, this patch adds the ID signal monitoring to change
the mode to host (A-Host) or peripheral (B-Peripheral).
This patch also removes hardcoded setting as B-Peripheral mode.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
drivers/usb/gadget/udc/renesas_usb3.c | 67 ++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 2218f91..3e96c56 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -37,6 +37,9 @@
#define USB3_USB_INT_ENA_2 0x22c
#define USB3_STUP_DAT_0 0x230
#define USB3_STUP_DAT_1 0x234
+#define USB3_USB_OTG_STA 0x268
+#define USB3_USB_OTG_INT_STA 0x26c
+#define USB3_USB_OTG_INT_ENA 0x270
#define USB3_P0_MOD 0x280
#define USB3_P0_CON 0x288
#define USB3_P0_STA 0x28c
@@ -124,6 +127,9 @@
/* USB_INT_ENA_2 and USB_INT_STA_2 */
#define USB_INT_2_PIPE(n) BIT(n)
+/* USB_OTG_STA, USB_OTG_INT_STA and USB_OTG_INT_ENA */
+#define USB_OTG_IDMON BIT(4)
+
/* P0_MOD */
#define P0_MOD_DIR BIT(6)
@@ -362,10 +368,6 @@ static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
static void usb3_init_epc_registers(struct renesas_usb3 *usb3)
{
- /* FIXME: How to change host / peripheral mode as well? */
- usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON);
- usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON);
-
usb3_write(usb3, ~0, USB3_USB_INT_STA_1);
usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG);
}
@@ -538,11 +540,49 @@ static void usb3_check_vbus(struct renesas_usb3 *usb3)
}
}
+static void usb3_set_mode(struct renesas_usb3 *usb3, bool host)
+{
+ if (host)
+ usb3_clear_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON);
+ else
+ usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON);
+}
+
+static void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable)
+{
+ if (enable)
+ usb3_set_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON);
+ else
+ usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON);
+}
+
+static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
+{
+ usb3_set_mode(usb3, host);
+ usb3_vbus_out(usb3, a_dev);
+}
+
+static bool usb3_is_a_device(struct renesas_usb3 *usb3)
+{
+ return !(usb3_read(usb3, USB3_USB_OTG_STA) & USB_OTG_IDMON);
+}
+
+static void usb3_check_id(struct renesas_usb3 *usb3)
+{
+ if (usb3_is_a_device(usb3))
+ usb3_mode_config(usb3, true, true);
+ else
+ usb3_mode_config(usb3, false, false);
+}
+
static void renesas_usb3_init_controller(struct renesas_usb3 *usb3)
{
usb3_init_axi_bridge(usb3);
usb3_init_epc_registers(usb3);
+ usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_STA);
+ usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_ENA);
+ usb3_check_id(usb3);
usb3_check_vbus(usb3);
}
@@ -551,6 +591,7 @@ static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3)
usb3_disconnect(usb3);
usb3_write(usb3, 0, USB3_P0_INT_ENA);
usb3_write(usb3, 0, USB3_PN_INT_ENA);
+ usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA);
usb3_write(usb3, 0, USB3_USB_INT_ENA_1);
usb3_write(usb3, 0, USB3_USB_INT_ENA_2);
usb3_write(usb3, 0, USB3_AXI_INT_ENA);
@@ -1474,10 +1515,22 @@ static void usb3_irq_epc_int_2(struct renesas_usb3 *usb3, u32 int_sta_2)
}
}
+static void usb3_irq_idmon_change(struct renesas_usb3 *usb3)
+{
+ usb3_check_id(usb3);
+}
+
+static void usb3_irq_otg_int(struct renesas_usb3 *usb3, u32 otg_int_sta)
+{
+ if (otg_int_sta & USB_OTG_IDMON)
+ usb3_irq_idmon_change(usb3);
+}
+
static void usb3_irq_epc(struct renesas_usb3 *usb3)
{
u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1);
u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2);
+ u32 otg_int_sta = usb3_read(usb3, USB3_USB_OTG_INT_STA);
int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1);
if (int_sta_1) {
@@ -1488,6 +1541,12 @@ static void usb3_irq_epc(struct renesas_usb3 *usb3)
int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2);
if (int_sta_2)
usb3_irq_epc_int_2(usb3, int_sta_2);
+
+ otg_int_sta &= usb3_read(usb3, USB3_USB_OTG_INT_ENA);
+ if (otg_int_sta) {
+ usb3_write(usb3, otg_int_sta, USB3_USB_OTG_INT_STA);
+ usb3_irq_otg_int(usb3, otg_int_sta);
+ }
}
static irqreturn_t renesas_usb3_irq(int irq, void *_usb3)
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/3] usb: gadget: udc: renesas_usb3: add extcon support
2017-03-30 2:16 [PATCH v3 0/3] usb: gadget: udc: renesas_usb3: add USB3.0 DRD support Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 1/3] usb: gadget: udc: add USB ID signal monitoring Yoshihiro Shimoda
@ 2017-03-30 2:16 ` Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap Yoshihiro Shimoda
2 siblings, 0 replies; 6+ messages in thread
From: Yoshihiro Shimoda @ 2017-03-30 2:16 UTC (permalink / raw)
To: balbi; +Cc: gregkh, linux-usb, linux-renesas-soc, Yoshihiro Shimoda
This patch adds extcon support to see VBUS/ID signal states.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
drivers/usb/gadget/udc/Kconfig | 1 +
drivers/usb/gadget/udc/renesas_usb3.c | 43 +++++++++++++++++++++++++++++++++--
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 4b69f28..66cb00b 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -191,6 +191,7 @@ config USB_RENESAS_USBHS_UDC
config USB_RENESAS_USB3
tristate 'Renesas USB3.0 Peripheral controller'
depends on ARCH_RENESAS || COMPILE_TEST
+ depends on EXTCON
help
Renesas USB3.0 Peripheral controller is a USB peripheral controller
that supports super, high, and full speed USB 3.0 data transfers.
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 3e96c56..a1e79fc 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/extcon.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -263,6 +264,8 @@ struct renesas_usb3 {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
+ struct extcon_dev *extcon;
+ struct work_struct extcon_work;
struct renesas_usb3_ep *usb3_ep;
int num_usb3_eps;
@@ -275,6 +278,8 @@ struct renesas_usb3 {
u8 ep0_buf[USB3_EP0_BUF_SIZE];
bool softconnect;
bool workaround_for_vbus;
+ bool extcon_host; /* check id and set EXTCON_USB_HOST */
+ bool extcon_usb; /* check vbus and set EXTCON_USB */
};
#define gadget_to_renesas_usb3(_gadget) \
@@ -338,6 +343,15 @@ static int usb3_wait(struct renesas_usb3 *usb3, u32 reg, u32 mask,
return -EBUSY;
}
+static void renesas_usb3_extcon_work(struct work_struct *work)
+{
+ struct renesas_usb3 *usb3 = container_of(work, struct renesas_usb3,
+ extcon_work);
+
+ extcon_set_state_sync(usb3->extcon, EXTCON_USB_HOST, usb3->extcon_host);
+ extcon_set_state_sync(usb3->extcon, EXTCON_USB, usb3->extcon_usb);
+}
+
static void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits)
{
usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1);
@@ -533,10 +547,14 @@ static void usb3_check_vbus(struct renesas_usb3 *usb3)
if (usb3->workaround_for_vbus) {
usb3_connect(usb3);
} else {
- if (usb3_read(usb3, USB3_USB_STA) & USB_STA_VBUS_STA)
+ usb3->extcon_usb = !!(usb3_read(usb3, USB3_USB_STA) &
+ USB_STA_VBUS_STA);
+ if (usb3->extcon_usb)
usb3_connect(usb3);
else
usb3_disconnect(usb3);
+
+ schedule_work(&usb3->extcon_work);
}
}
@@ -569,10 +587,14 @@ static bool usb3_is_a_device(struct renesas_usb3 *usb3)
static void usb3_check_id(struct renesas_usb3 *usb3)
{
- if (usb3_is_a_device(usb3))
+ usb3->extcon_host = usb3_is_a_device(usb3);
+
+ if (usb3->extcon_host)
usb3_mode_config(usb3, true, true);
else
usb3_mode_config(usb3, false, false);
+
+ schedule_work(&usb3->extcon_work);
}
static void renesas_usb3_init_controller(struct renesas_usb3 *usb3)
@@ -1953,6 +1975,12 @@ static void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
};
MODULE_DEVICE_TABLE(of, usb3_of_match);
+static const unsigned int renesas_usb3_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
static int renesas_usb3_probe(struct platform_device *pdev)
{
struct renesas_usb3 *usb3;
@@ -1996,6 +2024,17 @@ static int renesas_usb3_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ INIT_WORK(&usb3->extcon_work, renesas_usb3_extcon_work);
+ usb3->extcon = devm_extcon_dev_allocate(&pdev->dev, renesas_usb3_cable);
+ if (IS_ERR(usb3->extcon))
+ return PTR_ERR(usb3->extcon);
+
+ ret = devm_extcon_dev_register(&pdev->dev, usb3->extcon);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register extcon\n");
+ return ret;
+ }
+
/* for ep0 handling */
usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL);
if (!usb3->ep0_req)
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap
2017-03-30 2:16 [PATCH v3 0/3] usb: gadget: udc: renesas_usb3: add USB3.0 DRD support Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 1/3] usb: gadget: udc: add USB ID signal monitoring Yoshihiro Shimoda
2017-03-30 2:16 ` [PATCH v3 2/3] usb: gadget: udc: renesas_usb3: add extcon support Yoshihiro Shimoda
@ 2017-03-30 2:16 ` Yoshihiro Shimoda
2017-03-30 10:36 ` Felipe Balbi
2 siblings, 1 reply; 6+ messages in thread
From: Yoshihiro Shimoda @ 2017-03-30 2:16 UTC (permalink / raw)
To: balbi; +Cc: gregkh, linux-usb, linux-renesas-soc, Yoshihiro Shimoda
This patch adds support for usb role swap via sysfs "role".
For example:
1) Connect a usb cable using 2 Salvator-X boards.
- For A-Device, the cable is connected to CN11 (USB3.0 ch0).
- For B-Device, the cable is connected to CN9 (USB2.0 ch0).
2) On A-Device, you input the following command:
# echo peripheral > /sys/devices/platform/soc/ee020000.usb/role
3) On B-Device, you input the following command:
# echo host > /sys/devices/platform/soc/ee080200.usb-phy/role
Then, the A-Device acts as a peripheral and the B-Device acts as
a host. Please note that A-Device must input the following command
if you want the board to act as a host again.
# echo host > /sys/devices/platform/soc/ee020000.usb/role
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
.../ABI/testing/sysfs-platform-renesas_usb3 | 15 ++++++
drivers/usb/gadget/udc/renesas_usb3.c | 56 ++++++++++++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-platform-renesas_usb3
diff --git a/Documentation/ABI/testing/sysfs-platform-renesas_usb3 b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
new file mode 100644
index 0000000..1f63190
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
@@ -0,0 +1,15 @@
+What: /sys/devices/platform/<udc-name>/role
+Date: March 2017
+KernelVersion: 4.13
+Contact: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Description:
+ This file can be read and write.
+ The file can show/change the drd mode of usb.
+
+ Write the following string to change the mode:
+ "host" - switching mode from peripheral to host.
+ "peripheral" - switching mode from host to peripheral.
+
+ Read the file, then it shows the following strings:
+ "host" - The mode is host now.
+ "peripheral" - The mode is peripheral now.
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index a1e79fc..5a2d845 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -372,6 +372,11 @@ static void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num)
usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
}
+static bool usb3_is_host(struct renesas_usb3 *usb3)
+{
+ return !(usb3_read(usb3, USB3_DRD_CON) & DRD_CON_PERI_CON);
+}
+
static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
{
/* Set AXI_INT */
@@ -576,8 +581,14 @@ static void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable)
static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb3->lock, flags);
usb3_set_mode(usb3, host);
usb3_vbus_out(usb3, a_dev);
+ if (!host && a_dev) /* for A-Peripheral */
+ usb3_connect(usb3);
+ spin_unlock_irqrestore(&usb3->lock, flags);
}
static bool usb3_is_a_device(struct renesas_usb3 *usb3)
@@ -1837,11 +1848,49 @@ static int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self)
.set_selfpowered = renesas_usb3_set_selfpowered,
};
+static ssize_t role_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
+ bool new_mode_is_host;
+
+ if (!usb3->driver)
+ return -ENODEV;
+
+ if (!strncmp(buf, "host", strlen("host")))
+ new_mode_is_host = true;
+ else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+ new_mode_is_host = false;
+ else
+ return -EINVAL;
+
+ if (new_mode_is_host == usb3_is_host(usb3))
+ return -EINVAL;
+
+ usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3));
+
+ return count;
+}
+
+static ssize_t role_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
+
+ if (!usb3->driver)
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral");
+}
+static DEVICE_ATTR_RW(role);
+
/*------- platform_driver ------------------------------------------------*/
static int renesas_usb3_remove(struct platform_device *pdev)
{
struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
+ device_remove_file(&pdev->dev, &dev_attr_role);
+
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -2044,6 +2093,10 @@ static int renesas_usb3_probe(struct platform_device *pdev)
if (ret < 0)
goto err_add_udc;
+ ret = device_create_file(&pdev->dev, &dev_attr_role);
+ if (ret < 0)
+ goto err_dev_create;
+
usb3->workaround_for_vbus = priv->workaround_for_vbus;
pm_runtime_enable(&pdev->dev);
@@ -2053,6 +2106,9 @@ static int renesas_usb3_probe(struct platform_device *pdev)
return 0;
+err_dev_create:
+ usb_del_gadget_udc(&usb3->gadget);
+
err_add_udc:
__renesas_usb3_ep_free_request(usb3->ep0_req);
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap
2017-03-30 2:16 ` [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap Yoshihiro Shimoda
@ 2017-03-30 10:36 ` Felipe Balbi
2017-03-31 1:58 ` Yoshihiro Shimoda
0 siblings, 1 reply; 6+ messages in thread
From: Felipe Balbi @ 2017-03-30 10:36 UTC (permalink / raw)
To: Yoshihiro Shimoda, Greg KH
Cc: gregkh, linux-usb, linux-renesas-soc, Yoshihiro Shimoda
[-- Attachment #1: Type: text/plain, Size: 5848 bytes --]
Hi,
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> writes:
> This patch adds support for usb role swap via sysfs "role".
>
> For example:
> 1) Connect a usb cable using 2 Salvator-X boards.
> - For A-Device, the cable is connected to CN11 (USB3.0 ch0).
> - For B-Device, the cable is connected to CN9 (USB2.0 ch0).
> 2) On A-Device, you input the following command:
> # echo peripheral > /sys/devices/platform/soc/ee020000.usb/role
> 3) On B-Device, you input the following command:
> # echo host > /sys/devices/platform/soc/ee080200.usb-phy/role
>
> Then, the A-Device acts as a peripheral and the B-Device acts as
> a host. Please note that A-Device must input the following command
> if you want the board to act as a host again.
> # echo host > /sys/devices/platform/soc/ee020000.usb/role
>
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> ---
> .../ABI/testing/sysfs-platform-renesas_usb3 | 15 ++++++
> drivers/usb/gadget/udc/renesas_usb3.c | 56 ++++++++++++++++++++++
> 2 files changed, 71 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-platform-renesas_usb3
>
> diff --git a/Documentation/ABI/testing/sysfs-platform-renesas_usb3 b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
> new file mode 100644
> index 0000000..1f63190
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
> @@ -0,0 +1,15 @@
> +What: /sys/devices/platform/<udc-name>/role
I have one question here. This seems to imply that platform devices have
a "role" file which is not true for all platforms devices. I really
don't have a suggestion as to how this could/should be written out,
though :-s
Greg, any suggestions?
(keeping patch below for reference only)
> +Date: March 2017
> +KernelVersion: 4.13
> +Contact: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> +Description:
> + This file can be read and write.
> + The file can show/change the drd mode of usb.
> +
> + Write the following string to change the mode:
> + "host" - switching mode from peripheral to host.
> + "peripheral" - switching mode from host to peripheral.
> +
> + Read the file, then it shows the following strings:
> + "host" - The mode is host now.
> + "peripheral" - The mode is peripheral now.
> diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
> index a1e79fc..5a2d845 100644
> --- a/drivers/usb/gadget/udc/renesas_usb3.c
> +++ b/drivers/usb/gadget/udc/renesas_usb3.c
> @@ -372,6 +372,11 @@ static void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num)
> usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
> }
>
> +static bool usb3_is_host(struct renesas_usb3 *usb3)
> +{
> + return !(usb3_read(usb3, USB3_DRD_CON) & DRD_CON_PERI_CON);
> +}
> +
> static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
> {
> /* Set AXI_INT */
> @@ -576,8 +581,14 @@ static void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable)
>
> static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
> {
> + unsigned long flags;
> +
> + spin_lock_irqsave(&usb3->lock, flags);
> usb3_set_mode(usb3, host);
> usb3_vbus_out(usb3, a_dev);
> + if (!host && a_dev) /* for A-Peripheral */
> + usb3_connect(usb3);
> + spin_unlock_irqrestore(&usb3->lock, flags);
> }
>
> static bool usb3_is_a_device(struct renesas_usb3 *usb3)
> @@ -1837,11 +1848,49 @@ static int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self)
> .set_selfpowered = renesas_usb3_set_selfpowered,
> };
>
> +static ssize_t role_store(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
> + bool new_mode_is_host;
> +
> + if (!usb3->driver)
> + return -ENODEV;
> +
> + if (!strncmp(buf, "host", strlen("host")))
> + new_mode_is_host = true;
> + else if (!strncmp(buf, "peripheral", strlen("peripheral")))
> + new_mode_is_host = false;
> + else
> + return -EINVAL;
> +
> + if (new_mode_is_host == usb3_is_host(usb3))
> + return -EINVAL;
> +
> + usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3));
> +
> + return count;
> +}
> +
> +static ssize_t role_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
> +
> + if (!usb3->driver)
> + return -ENODEV;
> +
> + return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral");
> +}
> +static DEVICE_ATTR_RW(role);
> +
> /*------- platform_driver ------------------------------------------------*/
> static int renesas_usb3_remove(struct platform_device *pdev)
> {
> struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
>
> + device_remove_file(&pdev->dev, &dev_attr_role);
> +
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
>
> @@ -2044,6 +2093,10 @@ static int renesas_usb3_probe(struct platform_device *pdev)
> if (ret < 0)
> goto err_add_udc;
>
> + ret = device_create_file(&pdev->dev, &dev_attr_role);
> + if (ret < 0)
> + goto err_dev_create;
> +
> usb3->workaround_for_vbus = priv->workaround_for_vbus;
>
> pm_runtime_enable(&pdev->dev);
> @@ -2053,6 +2106,9 @@ static int renesas_usb3_probe(struct platform_device *pdev)
>
> return 0;
>
> +err_dev_create:
> + usb_del_gadget_udc(&usb3->gadget);
> +
> err_add_udc:
> __renesas_usb3_ep_free_request(usb3->ep0_req);
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
balbi
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread* RE: [PATCH v3 3/3] usb: gadget: udc: renesas_usb3: add support for usb role swap
2017-03-30 10:36 ` Felipe Balbi
@ 2017-03-31 1:58 ` Yoshihiro Shimoda
0 siblings, 0 replies; 6+ messages in thread
From: Yoshihiro Shimoda @ 2017-03-31 1:58 UTC (permalink / raw)
To: Felipe Balbi
Cc: linux-usb@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Greg KH
Hi,
> From: Felipe Balbi, Sent: Thursday, March 30, 2017 7:37 PM
>
> Hi,
>
> Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> writes:
> > This patch adds support for usb role swap via sysfs "role".
> >
> > For example:
> > 1) Connect a usb cable using 2 Salvator-X boards.
> > - For A-Device, the cable is connected to CN11 (USB3.0 ch0).
> > - For B-Device, the cable is connected to CN9 (USB2.0 ch0).
> > 2) On A-Device, you input the following command:
> > # echo peripheral > /sys/devices/platform/soc/ee020000.usb/role
> > 3) On B-Device, you input the following command:
> > # echo host > /sys/devices/platform/soc/ee080200.usb-phy/role
> >
> > Then, the A-Device acts as a peripheral and the B-Device acts as
> > a host. Please note that A-Device must input the following command
> > if you want the board to act as a host again.
> > # echo host > /sys/devices/platform/soc/ee020000.usb/role
> >
> > Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > ---
> > .../ABI/testing/sysfs-platform-renesas_usb3 | 15 ++++++
> > drivers/usb/gadget/udc/renesas_usb3.c | 56 ++++++++++++++++++++++
> > 2 files changed, 71 insertions(+)
> > create mode 100644 Documentation/ABI/testing/sysfs-platform-renesas_usb3
> >
> > diff --git a/Documentation/ABI/testing/sysfs-platform-renesas_usb3
> b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
> > new file mode 100644
> > index 0000000..1f63190
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-platform-renesas_usb3
> > @@ -0,0 +1,15 @@
> > +What: /sys/devices/platform/<udc-name>/role
>
> I have one question here. This seems to imply that platform devices have
> a "role" file which is not true for all platforms devices. I really
> don't have a suggestion as to how this could/should be written out,
> though :-s
Thank you for the comment. I think that this "<udc-name>" is not good keyword.
Also actual name on a R-Car system (like /sys/device/platform/soc/ee020000.usb/role) is not good
because this name also seems to imply that platform devices have a "role".
So, I will change the "<udc-name>" to "<renesas_usb3's name>" as v4 patch.
Since patch 1/3 and 2/3 had merged into your testing/next branch (thanks!), I will do rebase.
Best regards,
Yoshihiro Shimoda
> Greg, any suggestions?
>
> (keeping patch below for reference only)
>
> > +Date: March 2017
> > +KernelVersion: 4.13
> > +Contact: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > +Description:
> > + This file can be read and write.
> > + The file can show/change the drd mode of usb.
> > +
> > + Write the following string to change the mode:
> > + "host" - switching mode from peripheral to host.
> > + "peripheral" - switching mode from host to peripheral.
> > +
> > + Read the file, then it shows the following strings:
> > + "host" - The mode is host now.
> > + "peripheral" - The mode is peripheral now.
> > diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
> > index a1e79fc..5a2d845 100644
> > --- a/drivers/usb/gadget/udc/renesas_usb3.c
> > +++ b/drivers/usb/gadget/udc/renesas_usb3.c
> > @@ -372,6 +372,11 @@ static void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num)
> > usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
> > }
> >
> > +static bool usb3_is_host(struct renesas_usb3 *usb3)
> > +{
> > + return !(usb3_read(usb3, USB3_DRD_CON) & DRD_CON_PERI_CON);
> > +}
> > +
> > static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
> > {
> > /* Set AXI_INT */
> > @@ -576,8 +581,14 @@ static void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable)
> >
> > static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
> > {
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&usb3->lock, flags);
> > usb3_set_mode(usb3, host);
> > usb3_vbus_out(usb3, a_dev);
> > + if (!host && a_dev) /* for A-Peripheral */
> > + usb3_connect(usb3);
> > + spin_unlock_irqrestore(&usb3->lock, flags);
> > }
> >
> > static bool usb3_is_a_device(struct renesas_usb3 *usb3)
> > @@ -1837,11 +1848,49 @@ static int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self)
> > .set_selfpowered = renesas_usb3_set_selfpowered,
> > };
> >
> > +static ssize_t role_store(struct device *dev, struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
> > + bool new_mode_is_host;
> > +
> > + if (!usb3->driver)
> > + return -ENODEV;
> > +
> > + if (!strncmp(buf, "host", strlen("host")))
> > + new_mode_is_host = true;
> > + else if (!strncmp(buf, "peripheral", strlen("peripheral")))
> > + new_mode_is_host = false;
> > + else
> > + return -EINVAL;
> > +
> > + if (new_mode_is_host == usb3_is_host(usb3))
> > + return -EINVAL;
> > +
> > + usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3));
> > +
> > + return count;
> > +}
> > +
> > +static ssize_t role_show(struct device *dev, struct device_attribute *attr,
> > + char *buf)
> > +{
> > + struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
> > +
> > + if (!usb3->driver)
> > + return -ENODEV;
> > +
> > + return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral");
> > +}
> > +static DEVICE_ATTR_RW(role);
> > +
> > /*------- platform_driver ------------------------------------------------*/
> > static int renesas_usb3_remove(struct platform_device *pdev)
> > {
> > struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
> >
> > + device_remove_file(&pdev->dev, &dev_attr_role);
> > +
> > pm_runtime_put(&pdev->dev);
> > pm_runtime_disable(&pdev->dev);
> >
> > @@ -2044,6 +2093,10 @@ static int renesas_usb3_probe(struct platform_device *pdev)
> > if (ret < 0)
> > goto err_add_udc;
> >
> > + ret = device_create_file(&pdev->dev, &dev_attr_role);
> > + if (ret < 0)
> > + goto err_dev_create;
> > +
> > usb3->workaround_for_vbus = priv->workaround_for_vbus;
> >
> > pm_runtime_enable(&pdev->dev);
> > @@ -2053,6 +2106,9 @@ static int renesas_usb3_probe(struct platform_device *pdev)
> >
> > return 0;
> >
> > +err_dev_create:
> > + usb_del_gadget_udc(&usb3->gadget);
> > +
> > err_add_udc:
> > __renesas_usb3_ep_free_request(usb3->ep0_req);
> >
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> --
> balbi
^ permalink raw reply [flat|nested] 6+ messages in thread