diff options
author | Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | 2017-03-30 05:16:04 +0300 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2017-04-11 10:58:23 +0300 |
commit | 77172a1f886a696bab5b4d3006ccf55ee4b1bfe5 (patch) | |
tree | 6c657cfa82832ea70785e3c745414c14ac8e0fa4 /drivers/usb/gadget | |
parent | e92634cd4d37d5a2ea2fb0d55d25d50bbba1e8e0 (diff) | |
download | linux-77172a1f886a696bab5b4d3006ccf55ee4b1bfe5.tar.xz |
usb: gadget: udc: renesas_usb3: add USB ID signal monitoring
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>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/udc/renesas_usb3.c | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 2218f91e92a6..3e96c56bc06e 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) |